Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d3fd3c2b0d | |||
| 5c18e2ccbc | |||
| 1dba1e0674 | |||
| 0e08e518c4 | |||
| 7d9b7f14e8 | |||
| 6943088df1 | |||
| 7ffc191f66 | |||
| 46a6222959 | |||
| 7c5bc44724 | |||
| c1abf2cdcd | |||
| 78d5e74c6f | |||
| d4a5e83a87 | |||
| f179907a3a | |||
| 4ee11c29c9 | |||
| 6736bfbde5 | |||
| ef1261e349 | |||
| 03f4b1b773 | |||
| a1de143ae8 | |||
| ecebc42603 |
76
.gitignore
vendored
@@ -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
@@ -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 ()
|
||||||
99
README.md
@@ -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!
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|||||||
155
README_ZH.md
@@ -1,155 +0,0 @@
|
|||||||
# Super Script Materializer
|
|
||||||
|
|
||||||
[English document](./README.md)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 简介
|
|
||||||
|
|
||||||
超级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。以及说明文档翻译上的帮助。
|
|
||||||
14
SuperScriptDecorator/.vscode/launch.json
vendored
@@ -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
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
@@ -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()
|
|
||||||
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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]))
|
|
||||||
@@ -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()
|
|
||||||
@@ -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()
|
|
||||||
|
|
||||||
|
|
||||||
@@ -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()
|
|
||||||
@@ -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.')
|
|
||||||
|
|
||||||
@@ -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
|
|
||||||
@@ -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>
|
|
||||||
@@ -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>
|
|
||||||
@@ -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>
|
|
||||||
@@ -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
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
#ifdef APSTUDIO_INVOKED
|
|
||||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
|
||||||
#define _APS_NEXT_RESOURCE_VALUE 10003
|
|
||||||
#define _APS_NEXT_COMMAND_VALUE 32771
|
|
||||||
#define _APS_NEXT_CONTROL_VALUE 10000
|
|
||||||
#define _APS_NEXT_SYMED_VALUE 10000
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
@@ -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
|
|
||||||
@@ -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] = '=';
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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.";
|
|
||||||
//}
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
import CustomConfig
|
|
||||||
|
|
||||||
class EmptyDatabase:
|
|
||||||
def __init__(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def CreateDatabase():
|
|
||||||
return EmptyDatabase()
|
|
||||||
|
|
||||||
def CloseDatabase(db):
|
|
||||||
pass
|
|
||||||
@@ -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()
|
|
||||||
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
import ServerCore
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import getopt
|
|
||||||
import logging
|
|
||||||
|
|
||||||
# todo: load db and cfg
|
|
||||||
|
|
||||||
# todo: start flask
|
|
||||||
ServerCore.run()
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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>
|
|
||||||
@@ -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>
|
|
||||||
@@ -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>
|
|
||||||
@@ -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 |
@@ -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 |
@@ -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 |
|
Before Width: | Height: | Size: 13 KiB |
@@ -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 |
@@ -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 |
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -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');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
@@ -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();
|
|
||||||
}
|
|
||||||
@@ -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]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -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>
|
|
||||||
@@ -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>
|
|
||||||
@@ -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"> </th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td style="width: 100px;" align="left"><button style="width: 50px;" onclick="doConv1_I2O();">v</button></td>
|
|
||||||
<td style="width: 150px;"> </td>
|
|
||||||
<td style="width: 100px;" align="right"> </td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th colspan="2"> </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"> </th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td style="width: 100px;" align="left"><button style="width: 50px;" onclick="doConv2_I2O();">v</button></td>
|
|
||||||
<td style="width: 150px;"> </td>
|
|
||||||
<td style="width: 100px;" align="right"><button style="width: 50px;" onclick="doConv2_O2I();">^</button></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th colspan="2"> </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"> </th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td style="width: 100px;" align="left"><button style="width: 50px;" onclick="doConv3_I2O();">v</button></td>
|
|
||||||
<td style="width: 150px;"> </td>
|
|
||||||
<td style="width: 100px;" align="right"><button style="width: 50px;" onclick="doConv3_O2I();">^</button></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th colspan="2"> </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"> </th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td style="width: 100px;" align="left"><button style="width: 50px;" onclick="doConv4_I2O();">v</button></td>
|
|
||||||
<td style="width: 150px;"> </td>
|
|
||||||
<td style="width: 100px;" align="right"><button style="width: 50px;" onclick="doConv4_O2I();">^</button></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th colspan="2"> </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>
|
|
||||||
@@ -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 }}, "{{ item.queryKey }}");">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>
|
|
||||||
@@ -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>
|
|
||||||
@@ -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 %}
|
|
||||||
@@ -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">>></p>
|
|
||||||
<p class="hamburger"><a href="{{ "/viewer%s"|format(i.path) }}">{{ i.name|e }}</a></p>
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
<p class="hamburger">>></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("plink");">Show pLink and eLink</input>
|
|
||||||
</p>
|
|
||||||
<p style="margin: 5px;">Action:<br />
|
|
||||||
<input type="checkbox" id="sidepanel-display-properties" value="1" onclick="settingChange("properties");">Interactive property inspector</input><br />
|
|
||||||
<input type="checkbox" id="sidepanel-display-highlight" value="1" onclick="settingChange("highlight");">Highlight focused object</input><br />
|
|
||||||
<input type="checkbox" id="sidepanel-display-move" value="1" onclick="settingChange("move");" 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("/help");">Help</button><br />
|
|
||||||
<button style="height: 30px; margin: 10px 0 10px 0;" onclick="window.open("/about");">About</button>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
35
cmake/custom_import_sqlite.cmake
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
if (WIN32)
|
||||||
|
# In Windows, we use custom way to import SQLite.
|
||||||
|
# Before using this CMake file in Windows, you should do following steps first.
|
||||||
|
# 1. Get SQLite SDK (amalgamation) and binaries (sqlite-dll) from http://www.sqlite.org/
|
||||||
|
# 2. Extract SQLite SDK and binaries to your preferred directory.
|
||||||
|
# 3. Open Developer Command Prompt for Visual Studio (embedded with Visual Studio installation)
|
||||||
|
# 4. Use `cd` command to switch work directory to the directory where you extract binaries.
|
||||||
|
# 5. Execute `lib /DEF:sqlite3.def /OUT:sqlite3.lib /MACHINE:x86` (`x86` is the architecture of your SQLite3, you may change it according to your requirement).
|
||||||
|
# 6. Now you have a generated LIB file for MSVC linking.
|
||||||
|
|
||||||
|
# Check SQLite path variable
|
||||||
|
if (NOT DEFINED SQLITE_AMALGAMATION_PATH)
|
||||||
|
message(FATAL_ERROR "You must set SQLITE_AMALGAMATION_PATH to the directory where the SQLite3 header file locate.")
|
||||||
|
endif()
|
||||||
|
if (NOT DEFINED SQLITE_DLL_PATH)
|
||||||
|
message(FATAL_ERROR "You must set SQLITE_DLL_PATH to the directory where the generated SQLite3 LIB file locate for linking.")
|
||||||
|
endif()
|
||||||
|
# Add imported library
|
||||||
|
add_library(SQLite3 INTERFACE IMPORTED)
|
||||||
|
# Add alias for it to let it has the same behavior with CMake imported SQLite3.
|
||||||
|
add_library(SQLite3::SQLite3 ALIAS SQLite3)
|
||||||
|
# Setup header files
|
||||||
|
set_target_properties(SQLite3 PROPERTIES
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES
|
||||||
|
"${SQLITE_AMALGAMATION_PATH}"
|
||||||
|
)
|
||||||
|
# Setup lib files
|
||||||
|
set_target_properties(SQLite3 PROPERTIES
|
||||||
|
INTERFACE_LINK_LIBRARIES
|
||||||
|
"${SQLITE_DLL_PATH}/sqlite3.lib"
|
||||||
|
)
|
||||||
|
else ()
|
||||||
|
# In non-Windows, we simply import SQLite3 from CMake preset.
|
||||||
|
find_package(SQLite3 REQUIRED)
|
||||||
|
endif ()
|
||||||
15
cmake/custom_import_yycc.cmake
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
# Check YYCC path environment variable
|
||||||
|
if (NOT DEFINED YYCC_PATH)
|
||||||
|
message(FATAL_ERROR "You must set YYCC_PATH variable to one of YYCC CMake distribution installation path.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Find YYCC library
|
||||||
|
# It will produce YYCC::YYCCommonplace target for including and linking.
|
||||||
|
#
|
||||||
|
# Please note we MUST set CMake variable YYCCommonplace_ROOT to make sure CMake can found YYCC in out given path.
|
||||||
|
# The cache status of YYCCommonplace_ROOT is doesn't matter.
|
||||||
|
# CMake will throw error if we use HINTS feature in find_package to find YYCC.
|
||||||
|
set(YYCCommonplace_ROOT ${YYCC_PATH} CACHE PATH
|
||||||
|
"The path to YYCC CMake distribution installation path.")
|
||||||
|
find_package(YYCCommonplace REQUIRED)
|
||||||
126
cmake/init_materializer_env.cmake
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
# ========== Check Basic Environment ==========
|
||||||
|
# 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 Materializer Variables ==========
|
||||||
|
# Check build type
|
||||||
|
set(MATERIALIZER_BUILD_TYPES
|
||||||
|
"plugin" "standalone"
|
||||||
|
)
|
||||||
|
if (MATERIALIZER_BUILD_TYPE IN_LIST MATERIALIZER_BUILD_TYPES)
|
||||||
|
message( "VirtoolsSchematicWeaver::Materializer build type: ${MATERIALIZER_BUILD_TYPE}")
|
||||||
|
else ()
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"VirtoolsSchematicWeaver::Materializer do not have correct type."
|
||||||
|
"Please assign a legal value (\"plugin\" or \"standalone\") to MATERIALIZER_BUILD_TYPE."
|
||||||
|
)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
# ========== Check Virtools Variables ==========
|
||||||
|
# Check Virtools version variable
|
||||||
|
set(VIRTOOLS_VERSIONS "21" "25" "30" "35" "40" "50")
|
||||||
|
if (VIRTOOLS_VERSION IN_LIST 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()
|
||||||
|
|
||||||
|
# Check the combination between materializer build type and Virtools version
|
||||||
|
set(STANDALONE_MATERIALIZER_SUPPORTED_VT "21" "25" "30" "35" "40" "50")
|
||||||
|
set(PLUGIN_MATERIALIZER_SUPPORTED_VT "30" "35" "40" "50")
|
||||||
|
if (MATERIALIZER_BUILD_TYPE STREQUAL "plugin")
|
||||||
|
if (NOT (VIRTOOLS_VERSION IN_LIST PLUGIN_MATERIALIZER_SUPPORTED_VT))
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"The combination between build type ${MATERIALIZER_BUILD_TYPE} and Virtools version ${VIRTOOLS_VERSION} is not compatible."
|
||||||
|
"Please view our README for a legal combination."
|
||||||
|
)
|
||||||
|
endif ()
|
||||||
|
else ()
|
||||||
|
if (NOT (VIRTOOLS_VERSION IN_LIST STANDALONE_MATERIALIZER_SUPPORTED_VT))
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"The combination between build type ${MATERIALIZER_BUILD_TYPE} and Virtools version ${VIRTOOLS_VERSION} is not compatible."
|
||||||
|
"Please view our README for a legal combination."
|
||||||
|
)
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
# ========== Import library ==========
|
||||||
|
|
||||||
|
# Build essential variables
|
||||||
|
# Virtools header path
|
||||||
|
if (VIRTOOLS_VERSION STREQUAL "21")
|
||||||
|
set(VIRTOOLS_HEADER_PATH ${VIRTOOLS_PATH}/Include) # 2.1
|
||||||
|
elseif (VIRTOOLS_VERSION STREQUAL "25")
|
||||||
|
set(VIRTOOLS_HEADER_PATH ${VIRTOOLS_PATH}/Virtools_SDK/Includes) # 2.5
|
||||||
|
else ()
|
||||||
|
set(VIRTOOLS_HEADER_PATH ${VIRTOOLS_PATH}/Sdk/Includes) # 3.0, 3.5, 4.0, 5.0
|
||||||
|
endif ()
|
||||||
|
# Virtools lib path
|
||||||
|
if (VIRTOOLS_VERSION STREQUAL "21")
|
||||||
|
set(VIRTOOLS_LIB_PATH ${VIRTOOLS_PATH}/Lib) # 2.1
|
||||||
|
elseif (VIRTOOLS_VERSION STREQUAL "25")
|
||||||
|
set(VIRTOOLS_LIB_PATH ${VIRTOOLS_PATH}/Virtools_SDK/Lib) # 2.5
|
||||||
|
elseif (VIRTOOLS_VERSION STREQUAL "30")
|
||||||
|
set(VIRTOOLS_LIB_PATH ${VIRTOOLS_PATH}/Sdk/Lib) # 3.0
|
||||||
|
else ()
|
||||||
|
set(VIRTOOLS_LIB_PATH ${VIRTOOLS_PATH}/Sdk/Lib/Win32/Release) # 3.5, 4.0, 5.0
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
# Real importer
|
||||||
|
add_library(VirtoolsSDK INTERFACE IMPORTED)
|
||||||
|
# Setup header files
|
||||||
|
set_target_properties(VirtoolsSDK PROPERTIES
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES
|
||||||
|
"${VIRTOOLS_HEADER_PATH}"
|
||||||
|
)
|
||||||
|
# Setup lib files
|
||||||
|
set(VirtoolsSDK_LIBS_LIST
|
||||||
|
# Both standalone and plugin build type needed
|
||||||
|
"${VIRTOOLS_LIB_PATH}/CK2.lib"
|
||||||
|
"${VIRTOOLS_LIB_PATH}/VxMath.lib"
|
||||||
|
# Pugin build type only libraries
|
||||||
|
"$<$<STREQUAL:${MATERIALIZER_BUILD_TYPE},plugin>:${VIRTOOLS_LIB_PATH}/DllEditor.lib>"
|
||||||
|
"$<$<STREQUAL:${MATERIALIZER_BUILD_TYPE},plugin>:${VIRTOOLS_LIB_PATH}/InterfaceControls.lib>"
|
||||||
|
"$<$<STREQUAL:${MATERIALIZER_BUILD_TYPE},plugin>:${VIRTOOLS_LIB_PATH}/CKControls.lib>"
|
||||||
|
# Virtools 5.0 special
|
||||||
|
"$<$<STREQUAL:${VIRTOOLS_VERSION},50>:${VIRTOOLS_LIB_PATH}/CKKernelInit.lib>"
|
||||||
|
)
|
||||||
|
set_target_properties(VirtoolsSDK PROPERTIES
|
||||||
|
INTERFACE_LINK_LIBRARIES "${VirtoolsSDK_LIBS_LIST}"
|
||||||
|
)
|
||||||
|
# Setup compile macros
|
||||||
|
target_compile_definitions(VirtoolsSDK
|
||||||
|
INTERFACE
|
||||||
|
# Virtools version macro
|
||||||
|
"VIRTOOLS_${VIRTOOLS_VERSION}"
|
||||||
|
# Virtools 5.0 standalone mode need an extra macro
|
||||||
|
"$<$<AND:$<STREQUAL:${MATERIALIZER_BUILD_TYPE},standalone>,$<STREQUAL:${VIRTOOLS_VERSION},50>>:VIRTOOLS_USER_SDK>"
|
||||||
|
)
|
||||||
|
# Setup compiler options
|
||||||
|
target_compile_options(VirtoolsSDK
|
||||||
|
INTERFACE
|
||||||
|
# Permissive mode ordered.
|
||||||
|
"/permissive"
|
||||||
|
)
|
||||||
|
|
||||||
51
decorator/CMakeLists.txt
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
# Create executable
|
||||||
|
add_executable(VSWDecorator "")
|
||||||
|
# Setup source files
|
||||||
|
target_sources(VSWDecorator
|
||||||
|
PRIVATE
|
||||||
|
# Sources
|
||||||
|
main.cpp
|
||||||
|
)
|
||||||
|
# Setup header files
|
||||||
|
target_sources(VSWDecorator
|
||||||
|
PRIVATE
|
||||||
|
FILE_SET HEADERS
|
||||||
|
FILES
|
||||||
|
# Headers
|
||||||
|
)
|
||||||
|
# Setup header infomations
|
||||||
|
target_include_directories(VSWDecorator
|
||||||
|
PUBLIC
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}
|
||||||
|
)
|
||||||
|
# Setup linked library
|
||||||
|
target_link_libraries(VSWDecorator
|
||||||
|
PRIVATE
|
||||||
|
YYCC::YYCCommonplace
|
||||||
|
SQLite3::SQLite3
|
||||||
|
VSWShared
|
||||||
|
)
|
||||||
|
# Setup C++ standard
|
||||||
|
set_target_properties(VSWDecorator
|
||||||
|
PROPERTIES
|
||||||
|
CXX_STANDARD 17
|
||||||
|
CXX_STANDARD_REQUIRED 17
|
||||||
|
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
@@ -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自动完成相关操作。
|
|
||||||
|
|
||||||
@@ -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: 贴上链接
|
|
||||||
@@ -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_behavior:behavior本身,包括behavior graph和prototype behavior之类的
|
|
||||||
- script_bIn:behavior的行为输入
|
|
||||||
- script_bOut:behavior的行为输出
|
|
||||||
- script_eLink:export link
|
|
||||||
- script_pAttr:attribute类型的parameter
|
|
||||||
- script_pIn:behavior的parameter输入
|
|
||||||
- script_pLink:parameter link
|
|
||||||
- script_pLocal:local parameter
|
|
||||||
- script_pOper:parameter operator
|
|
||||||
- script_pOut:behavior的parameter输出
|
|
||||||
- script_pTarget:behavior的target输入,实际上是一个特殊的parameter输入
|
|
||||||
- msg:文档内定义的message标号与数值的对应
|
|
||||||
- array:文档里的每个CKDataArray
|
|
||||||
- array_header:CKDataArray的表头
|
|
||||||
- array_cell:CKDataArray的数据体
|
|
||||||
- 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为bIn,1为bOut|
|
|
||||||
|input_index|INTEGER|指示连线位于输入端所在Behavior的第几个bIO口|
|
|
||||||
|output_obj|INTEGER|输出端所属Behavior的`CK_ID`|
|
|
||||||
|output_type|INTEGER|指示输出端类型,0为bIn,1为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只能链接pIn,pOut只能链接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`使用下列数值:
|
|
||||||
|
|
||||||
* pIn:0
|
|
||||||
* pOut:1
|
|
||||||
* pLocal:2
|
|
||||||
* pTarget:3
|
|
||||||
* pAttr:4
|
|
||||||
|
|
||||||
当其值不是`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`描述,因为对于一个Behavior,pTarget至多只能有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`里综合一次即可
|
|
||||||
|
|
||||||
表列表:
|
|
||||||
|
|
||||||
- attr:attribute
|
|
||||||
- op:operator,parameter转换的定义
|
|
||||||
- param:parameter的定义
|
|
||||||
- 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`输出的脚本综合的数据库,包含了所有脚本的连线和图形位置。
|
|
||||||
|
|
||||||
表列表:
|
|
||||||
|
|
||||||
- block:behavior的图形结构
|
|
||||||
- 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综合
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
Ballance/vt2obj "example.nmo" "export.db" "env.db"
|
|
||||||
"Ballance/vt2obj mirror" Gameplay.nmo export.db env.db
|
|
||||||
103
materializer/CMakeLists.txt
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
# Try to initialize build environment
|
||||||
|
include(${CMAKE_CURRENT_LIST_DIR}/../cmake/init_materializer_env.cmake)
|
||||||
|
|
||||||
|
# Create library or executable according to build type
|
||||||
|
if (MATERIALIZER_BUILD_TYPE STREQUAL "plugin")
|
||||||
|
add_library(VSWMaterializer SHARED "")
|
||||||
|
else ()
|
||||||
|
add_executable(VSWMaterializer "")
|
||||||
|
endif ()
|
||||||
|
# Setup source files
|
||||||
|
target_sources(VSWMaterializer
|
||||||
|
PRIVATE
|
||||||
|
# Sources
|
||||||
|
# Main
|
||||||
|
main.cpp
|
||||||
|
PluginMain.cpp
|
||||||
|
StandaloneMain.cpp
|
||||||
|
# Exporter
|
||||||
|
ExportDocument.cpp
|
||||||
|
ExportEnvironment.cpp
|
||||||
|
ExportScript.cpp
|
||||||
|
# Utilities
|
||||||
|
Utilities.cpp
|
||||||
|
Database.cpp
|
||||||
|
# MFC parts
|
||||||
|
ExportDialog.cpp
|
||||||
|
# Resources file
|
||||||
|
"$<$<STREQUAL:${MATERIALIZER_BUILD_TYPE},plugin>:Materializer.rc>"
|
||||||
|
# Defination file
|
||||||
|
"$<$<STREQUAL:${MATERIALIZER_BUILD_TYPE},plugin>:Materializer.def>"
|
||||||
|
)
|
||||||
|
# Setup header files
|
||||||
|
target_sources(VSWMaterializer
|
||||||
|
PRIVATE
|
||||||
|
FILE_SET HEADERS
|
||||||
|
FILES
|
||||||
|
# Headers
|
||||||
|
# Misc
|
||||||
|
stdafx.hpp
|
||||||
|
# Main
|
||||||
|
PluginMain.hpp
|
||||||
|
StandaloneMain.hpp
|
||||||
|
# Exporter
|
||||||
|
ExportCore.hpp
|
||||||
|
# Utilities
|
||||||
|
Utilities.hpp
|
||||||
|
Database.hpp
|
||||||
|
DataTypes.hpp
|
||||||
|
# MFC Parts
|
||||||
|
resource.h
|
||||||
|
ExportDialog.hpp
|
||||||
|
)
|
||||||
|
# Setup header infomations
|
||||||
|
target_include_directories(VSWMaterializer
|
||||||
|
PRIVATE
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}
|
||||||
|
)
|
||||||
|
# Setup linked library
|
||||||
|
target_link_libraries(VSWMaterializer
|
||||||
|
PRIVATE
|
||||||
|
YYCC::YYCCommonplace
|
||||||
|
SQLite3::SQLite3
|
||||||
|
VirtoolsSDK
|
||||||
|
VSWShared
|
||||||
|
)
|
||||||
|
# Setup C++ standard (we require C++ 17 because Virtools can hold more higher C++ standard)
|
||||||
|
set_target_properties(VSWMaterializer
|
||||||
|
PROPERTIES
|
||||||
|
CXX_STANDARD 17
|
||||||
|
CXX_STANDARD_REQUIRED 17
|
||||||
|
CXX_EXTENSION OFF
|
||||||
|
)
|
||||||
|
# Setup MFC used in shared library
|
||||||
|
if (MATERIALIZER_BUILD_TYPE STREQUAL "plugin")
|
||||||
|
set_target_properties(VSWMaterializer
|
||||||
|
PROPERTIES
|
||||||
|
CMAKE_MFC_FLAG 2
|
||||||
|
)
|
||||||
|
endif ()
|
||||||
|
# MSVC specific correction
|
||||||
|
target_compile_definitions(VSWMaterializer
|
||||||
|
PRIVATE
|
||||||
|
# MFC macro
|
||||||
|
_AFXDLL
|
||||||
|
# Materializer build type
|
||||||
|
"MATERIALIZER_$<UPPER_CASE:${MATERIALIZER_BUILD_TYPE}>"
|
||||||
|
# Materializer debug or release
|
||||||
|
"$<$<CONFIG:Debug>:MATERIALIZER_DEBUG>"
|
||||||
|
"$<$<CONFIG:Release,RelWithDebInfo,MinSizeRel>:MATERIALIZER_DEBUG>"
|
||||||
|
# Multibyte encoding
|
||||||
|
$<$<CXX_COMPILER_ID:MSVC>:MBCS>
|
||||||
|
$<$<CXX_COMPILER_ID:MSVC>:_MBCS>
|
||||||
|
)
|
||||||
|
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}
|
||||||
|
)
|
||||||
308
materializer/DataTypes.hpp
Normal file
@@ -0,0 +1,308 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "stdafx.hpp"
|
||||||
|
#include <GenericHelper.hpp>
|
||||||
|
|
||||||
|
namespace VSW::Materializer::DataTypes {
|
||||||
|
|
||||||
|
struct BlobDescriptor {
|
||||||
|
const void* ptr;
|
||||||
|
int length;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace Script {
|
||||||
|
|
||||||
|
struct Table_script {
|
||||||
|
CK_ID beobj;
|
||||||
|
YYCC::yycc_u8string beobj_name;
|
||||||
|
int behavior_index;
|
||||||
|
CK_ID behavior;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Table_behavior {
|
||||||
|
CK_ID thisobj;
|
||||||
|
YYCC::yycc_u8string name;
|
||||||
|
CK_BEHAVIOR_TYPE type;
|
||||||
|
YYCC::yycc_u8string proto_name;
|
||||||
|
int64_t proto_guid;
|
||||||
|
CK_BEHAVIOR_FLAGS flags;
|
||||||
|
int priority;
|
||||||
|
CKDWORD version;
|
||||||
|
int pin_count_ptarget;
|
||||||
|
int pin_count_pin;
|
||||||
|
int pin_count_pout;
|
||||||
|
int pin_count_bin;
|
||||||
|
int pin_count_bout;
|
||||||
|
CK_ID parent;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Table_bIO {
|
||||||
|
CK_ID thisobj;
|
||||||
|
int index;
|
||||||
|
YYCC::yycc_u8string name;
|
||||||
|
CK_ID parent;
|
||||||
|
};
|
||||||
|
struct Table_bIn : public Table_bIO {};
|
||||||
|
struct Table_bOut : public Table_bIO {};
|
||||||
|
|
||||||
|
struct Table_pTarget {
|
||||||
|
CK_ID thisobj;
|
||||||
|
YYCC::yycc_u8string name;
|
||||||
|
int64_t type;
|
||||||
|
CK_ID parent;
|
||||||
|
CK_ID direct_source;
|
||||||
|
CK_ID shared_source;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Table_pIn {
|
||||||
|
CK_ID thisobj;
|
||||||
|
int index;
|
||||||
|
YYCC::yycc_u8string name;
|
||||||
|
int64_t type;
|
||||||
|
CK_ID parent;
|
||||||
|
CK_ID direct_source;
|
||||||
|
CK_ID shared_source;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Table_pOut {
|
||||||
|
CK_ID thisobj;
|
||||||
|
int index;
|
||||||
|
YYCC::yycc_u8string name;
|
||||||
|
int64_t type;
|
||||||
|
CK_ID parent;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Table_bLink {
|
||||||
|
CK_ID input;
|
||||||
|
CK_ID output;
|
||||||
|
int delay;
|
||||||
|
CK_ID parent;
|
||||||
|
|
||||||
|
// additional field
|
||||||
|
CK_ID input_obj;
|
||||||
|
VSW::DataTypes::BehaviorLinkIOType input_type;
|
||||||
|
int input_index;
|
||||||
|
CK_ID output_obj;
|
||||||
|
VSW::DataTypes::BehaviorLinkIOType output_type;
|
||||||
|
int output_index;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Table_pLocal {
|
||||||
|
CK_ID thisobj;
|
||||||
|
YYCC::yycc_u8string name;
|
||||||
|
int64_t type;
|
||||||
|
bool is_setting;
|
||||||
|
CK_ID parent;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Table_pAttr {
|
||||||
|
CK_ID thisobj;
|
||||||
|
YYCC::yycc_u8string name;
|
||||||
|
int64_t type;
|
||||||
|
CK_ID owner;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Table_pLink {
|
||||||
|
// Basic infos
|
||||||
|
CK_ID parent;
|
||||||
|
// Input infos
|
||||||
|
CK_ID input;
|
||||||
|
CK_ID input_obj;
|
||||||
|
VSW::DataTypes::ParameterLinkIOType input_type;
|
||||||
|
bool input_is_bb;
|
||||||
|
int input_index;
|
||||||
|
// Output infos
|
||||||
|
CK_ID output;
|
||||||
|
CK_ID output_obj;
|
||||||
|
VSW::DataTypes::ParameterLinkIOType output_type;
|
||||||
|
bool output_is_bb;
|
||||||
|
int output_index;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Table_pOper {
|
||||||
|
CK_ID thisobj;
|
||||||
|
int64_t op;
|
||||||
|
CK_ID parent;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Table_eLink {
|
||||||
|
CK_ID export_obj;
|
||||||
|
CK_ID internal_obj;
|
||||||
|
bool is_in;
|
||||||
|
int index;
|
||||||
|
CK_ID parent;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Table_data {
|
||||||
|
YYCC::yycc_u8string field;
|
||||||
|
BlobDescriptor data;
|
||||||
|
CK_ID parent;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DataCache {
|
||||||
|
public:
|
||||||
|
DataCache() :
|
||||||
|
script(), behavior(),
|
||||||
|
bIn(), bOut(), bLink(),
|
||||||
|
pOper(),
|
||||||
|
pIn(), pOut(), pLocal(), pAttr(), pTarget(), pLink(),
|
||||||
|
eLink(),
|
||||||
|
data() {}
|
||||||
|
~DataCache() {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
Table_script script;
|
||||||
|
Table_behavior behavior;
|
||||||
|
Table_bIn bIn;
|
||||||
|
Table_bOut bOut;
|
||||||
|
Table_pIn pIn;
|
||||||
|
Table_pOut pOut;
|
||||||
|
Table_bLink bLink;
|
||||||
|
Table_pLocal pLocal;
|
||||||
|
Table_pAttr pAttr;
|
||||||
|
Table_pLink pLink;
|
||||||
|
Table_pOper pOper;
|
||||||
|
Table_eLink eLink;
|
||||||
|
Table_pTarget pTarget;
|
||||||
|
Table_data data;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Document {
|
||||||
|
|
||||||
|
struct Table_msg {
|
||||||
|
CKMessageType index;
|
||||||
|
YYCC::yycc_u8string name;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Table_obj {
|
||||||
|
CK_ID id;
|
||||||
|
YYCC::yycc_u8string name;
|
||||||
|
CK_CLASSID classid;
|
||||||
|
YYCC::yycc_u8string classid_name;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DataCache {
|
||||||
|
public:
|
||||||
|
DataCache() : msg(), obj() {}
|
||||||
|
~DataCache() {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
Table_msg msg;
|
||||||
|
Table_obj obj;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Environment {
|
||||||
|
|
||||||
|
struct Table_op {
|
||||||
|
YYCC::yycc_u8string func_ptr;
|
||||||
|
int64_t in1_guid;
|
||||||
|
int64_t in2_guid;
|
||||||
|
int64_t out_guid;
|
||||||
|
int64_t op_guid;
|
||||||
|
YYCC::yycc_u8string op_name;
|
||||||
|
CKOperationType op_code;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Table_param {
|
||||||
|
// Parameter infos
|
||||||
|
CKParameterType index;
|
||||||
|
int64_t guid;
|
||||||
|
int64_t derived_from;
|
||||||
|
YYCC::yycc_u8string name;
|
||||||
|
int default_size;
|
||||||
|
YYCC::yycc_u8string func_CreateDefault;
|
||||||
|
YYCC::yycc_u8string func_Delete;
|
||||||
|
YYCC::yycc_u8string func_SaveLoad;
|
||||||
|
YYCC::yycc_u8string func_Check;
|
||||||
|
YYCC::yycc_u8string func_Copy;
|
||||||
|
YYCC::yycc_u8string func_String;
|
||||||
|
YYCC::yycc_u8string func_UICreator;
|
||||||
|
// Dll infos
|
||||||
|
YYCC::yycc_u8string dll_name;
|
||||||
|
int dll_index;
|
||||||
|
int position_in_dll;
|
||||||
|
// Misc
|
||||||
|
CKDWORD flags;
|
||||||
|
CKDWORD dw_param;
|
||||||
|
CKDWORD cid;
|
||||||
|
int64_t saver_manager;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Table_attr {
|
||||||
|
CKAttributeType index;
|
||||||
|
YYCC::yycc_u8string name;
|
||||||
|
CKAttributeCategory category_index;
|
||||||
|
YYCC::yycc_u8string category_name;
|
||||||
|
CK_ATTRIBUT_FLAGS flags;
|
||||||
|
CKParameterType param_index;
|
||||||
|
int64_t param_guid;
|
||||||
|
CK_CLASSID compatible_classid;
|
||||||
|
YYCC::yycc_u8string default_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Table_plugin {
|
||||||
|
// Category
|
||||||
|
YYCC::yycc_u8string category_name;
|
||||||
|
int category_index;
|
||||||
|
// Dll infos
|
||||||
|
YYCC::yycc_u8string dll_name;
|
||||||
|
int dll_index;
|
||||||
|
int position_in_dll;
|
||||||
|
// Plugin infos
|
||||||
|
int index;
|
||||||
|
int64_t guid;
|
||||||
|
YYCC::yycc_u8string desc;
|
||||||
|
YYCC::yycc_u8string author;
|
||||||
|
YYCC::yycc_u8string summary;
|
||||||
|
DWORD version;
|
||||||
|
CK_PLUGIN_TYPE type;
|
||||||
|
YYCC::yycc_u8string func_init;
|
||||||
|
YYCC::yycc_u8string func_exit;
|
||||||
|
// Reader specific
|
||||||
|
YYCC::yycc_u8string reader_fct;
|
||||||
|
int reader_opt_count;
|
||||||
|
CK_DATAREADER_FLAGS reader_flags;
|
||||||
|
int64_t reader_setting_param_guid;
|
||||||
|
YYCC::yycc_u8string reader_file_ext;
|
||||||
|
// Manager and Render Engine specific
|
||||||
|
bool manager_active;
|
||||||
|
// Behavior specific
|
||||||
|
YYCC::yycc_u8string behavior_guids;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined(VIRTOOLS_21)
|
||||||
|
// Virtools 2.1 doesn't have Variable Manager
|
||||||
|
// We use a normal type as a placeholder.
|
||||||
|
using GenericVarType_t = int;
|
||||||
|
#else
|
||||||
|
using GenericVarType_t = CKVariableManager::Variable::Type;
|
||||||
|
#endif
|
||||||
|
struct Table_variable {
|
||||||
|
YYCC::yycc_u8string name;
|
||||||
|
YYCC::yycc_u8string desciption;
|
||||||
|
XWORD flags;
|
||||||
|
GenericVarType_t type;
|
||||||
|
YYCC::yycc_u8string representation;
|
||||||
|
YYCC::yycc_u8string data;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DataCache {
|
||||||
|
public:
|
||||||
|
DataCache() :
|
||||||
|
op(), param(), attr(), plugin(), variable() {}
|
||||||
|
~DataCache() {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
Table_op op;
|
||||||
|
Table_param param;
|
||||||
|
Table_attr attr;
|
||||||
|
Table_plugin plugin;
|
||||||
|
Table_variable variable;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
471
materializer/Database.cpp
Normal file
@@ -0,0 +1,471 @@
|
|||||||
|
#include "Database.hpp"
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace VSW::Materializer::Database {
|
||||||
|
|
||||||
|
#pragma region Help Macros
|
||||||
|
|
||||||
|
#define BEGIN_CTOR int errcode;
|
||||||
|
#define CTOR_SQL_EXEC(sql) errcode = sqlite3_exec(this->GetDb(), sql, nullptr, nullptr, nullptr); \
|
||||||
|
if (errcode != SQLITE_OK) goto failed;
|
||||||
|
#define END_CTOR return; \
|
||||||
|
failed: throw std::runtime_error("fail to initialize database.");
|
||||||
|
#define BEGIN_DTOR int errcode;
|
||||||
|
#define DTOR_SQL_EXEC(sql) errcode = sqlite3_exec(this->GetDb(), sql, nullptr, nullptr, nullptr); \
|
||||||
|
if (errcode != SQLITE_OK) return;
|
||||||
|
#define END_DTOR ;
|
||||||
|
|
||||||
|
/// @brief
|
||||||
|
/// Check database connection first.
|
||||||
|
/// Create index variables for sqlite prepared statement binding use.
|
||||||
|
/// Fetch and reset prepared statement
|
||||||
|
#define BEGIN_WRITER(stmt_str) if (!this->IsValid()) throw std::runtime_error("write on disconnected database."); \
|
||||||
|
int argument_index = 1; \
|
||||||
|
sqlite3_stmt* stmt = GetStmt(stmt_str); \
|
||||||
|
sqlite3_reset(stmt);
|
||||||
|
/// @brief Wrapper of binding function calling.
|
||||||
|
#define WRITER_BIND(eval) if ((eval) != SQLITE_OK) goto failed;
|
||||||
|
/// @brief Get auto incresement index during binding.
|
||||||
|
#define WRITER_INDEX (argument_index++)
|
||||||
|
/// @brief Get prepared statement during binding.
|
||||||
|
#define WRITER_STMT (stmt)
|
||||||
|
/// @brief
|
||||||
|
/// Sumbit binded prepared statement.
|
||||||
|
/// Binding error process.
|
||||||
|
#define END_WRITER if (sqlite3_step(stmt) == SQLITE_DONE) return; \
|
||||||
|
failed: throw std::runtime_error("fail to bind value for prepared statement.");
|
||||||
|
|
||||||
|
#define REVEAL_ENUM(enum_val) static_cast<std::underlying_type_t<decltype(enum_val)>>(enum_val)
|
||||||
|
#define REVEAL_U8STR(u8_str) YYCC::EncodingHelper::ToOrdinary((u8_str).c_str()), -1, SQLITE_TRANSIENT
|
||||||
|
#define REVEAL_BLOB(blob_val) (blob_val).ptr, (blob_val).length, SQLITE_TRANSIENT
|
||||||
|
#define REVEAL_BOOL(bool_val) ((bool_val) ? 1 : 0)
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region Abstract Database
|
||||||
|
|
||||||
|
AbstractDatabase::AbstractDatabase(const YYCC::yycc_u8string_view& file) :
|
||||||
|
m_Db(nullptr), m_StmtCache() {
|
||||||
|
// connect to database (the argument of sqlite3 open function is UTF8)
|
||||||
|
int errcode;
|
||||||
|
if (file.empty()) goto failed;
|
||||||
|
errcode = sqlite3_open_v2(YYCC::EncodingHelper::ToOrdinary(file.data()), &m_Db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr);
|
||||||
|
if (errcode != SQLITE_OK) goto failed;
|
||||||
|
|
||||||
|
// disable synchronous to accelerate speed.
|
||||||
|
errcode = sqlite3_exec(m_Db, "PRAGMA synchronous = OFF;", nullptr, nullptr, nullptr);
|
||||||
|
if (errcode != SQLITE_OK) goto failed_after_open;
|
||||||
|
|
||||||
|
// start transaction
|
||||||
|
errcode = sqlite3_exec(m_Db, "begin;", nullptr, nullptr, nullptr);
|
||||||
|
if (errcode != SQLITE_OK) goto failed_after_open;
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
failed_after_open:
|
||||||
|
sqlite3_close(m_Db);
|
||||||
|
failed:
|
||||||
|
m_Db = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
AbstractDatabase::~AbstractDatabase() {
|
||||||
|
if (m_Db == nullptr) return;
|
||||||
|
int errcode;
|
||||||
|
|
||||||
|
// free all cached stmts
|
||||||
|
for (const auto& pair : m_StmtCache) {
|
||||||
|
if (pair.second != nullptr) {
|
||||||
|
errcode = sqlite3_finalize(pair.second);
|
||||||
|
if (errcode != SQLITE_OK) goto failed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// commit transaction
|
||||||
|
errcode = sqlite3_exec(m_Db, "commit;", nullptr, nullptr, nullptr);
|
||||||
|
if (errcode != SQLITE_OK) goto failed;
|
||||||
|
|
||||||
|
failed:
|
||||||
|
// directly release resources
|
||||||
|
sqlite3_close(m_Db);
|
||||||
|
m_Db = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AbstractDatabase::IsValid() const {
|
||||||
|
return m_Db != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
sqlite3_stmt* AbstractDatabase::GetStmt(const char* stmt_str) {
|
||||||
|
// try to find matched cache
|
||||||
|
auto finder = m_StmtCache.find(stmt_str);
|
||||||
|
if (finder != m_StmtCache.end()) {
|
||||||
|
return finder->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
// no found. create one
|
||||||
|
sqlite3_stmt* stmt = nullptr;
|
||||||
|
int errcode = sqlite3_prepare_v2(m_Db, stmt_str, -1, &stmt, nullptr);
|
||||||
|
if (errcode != SQLITE_OK) throw std::runtime_error("fail to create sqlite3 stmt!");
|
||||||
|
|
||||||
|
// append new one
|
||||||
|
m_StmtCache.emplace(stmt_str, stmt);
|
||||||
|
return stmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
sqlite3* AbstractDatabase::GetDb() {
|
||||||
|
return m_Db;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region Script Database
|
||||||
|
|
||||||
|
ScriptDatabase::ScriptDatabase(const YYCC::yycc_u8string_view& file) :
|
||||||
|
AbstractDatabase(file) {
|
||||||
|
// initialize table
|
||||||
|
BEGIN_CTOR;
|
||||||
|
CTOR_SQL_EXEC("DROP TABLE IF EXISTS [script];");
|
||||||
|
CTOR_SQL_EXEC("DROP TABLE IF EXISTS [behavior];");
|
||||||
|
CTOR_SQL_EXEC("DROP TABLE IF EXISTS [bIO];");
|
||||||
|
CTOR_SQL_EXEC("DROP TABLE IF EXISTS [pTarget];");
|
||||||
|
CTOR_SQL_EXEC("DROP TABLE IF EXISTS [pIn];");
|
||||||
|
CTOR_SQL_EXEC("DROP TABLE IF EXISTS [pOut];");
|
||||||
|
CTOR_SQL_EXEC("DROP TABLE IF EXISTS [bLink];");
|
||||||
|
CTOR_SQL_EXEC("DROP TABLE IF EXISTS [pLocal];");
|
||||||
|
CTOR_SQL_EXEC("DROP TABLE IF EXISTS [pAttr];");
|
||||||
|
CTOR_SQL_EXEC("DROP TABLE IF EXISTS [pLink];");
|
||||||
|
CTOR_SQL_EXEC("DROP TABLE IF EXISTS [pOper];");
|
||||||
|
CTOR_SQL_EXEC("DROP TABLE IF EXISTS [eLink];");
|
||||||
|
CTOR_SQL_EXEC("DROP TABLE IF EXISTS [data];");
|
||||||
|
|
||||||
|
CTOR_SQL_EXEC("CREATE TABLE [script] ([beobj] INTEGER, [beobj_name] TEXT, [behavior_index] INTEGER, [behavior] INTEGER);");
|
||||||
|
CTOR_SQL_EXEC("CREATE TABLE [behavior] ([thisobj] INTEGER, [name] TEXT, [type] INTEGER, [proto_name] TEXT, [proto_guid] INTEGER, [flags] INTEGER, [priority] INTEGER, [version] INTEGER, [pin_count_ptarget] INTEGER, [pin_count_pin] INTEGER, [pin_count_pout] INTEGER, [pin_count_bin] INTEGER, [pin_count_bout] INTEGER, [parent] INTEGER);");
|
||||||
|
CTOR_SQL_EXEC("CREATE TABLE [pTarget] ([thisobj] INTEGER, [name] TEXT, [type] INTEGER, [parent] INTEGER, [direct_source] INTEGER, [shared_source] INTEGER);");
|
||||||
|
CTOR_SQL_EXEC("CREATE TABLE [pIn] ([thisobj] INTEGER, [index] INTEGER, [name] TEXT, [type] INTEGER, [parent] INTEGER, [direct_source] INTEGER, [shared_source] INTEGER);");
|
||||||
|
CTOR_SQL_EXEC("CREATE TABLE [pOut] ([thisobj] INTEGER, [index] INTEGER, [name] TEXT, [type] INTEGER, [parent] INTEGER);");
|
||||||
|
CTOR_SQL_EXEC("CREATE TABLE [bIn] ([thisobj] INTEGER, [index] INTEGER, [name] TEXT, [parent] INTEGER);");
|
||||||
|
CTOR_SQL_EXEC("CREATE TABLE [bOut] ([thisobj] INTEGER, [index] INTEGER, [name] TEXT, [parent] INTEGER);");
|
||||||
|
CTOR_SQL_EXEC("CREATE TABLE [bLink] ([input] INTEGER, [output] INTEGER, [delay] INTEGER, [parent] INTEGER, [input_obj] INTEGER, [input_type] INTEGER, [input_index] INTEGER, [output_obj] INTEGER, [output_type] INTEGER, [output_index] INTEGER);");
|
||||||
|
CTOR_SQL_EXEC("CREATE TABLE [pLocal] ([thisobj] INTEGER, [name] TEXT, [type] INTEGER, [is_setting] INTEGER, [parent] INTEGER);");
|
||||||
|
CTOR_SQL_EXEC("CREATE TABLE [pLink] ([parent] INTEGER, [input] INTEGER, [input_obj] INTEGER, [input_type] INTEGER, [input_is_bb] INTEGER, [input_index] INTEGER, [output] INTEGER, [output_obj] INTEGER, [output_type] INTEGER, [output_is_bb] INTEGER, [output_index] INTEGER);");
|
||||||
|
CTOR_SQL_EXEC("CREATE TABLE [pOper] ([thisobj] INTEGER, [op] INTEGER, [parent] INTEGER);");
|
||||||
|
CTOR_SQL_EXEC("CREATE TABLE [eLink] ([export_obj] INTEGER, [internal_obj] INTEGER, [is_in] INTEGER, [index] INTEGER, [parent] INTEGER);");
|
||||||
|
CTOR_SQL_EXEC("CREATE TABLE [pAttr] ([thisobj] INTEGER, [name] TEXT, [type] INTEGER, [owner] INTEGER);");
|
||||||
|
CTOR_SQL_EXEC("CREATE TABLE [data] ([field] TEXT, [data] BLOB, [parent] INTEGER);");
|
||||||
|
END_CTOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScriptDatabase::~ScriptDatabase() {
|
||||||
|
// create index for quick select in following process
|
||||||
|
BEGIN_DTOR;
|
||||||
|
DTOR_SQL_EXEC("CREATE INDEX [quick_where1] ON [behavior] ([parent])");
|
||||||
|
DTOR_SQL_EXEC("CREATE INDEX [quick_where2] ON [pOper] ([parent], [thisobj])");
|
||||||
|
DTOR_SQL_EXEC("CREATE INDEX [quick_where3] ON [pTarget] ([parent])");
|
||||||
|
DTOR_SQL_EXEC("CREATE INDEX [quick_where4] ON [bIn] ([parent])");
|
||||||
|
DTOR_SQL_EXEC("CREATE INDEX [quick_where5] ON [bOut] ([parent])");
|
||||||
|
DTOR_SQL_EXEC("CREATE INDEX [quick_where6] ON [pIn] ([parent], [thisobj])");
|
||||||
|
DTOR_SQL_EXEC("CREATE INDEX [quick_where7] ON [pOut] ([parent], [thisobj])");
|
||||||
|
DTOR_SQL_EXEC("CREATE INDEX [quick_where8] ON [pLocal] ([parent])");
|
||||||
|
DTOR_SQL_EXEC("CREATE INDEX [quick_where9] ON [pLink] ([parent])");
|
||||||
|
DTOR_SQL_EXEC("CREATE INDEX [quick_where10] ON [bLink] ([parent])");
|
||||||
|
DTOR_SQL_EXEC("CREATE INDEX [quick_where11] ON [elink] ([parent])");
|
||||||
|
DTOR_SQL_EXEC("CREATE INDEX [quick_where12] ON [pAttr] ([thisobj])");
|
||||||
|
DTOR_SQL_EXEC("CREATE INDEX [quick_where13] ON [data] ([parent])");
|
||||||
|
END_DTOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptDatabase::Write(const DataTypes::Script::Table_script& data) {
|
||||||
|
BEGIN_WRITER("INSERT INTO [script] VALUES (?, ?, ?, ?);");
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.beobj));
|
||||||
|
WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.beobj_name)));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.behavior_index));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.behavior));
|
||||||
|
END_WRITER;
|
||||||
|
}
|
||||||
|
void ScriptDatabase::Write(const DataTypes::Script::Table_behavior& data) {
|
||||||
|
BEGIN_WRITER("INSERT INTO [behavior] VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);");
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.thisobj));
|
||||||
|
WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.name)));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.type));
|
||||||
|
WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.proto_name)));
|
||||||
|
WRITER_BIND(sqlite3_bind_int64(WRITER_STMT, WRITER_INDEX, data.proto_guid));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.flags));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.priority));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.version));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.pin_count_ptarget));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.pin_count_pin));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.pin_count_pout));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.pin_count_bin));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.pin_count_bout));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.parent));
|
||||||
|
END_WRITER;
|
||||||
|
}
|
||||||
|
void ScriptDatabase::Write(const DataTypes::Script::Table_bIn& data) {
|
||||||
|
BEGIN_WRITER("INSERT INTO [bIn] VALUES (?, ?, ?, ?);");
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.thisobj));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.index));
|
||||||
|
WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.name)));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.parent));
|
||||||
|
END_WRITER;
|
||||||
|
}
|
||||||
|
void ScriptDatabase::Write(const DataTypes::Script::Table_bOut& data) {
|
||||||
|
BEGIN_WRITER("INSERT INTO [bOut] VALUES (?, ?, ?, ?);");
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.thisobj));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.index));
|
||||||
|
WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.name)));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.parent));
|
||||||
|
END_WRITER;
|
||||||
|
}
|
||||||
|
void ScriptDatabase::Write(const DataTypes::Script::Table_pIn& data) {
|
||||||
|
BEGIN_WRITER("INSERT INTO [pIn] VALUES (?, ?, ?, ?, ?, ?, ?);");
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.thisobj));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.index));
|
||||||
|
WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.name)));
|
||||||
|
WRITER_BIND(sqlite3_bind_int64(WRITER_STMT, WRITER_INDEX, data.type));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.parent));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.direct_source));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.shared_source));
|
||||||
|
END_WRITER;
|
||||||
|
}
|
||||||
|
void ScriptDatabase::Write(const DataTypes::Script::Table_pOut& data) {
|
||||||
|
BEGIN_WRITER("INSERT INTO [pOut] VALUES (?, ?, ?, ?, ?);");
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.thisobj));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.index));
|
||||||
|
WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.name)));
|
||||||
|
WRITER_BIND(sqlite3_bind_int64(WRITER_STMT, WRITER_INDEX, data.type));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.parent));
|
||||||
|
END_WRITER;
|
||||||
|
}
|
||||||
|
void ScriptDatabase::Write(const DataTypes::Script::Table_bLink& data) {
|
||||||
|
BEGIN_WRITER("INSERT INTO [bLink] VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?);");
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.input));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.output));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.delay));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.parent));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.input_obj));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, REVEAL_ENUM(data.input_type)));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.input_index));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.output_obj));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, REVEAL_ENUM(data.output_type)));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.output_index));
|
||||||
|
END_WRITER;
|
||||||
|
}
|
||||||
|
void ScriptDatabase::Write(const DataTypes::Script::Table_pLocal& data) {
|
||||||
|
BEGIN_WRITER("INSERT INTO [pLocal] VALUES (?, ?, ?, ?, ?);");
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.thisobj));
|
||||||
|
WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.name)));
|
||||||
|
WRITER_BIND(sqlite3_bind_int64(WRITER_STMT, WRITER_INDEX, data.type));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, REVEAL_BOOL(data.is_setting)));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.parent));
|
||||||
|
END_WRITER;
|
||||||
|
}
|
||||||
|
void ScriptDatabase::Write(const DataTypes::Script::Table_pAttr& data) {
|
||||||
|
BEGIN_WRITER("INSERT INTO [pAttr] VALUES (?, ?, ?, ?);");
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.thisobj));
|
||||||
|
WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.name)));
|
||||||
|
WRITER_BIND(sqlite3_bind_int64(WRITER_STMT, WRITER_INDEX, data.type));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.owner));
|
||||||
|
END_WRITER;
|
||||||
|
}
|
||||||
|
void ScriptDatabase::Write(const DataTypes::Script::Table_pLink& data) {
|
||||||
|
BEGIN_WRITER("INSERT INTO [pLink] VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);");
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.parent));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.input));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.input_obj));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, REVEAL_ENUM(data.input_type)));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, REVEAL_BOOL(data.input_is_bb)));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.input_index));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.output));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.output_obj));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, REVEAL_ENUM(data.output_type)));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, REVEAL_BOOL(data.output_is_bb)));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.output_index));
|
||||||
|
END_WRITER;
|
||||||
|
}
|
||||||
|
void ScriptDatabase::Write(const DataTypes::Script::Table_pOper& data) {
|
||||||
|
BEGIN_WRITER("INSERT INTO [pOper] VALUES (?, ?, ?);");
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.thisobj));
|
||||||
|
WRITER_BIND(sqlite3_bind_int64(WRITER_STMT, WRITER_INDEX, data.op));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.parent));
|
||||||
|
END_WRITER;
|
||||||
|
}
|
||||||
|
void ScriptDatabase::Write(const DataTypes::Script::Table_eLink& data) {
|
||||||
|
BEGIN_WRITER("INSERT INTO [eLink] VALUES (?, ?, ?, ?, ?);");
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.export_obj));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.internal_obj));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, REVEAL_BOOL(data.is_in)));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.index));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.parent));
|
||||||
|
END_WRITER;
|
||||||
|
}
|
||||||
|
void ScriptDatabase::Write(const DataTypes::Script::Table_pTarget& data) {
|
||||||
|
BEGIN_WRITER("INSERT INTO [pTarget] VALUES (?, ?, ?, ?, ?, ?);");
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.thisobj));
|
||||||
|
WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.name)));
|
||||||
|
WRITER_BIND(sqlite3_bind_int64(WRITER_STMT, WRITER_INDEX, data.type));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.parent));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.direct_source));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.shared_source));
|
||||||
|
END_WRITER;
|
||||||
|
}
|
||||||
|
void ScriptDatabase::Write(const DataTypes::Script::Table_data& data) {
|
||||||
|
BEGIN_WRITER("INSERT INTO [data] VALUES (?, ?, ?);");
|
||||||
|
WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.field)));
|
||||||
|
WRITER_BIND(sqlite3_bind_blob(WRITER_STMT, WRITER_INDEX, REVEAL_BLOB(data.data)));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.parent));
|
||||||
|
END_WRITER;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region Document Database
|
||||||
|
|
||||||
|
DocumentDatabase::DocumentDatabase(const YYCC::yycc_u8string_view& file) :
|
||||||
|
AbstractDatabase(file) {
|
||||||
|
// initialize table
|
||||||
|
BEGIN_CTOR;
|
||||||
|
CTOR_SQL_EXEC("DROP TABLE IF EXISTS [msg];");
|
||||||
|
CTOR_SQL_EXEC("DROP TABLE IF EXISTS [obj];");
|
||||||
|
|
||||||
|
CTOR_SQL_EXEC("CREATE TABLE [msg] ([index] INTEGER, [name] TEXT);");
|
||||||
|
CTOR_SQL_EXEC("CREATE TABLE [obj] ([id] INTEGER, [name] TEXT, [classid] INTEGER, [classid_name] TEXT);");
|
||||||
|
END_CTOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
DocumentDatabase::~DocumentDatabase() {
|
||||||
|
// create index for quick select in following process
|
||||||
|
BEGIN_DTOR;
|
||||||
|
DTOR_SQL_EXEC("CREATE INDEX [quick_where1] ON [msg] ([index])");
|
||||||
|
DTOR_SQL_EXEC("CREATE INDEX [quick_where2] ON [obj] ([id])");
|
||||||
|
END_DTOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DocumentDatabase::Write(const DataTypes::Document::Table_msg& data) {
|
||||||
|
BEGIN_WRITER("INSERT INTO [msg] VALUES (?, ?);");
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.index));
|
||||||
|
WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.name)));
|
||||||
|
END_WRITER;
|
||||||
|
}
|
||||||
|
void DocumentDatabase::Write(const DataTypes::Document::Table_obj& data) {
|
||||||
|
BEGIN_WRITER("INSERT INTO [obj] VALUES (?, ?, ?, ?);");
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.id));
|
||||||
|
WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.name)));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.classid));
|
||||||
|
WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.classid_name)));
|
||||||
|
END_WRITER;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region Environment Database
|
||||||
|
|
||||||
|
EnvironmentDatabase::EnvironmentDatabase(const YYCC::yycc_u8string_view& file) :
|
||||||
|
AbstractDatabase(file) {
|
||||||
|
// initialize table
|
||||||
|
BEGIN_CTOR;
|
||||||
|
CTOR_SQL_EXEC("DROP TABLE IF EXISTS [op];");
|
||||||
|
CTOR_SQL_EXEC("DROP TABLE IF EXISTS [param];");
|
||||||
|
CTOR_SQL_EXEC("DROP TABLE IF EXISTS [attr];");
|
||||||
|
CTOR_SQL_EXEC("DROP TABLE IF EXISTS [plugin];");
|
||||||
|
CTOR_SQL_EXEC("DROP TABLE IF EXISTS [variable];");
|
||||||
|
|
||||||
|
CTOR_SQL_EXEC("CREATE TABLE [op] ([func_ptr] TEXT, [in1_guid] INTEGER, [in2_guid] INTEGER, [out_guid] INTEGER, [op_guid] INTEGER, [op_name] TEXT, [op_code] INTEGER);");
|
||||||
|
CTOR_SQL_EXEC("CREATE TABLE [param] ([index] INTEGER, [guid] INTEGER, [derived_from] INTEGER, [name] TEXT, [default_size] INTEGER, [func_CreateDefault] TEXT, [func_Delete] TEXT, [func_SaveLoad] TEXT, [func_Check] TEXT, [func_Copy] TEXT, [func_String] TEXT, [func_UICreator] TEXT, [dll_name] TEXT, [dll_index] INTEGER, [position_in_dll] INTEGER, [flags] INTEGER, [dw_param] INTEGER, [cid] INTEGER, [saver_manager] INTEGER);");
|
||||||
|
CTOR_SQL_EXEC("CREATE TABLE [attr] ([index] INTEGER, [name] TEXT, [category_index] INTEGER, [category_name] TEXT, [flags] INTEGER, [param_index] INTEGER, [param_guid] INTEGER, [compatible_classid] INTEGER, [default_value] TEXT);");
|
||||||
|
CTOR_SQL_EXEC("CREATE TABLE [plugin] ([category_name] TEXT, [category_index] INTEGER, [dll_name] TEXT, [dll_index] INTEGER, [position_in_dll] INTEGER, [index] INTEGER, [guid] INTEGER, [desc] TEXT, [author] TEXT, [summary] TEXT, [version] INTEGER, [type] INTEGER, [func_init] TEXT, [func_exit] TEXT, [reader_fct] TEXT, [reader_opt_count] INTEGER, [reader_flags] INTEGER, [reader_setting_param_guid] INTEGER, [reader_file_ext] TEXT, [manager_active] INTEGER, [behavior_guids] TEXT);");
|
||||||
|
CTOR_SQL_EXEC("CREATE TABLE [variable] ([name] TEXT, [desciption] TEXT, [flags] INTEGER, [type] INTEGER, [representation] TEXT, [data] TEXT);");
|
||||||
|
END_CTOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
EnvironmentDatabase::~EnvironmentDatabase() {
|
||||||
|
// create index for quick select in following process
|
||||||
|
BEGIN_DTOR;
|
||||||
|
END_DTOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnvironmentDatabase::Write(const DataTypes::Environment::Table_op& data) {
|
||||||
|
BEGIN_WRITER("INSERT INTO [op] VALUES (?, ?, ?, ?, ?, ?, ?);");
|
||||||
|
WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.func_ptr)));
|
||||||
|
WRITER_BIND(sqlite3_bind_int64(WRITER_STMT, WRITER_INDEX, data.in1_guid));
|
||||||
|
WRITER_BIND(sqlite3_bind_int64(WRITER_STMT, WRITER_INDEX, data.in2_guid));
|
||||||
|
WRITER_BIND(sqlite3_bind_int64(WRITER_STMT, WRITER_INDEX, data.out_guid));
|
||||||
|
WRITER_BIND(sqlite3_bind_int64(WRITER_STMT, WRITER_INDEX, data.op_guid));
|
||||||
|
WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.op_name)));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.op_code));
|
||||||
|
END_WRITER;
|
||||||
|
}
|
||||||
|
void EnvironmentDatabase::Write(const DataTypes::Environment::Table_param& data) {
|
||||||
|
BEGIN_WRITER("INSERT INTO [param] VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);");
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.index));
|
||||||
|
WRITER_BIND(sqlite3_bind_int64(WRITER_STMT, WRITER_INDEX, data.guid));
|
||||||
|
WRITER_BIND(sqlite3_bind_int64(WRITER_STMT, WRITER_INDEX, data.derived_from));
|
||||||
|
WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.name)));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.default_size));
|
||||||
|
WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.func_CreateDefault)));
|
||||||
|
WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.func_Delete)));
|
||||||
|
WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.func_SaveLoad)));
|
||||||
|
WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.func_Check)));
|
||||||
|
WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.func_Copy)));
|
||||||
|
WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.func_String)));
|
||||||
|
WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.func_UICreator)));
|
||||||
|
WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.dll_name)));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.dll_index));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.position_in_dll));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.flags));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.dw_param));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.cid));
|
||||||
|
WRITER_BIND(sqlite3_bind_int64(WRITER_STMT, WRITER_INDEX, data.saver_manager));
|
||||||
|
END_WRITER;
|
||||||
|
}
|
||||||
|
void EnvironmentDatabase::Write(const DataTypes::Environment::Table_attr& data) {
|
||||||
|
BEGIN_WRITER("INSERT INTO [attr] VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);");
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.index));
|
||||||
|
WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.name)));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.category_index));
|
||||||
|
WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.category_name)));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.flags));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.param_index));
|
||||||
|
WRITER_BIND(sqlite3_bind_int64(WRITER_STMT, WRITER_INDEX, data.param_guid));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.compatible_classid));
|
||||||
|
WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.default_value)));
|
||||||
|
END_WRITER;
|
||||||
|
}
|
||||||
|
void EnvironmentDatabase::Write(const DataTypes::Environment::Table_plugin& data) {
|
||||||
|
BEGIN_WRITER("INSERT INTO [plugin] VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);");
|
||||||
|
WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.category_name)));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.category_index));
|
||||||
|
WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.dll_name)));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.dll_index));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.position_in_dll));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.index));
|
||||||
|
WRITER_BIND(sqlite3_bind_int64(WRITER_STMT, WRITER_INDEX, data.guid));
|
||||||
|
WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.desc)));
|
||||||
|
WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.author)));
|
||||||
|
WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.summary)));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.version));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.type));
|
||||||
|
WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.func_init)));
|
||||||
|
WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.func_exit)));
|
||||||
|
WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.reader_fct)));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.reader_opt_count));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.reader_flags));
|
||||||
|
WRITER_BIND(sqlite3_bind_int64(WRITER_STMT, WRITER_INDEX, data.reader_setting_param_guid));
|
||||||
|
WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.reader_file_ext)));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, REVEAL_BOOL(data.manager_active)));
|
||||||
|
WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.behavior_guids)));
|
||||||
|
END_WRITER;
|
||||||
|
}
|
||||||
|
void EnvironmentDatabase::Write(const DataTypes::Environment::Table_variable& data) {
|
||||||
|
BEGIN_WRITER("INSERT INTO [variable] VALUES (?, ?, ?, ?, ?, ?);");
|
||||||
|
WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.name)));
|
||||||
|
WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.desciption)));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.flags));
|
||||||
|
WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.type));
|
||||||
|
WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.representation)));
|
||||||
|
WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.data)));
|
||||||
|
END_WRITER;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
}
|
||||||
90
materializer/Database.hpp
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "stdafx.hpp"
|
||||||
|
#include "DataTypes.hpp"
|
||||||
|
#include <sqlite3.h>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
namespace VSW::Materializer::Database {
|
||||||
|
|
||||||
|
class AbstractDatabase {
|
||||||
|
public:
|
||||||
|
AbstractDatabase(const YYCC::yycc_u8string_view& file);
|
||||||
|
virtual ~AbstractDatabase();
|
||||||
|
AbstractDatabase(const AbstractDatabase&) = delete;
|
||||||
|
AbstractDatabase& operator=(const AbstractDatabase&) = delete;
|
||||||
|
AbstractDatabase(AbstractDatabase&&) = delete;
|
||||||
|
AbstractDatabase& operator=(AbstractDatabase&&) = delete;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// @brief Check whether this database is ready for use.
|
||||||
|
bool IsValid() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/// @brief Subclass used for creating stmt with cache feature.
|
||||||
|
sqlite3_stmt* GetStmt(const char* stmt_str);
|
||||||
|
/// @brief Subclass used for get pointer to opened database.
|
||||||
|
sqlite3* GetDb();
|
||||||
|
|
||||||
|
private:
|
||||||
|
sqlite3* m_Db;
|
||||||
|
std::map<const void*, sqlite3_stmt*> m_StmtCache;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ScriptDatabase : public AbstractDatabase {
|
||||||
|
public:
|
||||||
|
ScriptDatabase(const YYCC::yycc_u8string_view& file);
|
||||||
|
virtual ~ScriptDatabase();
|
||||||
|
ScriptDatabase(const ScriptDatabase&) = delete;
|
||||||
|
ScriptDatabase& operator=(const ScriptDatabase&) = delete;
|
||||||
|
ScriptDatabase(ScriptDatabase&&) = delete;
|
||||||
|
ScriptDatabase& operator=(ScriptDatabase&&) = delete;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void Write(const DataTypes::Script::Table_script& data);
|
||||||
|
void Write(const DataTypes::Script::Table_behavior& data);
|
||||||
|
void Write(const DataTypes::Script::Table_bIn& data);
|
||||||
|
void Write(const DataTypes::Script::Table_bOut& data);
|
||||||
|
void Write(const DataTypes::Script::Table_pIn& data);
|
||||||
|
void Write(const DataTypes::Script::Table_pOut& data);
|
||||||
|
void Write(const DataTypes::Script::Table_bLink& data);
|
||||||
|
void Write(const DataTypes::Script::Table_pLocal& data);
|
||||||
|
void Write(const DataTypes::Script::Table_pAttr& data);
|
||||||
|
void Write(const DataTypes::Script::Table_pLink& data);
|
||||||
|
void Write(const DataTypes::Script::Table_pOper& data);
|
||||||
|
void Write(const DataTypes::Script::Table_eLink& data);
|
||||||
|
void Write(const DataTypes::Script::Table_pTarget& data);
|
||||||
|
void Write(const DataTypes::Script::Table_data& data);
|
||||||
|
};
|
||||||
|
|
||||||
|
class DocumentDatabase : public AbstractDatabase {
|
||||||
|
public:
|
||||||
|
DocumentDatabase(const YYCC::yycc_u8string_view& file);
|
||||||
|
virtual ~DocumentDatabase();
|
||||||
|
DocumentDatabase(const DocumentDatabase&) = delete;
|
||||||
|
DocumentDatabase& operator=(const DocumentDatabase&) = delete;
|
||||||
|
DocumentDatabase(DocumentDatabase&&) = delete;
|
||||||
|
DocumentDatabase& operator=(DocumentDatabase&&) = delete;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void Write(const DataTypes::Document::Table_msg& data);
|
||||||
|
void Write(const DataTypes::Document::Table_obj& data);
|
||||||
|
};
|
||||||
|
|
||||||
|
class EnvironmentDatabase : public AbstractDatabase {
|
||||||
|
public:
|
||||||
|
EnvironmentDatabase(const YYCC::yycc_u8string_view& file);
|
||||||
|
virtual ~EnvironmentDatabase();
|
||||||
|
EnvironmentDatabase(const EnvironmentDatabase&) = delete;
|
||||||
|
EnvironmentDatabase& operator=(const EnvironmentDatabase&) = delete;
|
||||||
|
EnvironmentDatabase(EnvironmentDatabase&&) = delete;
|
||||||
|
EnvironmentDatabase& operator=(EnvironmentDatabase&&) = delete;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void Write(const DataTypes::Environment::Table_op& data);
|
||||||
|
void Write(const DataTypes::Environment::Table_param& data);
|
||||||
|
void Write(const DataTypes::Environment::Table_attr& data);
|
||||||
|
void Write(const DataTypes::Environment::Table_plugin& data);
|
||||||
|
void Write(const DataTypes::Environment::Table_variable& data);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
18
materializer/ExportCore.hpp
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "stdafx.hpp"
|
||||||
|
|
||||||
|
namespace VSW::Materializer {
|
||||||
|
|
||||||
|
namespace ExportScript {
|
||||||
|
void Export(CKContext* ctx, const YYCC::yycc_u8string_view& db_path, UINT code_page);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace ExportDocument {
|
||||||
|
void Export(CKContext* ctx, const YYCC::yycc_u8string_view& db_path, UINT code_page);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace ExportEnvironment {
|
||||||
|
void Export(CKContext* ctx, const YYCC::yycc_u8string_view& db_path, UINT code_page);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
215
materializer/ExportDialog.cpp
Normal file
@@ -0,0 +1,215 @@
|
|||||||
|
#if defined(MATERIALIZER_PLUGIN)
|
||||||
|
|
||||||
|
#include "ExportDialog.hpp"
|
||||||
|
#include "PluginMain.hpp"
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace VSW::Materializer {
|
||||||
|
|
||||||
|
namespace ExportDialogHelper {
|
||||||
|
|
||||||
|
#define RADIOBTN_GETCHECK(instance) (instance.GetCheck() == BST_CHECKED)
|
||||||
|
#define RADIOBTN_SETCHECK(instance, stmt) (instance.SetCheck((stmt) ? BST_CHECKED : BST_UNCHECKED))
|
||||||
|
|
||||||
|
static void SetCWndText(CWnd* ctl, const YYCC::yycc_u8string_view& val) {
|
||||||
|
ctl->SetWindowTextA(YYCC::EncodingHelper::UTF8ToChar(val, CP_ACP).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
YYCC::yycc_u8string GetCWndText(CWnd* ctl) {
|
||||||
|
// Ref: https://learn.microsoft.com/zh-cn/cpp/mfc/reference/cwnd-class?view=msvc-170#getwindowtext
|
||||||
|
CString recv;
|
||||||
|
ctl->GetWindowTextA(recv);
|
||||||
|
return YYCC::EncodingHelper::CharToUTF8((LPCSTR)recv, CP_ACP);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExportDialog dialog
|
||||||
|
|
||||||
|
IMPLEMENT_DYNAMIC(ExportDialog, CDialogEx)
|
||||||
|
|
||||||
|
ExportDialog::ExportDialog(CWnd* pParent /*=nullptr*/)
|
||||||
|
: CDialogEx(IDD_EXPORT_DIALOG, pParent),
|
||||||
|
m_InitialDatabaseType(InitialDatabaseType::Script),
|
||||||
|
m_DatabaseFileCache(),
|
||||||
|
m_DatabaseFileResult(), m_EncodingResult(CP_ACP) {}
|
||||||
|
|
||||||
|
ExportDialog::~ExportDialog() {}
|
||||||
|
|
||||||
|
void ExportDialog::DoDataExchange(CDataExchange* pDX) {
|
||||||
|
CDialogEx::DoDataExchange(pDX);
|
||||||
|
DDX_Control(pDX, IDC_EDIT1, m_DatabaseFile);
|
||||||
|
DDX_Control(pDX, IDC_RADIO1, m_EncodingSystem);
|
||||||
|
DDX_Control(pDX, IDC_RADIO2, m_EncodingCustom);
|
||||||
|
DDX_Control(pDX, IDC_EDIT2, m_EncodingCustom_Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BEGIN_MESSAGE_MAP(ExportDialog, CDialogEx)
|
||||||
|
// ===== Buttons =====
|
||||||
|
ON_BN_CLICKED(IDOK, &ExportDialog::OnBtnOkClicked)
|
||||||
|
ON_BN_CLICKED(IDCANCEL, &ExportDialog::OnBtnCancelClicked)
|
||||||
|
ON_BN_CLICKED(IDC_BUTTON1, &ExportDialog::OnBtnBrowseClicked)
|
||||||
|
// ===== Radio Buttons =====
|
||||||
|
ON_BN_CLICKED(IDC_RADIO1, &ExportDialog::OnBtnEncodingClicked)
|
||||||
|
ON_BN_CLICKED(IDC_RADIO2, &ExportDialog::OnBtnEncodingClicked)
|
||||||
|
END_MESSAGE_MAP()
|
||||||
|
|
||||||
|
#pragma region Initial Settings
|
||||||
|
|
||||||
|
void ExportDialog::SetInitialDatabaseType(InitialDatabaseType db_type) {
|
||||||
|
m_InitialDatabaseType = db_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region Result Getter
|
||||||
|
|
||||||
|
const YYCC::yycc_u8string& ExportDialog::GetDatabaseFileResult() {
|
||||||
|
return m_DatabaseFileResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT ExportDialog::GetEncodingResult() {
|
||||||
|
return m_EncodingResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
// ExportDialog message handlers
|
||||||
|
|
||||||
|
#pragma region Event Handler
|
||||||
|
|
||||||
|
BOOL ExportDialog::OnInitDialog() {
|
||||||
|
CDialogEx::OnInitDialog();
|
||||||
|
|
||||||
|
// Read settings from config manager
|
||||||
|
auto& config_manager = PluginMain::ConfigManager::GetSingleton();
|
||||||
|
auto u8_last_path = config_manager.m_LastFilePath.Get();
|
||||||
|
if (!u8_last_path.empty()) {
|
||||||
|
auto last_path = YYCC::StdPatch::ToStdPath(u8_last_path);
|
||||||
|
switch (m_InitialDatabaseType) {
|
||||||
|
case InitialDatabaseType::Script:
|
||||||
|
last_path.replace_filename(YYCC::StdPatch::ToStdPath(YYCC_U8("script.db")));
|
||||||
|
break;
|
||||||
|
case InitialDatabaseType::Document:
|
||||||
|
last_path.replace_filename(YYCC::StdPatch::ToStdPath(YYCC_U8("doc.db")));
|
||||||
|
break;
|
||||||
|
case InitialDatabaseType::Environment:
|
||||||
|
last_path.replace_filename(YYCC::StdPatch::ToStdPath(YYCC_U8("env.db")));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw std::runtime_error("invalid initial database type");
|
||||||
|
}
|
||||||
|
u8_last_path = YYCC::StdPatch::ToUTF8Path(last_path);
|
||||||
|
}
|
||||||
|
PushDatabaseFile(u8_last_path);
|
||||||
|
PushEncoding(config_manager.m_Encoding.Get());
|
||||||
|
|
||||||
|
return TRUE; // return TRUE unless you set the focus to a control
|
||||||
|
// EXCEPTION: OCX Property Pages should return FALSE
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExportDialog::OnBtnOkClicked() {
|
||||||
|
// ===== Collect input settings =====
|
||||||
|
m_DatabaseFileResult = PullDatabaseFile();
|
||||||
|
m_EncodingResult = PullEncoding();
|
||||||
|
if (m_DatabaseFileResult.empty()) {
|
||||||
|
MessageBoxW(m_hWnd, L"Exported database file should not be empty!", L"Setting Error", MB_OK + MB_ICONERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!YYCC::WinFctHelper::IsValidCodePage(m_EncodingResult)) {
|
||||||
|
MessageBoxW(m_hWnd, L"Invalid encoding!", L"Setting Error", MB_OK + MB_ICONERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check done. sync settings to config manager
|
||||||
|
auto& config_manager = PluginMain::ConfigManager::GetSingleton();
|
||||||
|
config_manager.m_LastFilePath.Set(m_DatabaseFileResult);
|
||||||
|
config_manager.m_Encoding.Set(m_EncodingResult);
|
||||||
|
|
||||||
|
CDialogEx::OnOK();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExportDialog::OnBtnCancelClicked() {
|
||||||
|
CDialogEx::OnCancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExportDialog::OnBtnBrowseClicked() {
|
||||||
|
// configure dialog properties
|
||||||
|
YYCC::DialogHelper::FileDialog dialog_settings;
|
||||||
|
auto& dialog_filter = dialog_settings.ConfigreFileTypes();
|
||||||
|
dialog_filter.Add(YYCC_U8("Database File (*.db)"), { YYCC_U8("*.db") });
|
||||||
|
dialog_settings.SetOwner(this->m_hWnd);
|
||||||
|
switch (m_InitialDatabaseType) {
|
||||||
|
case InitialDatabaseType::Script:
|
||||||
|
dialog_settings.SetInitFileName(YYCC_U8("script.db"));
|
||||||
|
break;
|
||||||
|
case InitialDatabaseType::Document:
|
||||||
|
dialog_settings.SetInitFileName(YYCC_U8("doc.db"));
|
||||||
|
break;
|
||||||
|
case InitialDatabaseType::Environment:
|
||||||
|
dialog_settings.SetInitFileName(YYCC_U8("env.db"));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw std::runtime_error("invalid initial database type");
|
||||||
|
}
|
||||||
|
|
||||||
|
// open directory picker and assign it if user click ok.
|
||||||
|
YYCC::yycc_u8string picked_file;
|
||||||
|
if (YYCC::DialogHelper::SaveFileDialog(dialog_settings, picked_file)) {
|
||||||
|
PushDatabaseFile(picked_file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExportDialog::OnBtnEncodingClicked() {
|
||||||
|
UpdateLayouts();
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region Assist Functions
|
||||||
|
|
||||||
|
const YYCC::yycc_u8string& ExportDialog::PullDatabaseFile() {
|
||||||
|
return m_DatabaseFileCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExportDialog::PushDatabaseFile(const YYCC::yycc_u8string& data) {
|
||||||
|
m_DatabaseFileCache = data;
|
||||||
|
ExportDialogHelper::SetCWndText(&m_DatabaseFile, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT ExportDialog::PullEncoding() {
|
||||||
|
if (RADIOBTN_GETCHECK(m_EncodingSystem)) return CP_ACP;
|
||||||
|
else if (RADIOBTN_GETCHECK(m_EncodingCustom)) {
|
||||||
|
UINT result;
|
||||||
|
if (!YYCC::ParserHelper::TryParse(ExportDialogHelper::GetCWndText(&m_EncodingCustom_Value), result))
|
||||||
|
result = static_cast<UINT>(-1);
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("invalid encoding selection");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExportDialog::PushEncoding(UINT data) {
|
||||||
|
RADIOBTN_SETCHECK(m_EncodingSystem, false);
|
||||||
|
RADIOBTN_SETCHECK(m_EncodingCustom, false);
|
||||||
|
|
||||||
|
if (data == CP_ACP) RADIOBTN_SETCHECK(m_EncodingSystem, true);
|
||||||
|
else {
|
||||||
|
RADIOBTN_SETCHECK(m_EncodingCustom, true);
|
||||||
|
ExportDialogHelper::SetCWndText(&m_EncodingCustom_Value, YYCC::ParserHelper::ToString(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateLayouts();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExportDialog::UpdateLayouts() {
|
||||||
|
// enable custom encoding input box according to selection.
|
||||||
|
m_EncodingCustom_Value.EnableWindow(RADIOBTN_GETCHECK(m_EncodingCustom));
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
71
materializer/ExportDialog.hpp
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
#pragma once
|
||||||
|
#if defined(MATERIALIZER_PLUGIN)
|
||||||
|
|
||||||
|
#include "stdafx.hpp"
|
||||||
|
#include "afxdialogex.h"
|
||||||
|
#include "resource.h"
|
||||||
|
|
||||||
|
namespace VSW::Materializer {
|
||||||
|
|
||||||
|
// ExportDialog dialog
|
||||||
|
|
||||||
|
class ExportDialog : public CDialogEx {
|
||||||
|
DECLARE_DYNAMIC(ExportDialog)
|
||||||
|
|
||||||
|
public:
|
||||||
|
ExportDialog(CWnd* pParent = nullptr); // standard constructor
|
||||||
|
virtual ~ExportDialog();
|
||||||
|
|
||||||
|
// Dialog Data
|
||||||
|
#ifdef AFX_DESIGN_TIME
|
||||||
|
enum { IDD = IDD_EXPORT_DIALOG };
|
||||||
|
#endif
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
||||||
|
|
||||||
|
DECLARE_MESSAGE_MAP()
|
||||||
|
public:
|
||||||
|
virtual BOOL OnInitDialog();
|
||||||
|
afx_msg void OnBtnOkClicked();
|
||||||
|
afx_msg void OnBtnCancelClicked();
|
||||||
|
afx_msg void OnBtnBrowseClicked();
|
||||||
|
afx_msg void OnBtnEncodingClicked();
|
||||||
|
|
||||||
|
// ===== Init Settings =====
|
||||||
|
public:
|
||||||
|
enum class InitialDatabaseType {
|
||||||
|
Script, Document, Environment
|
||||||
|
};
|
||||||
|
void SetInitialDatabaseType(InitialDatabaseType db_type);
|
||||||
|
protected:
|
||||||
|
InitialDatabaseType m_InitialDatabaseType;
|
||||||
|
|
||||||
|
// ===== Result =====
|
||||||
|
public:
|
||||||
|
const YYCC::yycc_u8string& GetDatabaseFileResult();
|
||||||
|
UINT GetEncodingResult();
|
||||||
|
private:
|
||||||
|
YYCC::yycc_u8string m_DatabaseFileResult;
|
||||||
|
UINT m_EncodingResult;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// ===== Controls =====
|
||||||
|
CEdit m_DatabaseFile;
|
||||||
|
CButton m_EncodingSystem;
|
||||||
|
CButton m_EncodingCustom;
|
||||||
|
CEdit m_EncodingCustom_Value;
|
||||||
|
// ===== Caches =====
|
||||||
|
YYCC::yycc_u8string m_DatabaseFileCache;
|
||||||
|
// ===== Pull & Push =====
|
||||||
|
const YYCC::yycc_u8string& PullDatabaseFile();
|
||||||
|
void PushDatabaseFile(const YYCC::yycc_u8string& data);
|
||||||
|
UINT PullEncoding();
|
||||||
|
void PushEncoding(UINT data);
|
||||||
|
// ===== Update Functions =====
|
||||||
|
void UpdateLayouts();
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
79
materializer/ExportDocument.cpp
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
#include "ExportCore.hpp"
|
||||||
|
#include "Database.hpp"
|
||||||
|
#include "DataTypes.hpp"
|
||||||
|
#include "Utilities.hpp"
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
namespace VSW::Materializer::ExportDocument {
|
||||||
|
|
||||||
|
struct ExportContext {
|
||||||
|
ExportContext(CKContext* ctx, const YYCC::yycc_u8string_view& db_path, UINT code_page) :
|
||||||
|
db(db_path), cache(), reporter(ctx), cp(code_page) {}
|
||||||
|
Database::DocumentDatabase db;
|
||||||
|
DataTypes::Document::DataCache cache;
|
||||||
|
Utilities::EnhancedReporter reporter;
|
||||||
|
UINT cp;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static void IterateMessage(ExportContext& expctx, CKMessageManager* msg_mgr) {
|
||||||
|
int count = msg_mgr->GetMessageTypeCount();
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
expctx.cache.msg.index = i;
|
||||||
|
CP_CKSTR(expctx.cache.msg.name, msg_mgr->GetMessageTypeName(i));
|
||||||
|
|
||||||
|
expctx.db.Write(expctx.cache.msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief The common parents list which exported objects belong to.
|
||||||
|
static const std::vector<CK_CLASSID> g_CommonClassIds {
|
||||||
|
// Export CKSceneObject will export almost objects in scene
|
||||||
|
// That's enough
|
||||||
|
CKCID_SCENEOBJECT
|
||||||
|
};
|
||||||
|
static void IterateObject(ExportContext& expctx, CKContext* ctx) {
|
||||||
|
// Get CKParameterManager to resolve Class ID name
|
||||||
|
CKParameterManager* param_mgr = ctx->GetParameterManager();
|
||||||
|
// prepare variables
|
||||||
|
CK_CLASSID classid_cache;
|
||||||
|
|
||||||
|
for (const auto& cid : g_CommonClassIds) {
|
||||||
|
XObjectPointerArray obj_array = ctx->GetObjectListByType(cid, TRUE);
|
||||||
|
int obj_count = obj_array.Size();
|
||||||
|
for (int i = 0; i < obj_count; i++) {
|
||||||
|
CKSceneObject* scene_obj = static_cast<CKSceneObject*>(obj_array.GetObjectA(i));
|
||||||
|
|
||||||
|
// basic infos
|
||||||
|
expctx.cache.obj.id = scene_obj->GetID();
|
||||||
|
CP_CKSTR(expctx.cache.obj.name, scene_obj->GetName());
|
||||||
|
classid_cache = scene_obj->GetClassID();
|
||||||
|
expctx.cache.obj.classid = classid_cache;
|
||||||
|
// resolve class id name
|
||||||
|
CP_CKSTR(expctx.cache.obj.classid_name, param_mgr->ParameterGuidToName(param_mgr->ClassIDToGuid(classid_cache)));
|
||||||
|
|
||||||
|
expctx.db.Write(expctx.cache.obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Export(CKContext* ctx, const YYCC::yycc_u8string_view& db_path, UINT code_page) {
|
||||||
|
// create export context
|
||||||
|
ExportContext expctx(ctx, db_path, code_page);
|
||||||
|
if (!expctx.db.IsValid()) {
|
||||||
|
expctx.reporter.Err(YYCC_U8("Fail to open database. Export process aborted."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// export document
|
||||||
|
IterateMessage(expctx, ctx->GetMessageManager());
|
||||||
|
IterateObject(expctx, ctx);
|
||||||
|
|
||||||
|
// report success
|
||||||
|
expctx.reporter.EnableBeep();
|
||||||
|
expctx.reporter.Info(YYCC_U8("Exporting document database done."));
|
||||||
|
expctx.reporter.DisableBeep();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
284
materializer/ExportEnvironment.cpp
Normal file
@@ -0,0 +1,284 @@
|
|||||||
|
#include "ExportCore.hpp"
|
||||||
|
#include "Database.hpp"
|
||||||
|
#include "DataTypes.hpp"
|
||||||
|
#include "Utilities.hpp"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace VSW::Materializer::ExportEnvironment {
|
||||||
|
|
||||||
|
struct ExportContext {
|
||||||
|
ExportContext(CKContext* ctx, const YYCC::yycc_u8string_view& db_path, UINT code_page) :
|
||||||
|
db(db_path), cache(), reporter(ctx), cp(code_page), ctx(ctx), plugin_mgr(CKGetPluginManager()) {}
|
||||||
|
Database::EnvironmentDatabase db;
|
||||||
|
DataTypes::Environment::DataCache cache;
|
||||||
|
Utilities::EnhancedReporter reporter;
|
||||||
|
UINT cp;
|
||||||
|
|
||||||
|
/// @brief Virtools context.
|
||||||
|
CKContext* ctx;
|
||||||
|
/// @brief Virtools Plugin Manager
|
||||||
|
CKPluginManager* plugin_mgr;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void IterateParameterOperation(ExportContext& expctx, CKParameterManager* param_mgr) {
|
||||||
|
// prepare variables
|
||||||
|
std::vector<CKOperationDesc> op_list;
|
||||||
|
CKGUID guid;
|
||||||
|
|
||||||
|
// get the count of all supported paramter operations and iterate it.
|
||||||
|
int count = param_mgr->GetParameterOperationCount();
|
||||||
|
int listCount = 0, cacheListCount = 0;
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
// fill the shared data part.
|
||||||
|
expctx.cache.op.op_code = i;
|
||||||
|
guid = param_mgr->OperationCodeToGuid(i);
|
||||||
|
CP_GUID(expctx.cache.op.op_guid, guid);
|
||||||
|
CP_CKSTR(expctx.cache.op.op_name, param_mgr->OperationCodeToName(i));
|
||||||
|
|
||||||
|
// get all sub-operation of this parameter operation.
|
||||||
|
// each sub-operation can have different in out parameter type
|
||||||
|
// and they are just grouped into the same parameter operation name.
|
||||||
|
int op_list_count = param_mgr->GetAvailableOperationsDesc(guid, nullptr, nullptr, nullptr, nullptr);
|
||||||
|
op_list.resize(static_cast<size_t>(op_list_count));
|
||||||
|
param_mgr->GetAvailableOperationsDesc(guid, nullptr, nullptr, nullptr, op_list.data());
|
||||||
|
for (const auto& op : op_list) {
|
||||||
|
CP_GUID(expctx.cache.op.in1_guid, op.P1Guid);
|
||||||
|
CP_GUID(expctx.cache.op.in2_guid, op.P2Guid);
|
||||||
|
CP_GUID(expctx.cache.op.out_guid, op.ResGuid);
|
||||||
|
CP_ADDR(expctx.cache.op.func_ptr, op.Fct);
|
||||||
|
|
||||||
|
expctx.db.Write(expctx.cache.op);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void IterateParameter(ExportContext& expctx, CKParameterManager* param_mgr) {
|
||||||
|
// prepare variables
|
||||||
|
CKParameterTypeDesc* desc = nullptr;
|
||||||
|
|
||||||
|
// get the count of all paramter types and iterate it.
|
||||||
|
int count = param_mgr->GetParameterTypesCount();
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
desc = param_mgr->GetParameterTypeDescription(i);
|
||||||
|
|
||||||
|
// Parameter basic infos
|
||||||
|
expctx.cache.param.index = desc->Index;
|
||||||
|
CP_GUID(expctx.cache.param.guid, desc->Guid);
|
||||||
|
CP_GUID(expctx.cache.param.derived_from, desc->DerivedFrom);
|
||||||
|
CP_CKSTR(expctx.cache.param.name, desc->TypeName.CStr());
|
||||||
|
expctx.cache.param.default_size = desc->DefaultSize;
|
||||||
|
CP_ADDR(expctx.cache.param.func_CreateDefault, desc->CreateDefaultFunction);
|
||||||
|
CP_ADDR(expctx.cache.param.func_Delete, desc->DeleteFunction);
|
||||||
|
CP_ADDR(expctx.cache.param.func_SaveLoad, desc->SaveLoadFunction);
|
||||||
|
CP_ADDR(expctx.cache.param.func_Check, desc->CheckFunction);
|
||||||
|
CP_ADDR(expctx.cache.param.func_Copy, desc->CopyFunction);
|
||||||
|
CP_ADDR(expctx.cache.param.func_String, desc->StringFunction);
|
||||||
|
CP_ADDR(expctx.cache.param.func_UICreator, desc->UICreatorFunction);
|
||||||
|
|
||||||
|
// Creator dll infos
|
||||||
|
// This is different with plugin.
|
||||||
|
// Because some parameters are provided by Virtools self.
|
||||||
|
CKPluginEntry* plugin_entry = desc->CreatorDll;
|
||||||
|
if (plugin_entry != nullptr) {
|
||||||
|
CKPluginDll* plugin_dll = expctx.plugin_mgr->GetPluginDllInfo(plugin_entry->m_PluginDllIndex);
|
||||||
|
CP_CKSTR(expctx.cache.param.dll_name, plugin_dll->m_DllFileName.CStr());
|
||||||
|
expctx.cache.param.dll_index = plugin_entry->m_PluginDllIndex;
|
||||||
|
expctx.cache.param.position_in_dll = plugin_entry->m_PositionInDll;
|
||||||
|
} else {
|
||||||
|
expctx.cache.param.dll_name = YYCC_U8("<embedded>");
|
||||||
|
expctx.cache.param.dll_index = -1;
|
||||||
|
expctx.cache.param.position_in_dll = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Misc
|
||||||
|
expctx.cache.param.flags = desc->dwFlags;
|
||||||
|
expctx.cache.param.dw_param = desc->dwParam;
|
||||||
|
expctx.cache.param.cid = desc->Cid;
|
||||||
|
CP_GUID(expctx.cache.param.saver_manager, desc->Saver_Manager);
|
||||||
|
|
||||||
|
expctx.db.Write(expctx.cache.param);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void IterateAttribute(ExportContext& expctx, CKAttributeManager* attr_mgr) {
|
||||||
|
// get the count of all attributes and iterate it.
|
||||||
|
int count = attr_mgr->GetAttributeCount();
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
expctx.cache.attr.index = i;
|
||||||
|
CP_CKSTR(expctx.cache.attr.name, attr_mgr->GetAttributeNameByType(i));
|
||||||
|
expctx.cache.attr.category_index = attr_mgr->GetAttributeCategoryIndex(i);
|
||||||
|
CP_CKSTR(expctx.cache.attr.category_name, attr_mgr->GetAttributeCategory(i));
|
||||||
|
expctx.cache.attr.flags = attr_mgr->GetAttributeFlags(i);
|
||||||
|
expctx.cache.attr.param_index = attr_mgr->GetAttributeParameterType(i);
|
||||||
|
CP_GUID(expctx.cache.attr.param_guid, attr_mgr->GetAttributeParameterGUID(i));
|
||||||
|
expctx.cache.attr.compatible_classid = attr_mgr->GetAttributeCompatibleClassId(i);
|
||||||
|
CP_CKSTR(expctx.cache.attr.default_value, attr_mgr->GetAttributeDefaultValue(i));
|
||||||
|
|
||||||
|
expctx.db.Write(expctx.cache.attr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void IteratePlugin(ExportContext& expctx, CKPluginManager* plugin_mgr) {
|
||||||
|
// prepare variables
|
||||||
|
CK_PLUGIN_TYPE plugin_type;
|
||||||
|
|
||||||
|
// get category count and iterate them
|
||||||
|
int category_count = plugin_mgr->GetCategoryCount();
|
||||||
|
for (int i = 0; i < category_count; ++i) {
|
||||||
|
// category name and its index
|
||||||
|
CP_CKSTR(expctx.cache.plugin.category_name, plugin_mgr->GetCategoryName(i));
|
||||||
|
expctx.cache.plugin.category_index = i;
|
||||||
|
|
||||||
|
// iterate plugin within this category
|
||||||
|
int plugin_count = plugin_mgr->GetPluginCount(i);
|
||||||
|
for (int j = 0; j < plugin_count; j++) {
|
||||||
|
CKPluginEntry* plugin_entry = plugin_mgr->GetPluginInfo(i, j);
|
||||||
|
CKPluginInfo* plugin_info = &(plugin_entry->m_PluginInfo);
|
||||||
|
CKPluginDll* plugin_dll = plugin_mgr->GetPluginDllInfo(plugin_entry->m_PluginDllIndex);
|
||||||
|
|
||||||
|
// dll infomation (name + index + position in dll)
|
||||||
|
CP_CKSTR(expctx.cache.plugin.dll_name, plugin_dll->m_DllFileName.CStr());
|
||||||
|
expctx.cache.plugin.dll_index = plugin_entry->m_PluginDllIndex;
|
||||||
|
expctx.cache.plugin.position_in_dll = plugin_entry->m_PositionInDll;
|
||||||
|
|
||||||
|
// plugin info
|
||||||
|
expctx.cache.plugin.index = j;
|
||||||
|
CP_GUID(expctx.cache.plugin.guid, plugin_info->m_GUID);
|
||||||
|
CP_CKSTR(expctx.cache.plugin.desc, plugin_info->m_Description.CStr());
|
||||||
|
CP_CKSTR(expctx.cache.plugin.author, plugin_info->m_Author.CStr());
|
||||||
|
CP_CKSTR(expctx.cache.plugin.summary, plugin_info->m_Summary.CStr());
|
||||||
|
expctx.cache.plugin.version = plugin_info->m_Version;
|
||||||
|
plugin_type = plugin_info->m_Type;
|
||||||
|
expctx.cache.plugin.type = plugin_type;
|
||||||
|
CP_ADDR(expctx.cache.plugin.func_init, plugin_info->m_InitInstanceFct);
|
||||||
|
CP_ADDR(expctx.cache.plugin.func_exit, plugin_info->m_ExitInstanceFct);
|
||||||
|
|
||||||
|
// extra fields according to plugin type
|
||||||
|
// first reset these specific fields
|
||||||
|
expctx.cache.plugin.reader_fct.clear();
|
||||||
|
expctx.cache.plugin.reader_opt_count = 0;
|
||||||
|
expctx.cache.plugin.reader_flags = static_cast<CK_DATAREADER_FLAGS>(0);
|
||||||
|
expctx.cache.plugin.reader_setting_param_guid = INT64_C(0);
|
||||||
|
expctx.cache.plugin.reader_file_ext.clear();
|
||||||
|
expctx.cache.plugin.behavior_guids.clear();
|
||||||
|
expctx.cache.plugin.manager_active = false;
|
||||||
|
// then try to fetch these specific fields
|
||||||
|
switch (plugin_type) {
|
||||||
|
case CKPLUGIN_BITMAP_READER:
|
||||||
|
case CKPLUGIN_SOUND_READER:
|
||||||
|
case CKPLUGIN_MODEL_READER:
|
||||||
|
case CKPLUGIN_MOVIE_READER:
|
||||||
|
{
|
||||||
|
// Reader specific
|
||||||
|
CP_ADDR(expctx.cache.plugin.reader_fct, plugin_entry->m_ReadersInfo->m_GetReaderFct);
|
||||||
|
expctx.cache.plugin.reader_opt_count = plugin_entry->m_ReadersInfo->m_OptionCount;
|
||||||
|
expctx.cache.plugin.reader_flags = plugin_entry->m_ReadersInfo->m_ReaderFlags;
|
||||||
|
CP_GUID(expctx.cache.plugin.reader_setting_param_guid, plugin_entry->m_ReadersInfo->m_SettingsParameterGuid);
|
||||||
|
CP_CKSTR(expctx.cache.plugin.reader_file_ext, static_cast<const char*>(plugin_info->m_Extension), YYCC_U8(""));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CKPLUGIN_BEHAVIOR_DLL:
|
||||||
|
{
|
||||||
|
// Behavior specific
|
||||||
|
std::vector<YYCC::yycc_u8string> guids;
|
||||||
|
YYCC::yycc_u8string guid_cache;
|
||||||
|
for (int i = 0; i < plugin_entry->m_BehaviorsInfo->m_BehaviorsGUID.Size(); ++i) {
|
||||||
|
CP_STR_GUID(guid_cache, plugin_entry->m_BehaviorsInfo->m_BehaviorsGUID[i]);
|
||||||
|
guids.emplace_back(guid_cache);
|
||||||
|
}
|
||||||
|
expctx.cache.plugin.behavior_guids = YYCC::StringHelper::Join(guids, YYCC_U8(", "));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CKPLUGIN_MANAGER_DLL:
|
||||||
|
case CKPLUGIN_RENDERENGINE_DLL:
|
||||||
|
{
|
||||||
|
// Render engine and manager specific
|
||||||
|
// active info
|
||||||
|
expctx.cache.plugin.manager_active = plugin_entry->m_Active;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
expctx.db.Write(expctx.cache.plugin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(VIRTOOLS_21)
|
||||||
|
static void IterateVariable(ExportContext& expctx, CKVariableManager* var_mgr) {
|
||||||
|
// prepare variables
|
||||||
|
CKVariableManager::Variable* varobj = nullptr;
|
||||||
|
const char* var_name;
|
||||||
|
CKVariableManager::Variable::Type var_type;
|
||||||
|
const char* var_representation;
|
||||||
|
int int_cache;
|
||||||
|
float float_cache;
|
||||||
|
XString xstring_cache;
|
||||||
|
|
||||||
|
for (CKVariableManager::Iterator it = var_mgr->GetVariableIterator(); !it.End(); it++) {
|
||||||
|
// get variable
|
||||||
|
varobj = it.GetVariable();
|
||||||
|
// variable name
|
||||||
|
var_name = it.GetName();
|
||||||
|
CP_CKSTR(expctx.cache.variable.name, var_name);
|
||||||
|
// variable description
|
||||||
|
CP_CKSTR(expctx.cache.variable.desciption, varobj->GetDescription());
|
||||||
|
// variable flags
|
||||||
|
expctx.cache.variable.flags = varobj->GetFlags();
|
||||||
|
// variable type
|
||||||
|
var_type = varobj->GetType();
|
||||||
|
expctx.cache.variable.type = var_type;
|
||||||
|
// variable representation
|
||||||
|
// Representation need a special treatment.
|
||||||
|
// Because it is not a name.
|
||||||
|
// So we should record it as empty string if it is nullptr, instead of default <unamed>
|
||||||
|
var_representation = varobj->GetRepresentation();
|
||||||
|
CP_CKSTR(expctx.cache.variable.representation, var_representation, YYCC_U8(""));
|
||||||
|
// We output variable stored value in different way
|
||||||
|
// according to its type.
|
||||||
|
switch (var_type) {
|
||||||
|
case CKVariableManager::Variable::Type::INT:
|
||||||
|
var_mgr->GetValue(var_name, &int_cache);
|
||||||
|
expctx.cache.variable.data = YYCC::ParserHelper::ToString(int_cache);
|
||||||
|
break;
|
||||||
|
case CKVariableManager::Variable::Type::FLOAT:
|
||||||
|
var_mgr->GetValue(var_name, &float_cache);
|
||||||
|
expctx.cache.variable.data = YYCC::ParserHelper::ToString(float_cache);
|
||||||
|
break;
|
||||||
|
case CKVariableManager::Variable::Type::STRING:
|
||||||
|
var_mgr->GetValue(var_name, xstring_cache);
|
||||||
|
CP_CKSTR(expctx.cache.variable.data, xstring_cache.CStr());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw std::runtime_error("invalid variable type!");
|
||||||
|
}
|
||||||
|
|
||||||
|
expctx.db.Write(expctx.cache.variable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void Export(CKContext* ctx, const YYCC::yycc_u8string_view& db_path, UINT code_page) {
|
||||||
|
// create database and data cache in context
|
||||||
|
ExportContext expctx(ctx, db_path, code_page);
|
||||||
|
if (!expctx.db.IsValid()) {
|
||||||
|
expctx.reporter.Err(YYCC_U8("Fail to open database. Export process aborted."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// export environment one by one
|
||||||
|
IterateParameterOperation(expctx, ctx->GetParameterManager());
|
||||||
|
IterateParameter(expctx, ctx->GetParameterManager());
|
||||||
|
IterateAttribute(expctx, ctx->GetAttributeManager());
|
||||||
|
IteratePlugin(expctx, CKGetPluginManager());
|
||||||
|
#if !defined(VIRTOOLS_21)
|
||||||
|
IterateVariable(expctx, ctx->GetVariableManager());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// report success
|
||||||
|
expctx.reporter.EnableBeep();
|
||||||
|
expctx.reporter.Info(YYCC_U8("Exporting environment database done."));
|
||||||
|
expctx.reporter.DisableBeep();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
648
materializer/ExportScript.cpp
Normal file
@@ -0,0 +1,648 @@
|
|||||||
|
#include "ExportCore.hpp"
|
||||||
|
#include "Database.hpp"
|
||||||
|
#include "DataTypes.hpp"
|
||||||
|
#include "Utilities.hpp"
|
||||||
|
#include <numeric>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The namespace contain functions exporting scripts
|
||||||
|
* @details
|
||||||
|
* \c Generate mean that this function will analyse something to generate some objects which are not existed in original Virtools document.
|
||||||
|
* \c Proc meath that this function only just export something which is already existed in original Virtools document, or with slight modifications.
|
||||||
|
*/
|
||||||
|
namespace VSW::Materializer::ExportScript {
|
||||||
|
|
||||||
|
struct ExportContext {
|
||||||
|
ExportContext(CKContext* ctx, const YYCC::yycc_u8string_view& db_path, UINT code_page) :
|
||||||
|
db(db_path), cache(), reporter(ctx), cp(code_page), attr_set(), ctx(ctx), param_mgr(ctx->GetParameterManager()) {}
|
||||||
|
Database::ScriptDatabase db;
|
||||||
|
DataTypes::Script::DataCache cache;
|
||||||
|
Utilities::EnhancedReporter reporter;
|
||||||
|
UINT cp;
|
||||||
|
|
||||||
|
/// @brief Variable for removing duplicated exported attributes.
|
||||||
|
std::set<CK_ID> attr_set;
|
||||||
|
/// @brief Virtools context.
|
||||||
|
CKContext* ctx;
|
||||||
|
/// @brief Virtools Parameter Manager
|
||||||
|
CKParameterManager* param_mgr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#pragma region Assist Functions
|
||||||
|
|
||||||
|
static void DataDictWriter(ExportContext& expctx, const YYCC::yycc_u8string_view& field, const void* data, size_t data_length, CK_ID parent) {
|
||||||
|
// check given data length
|
||||||
|
using db_size_t = decltype(expctx.cache.data.data.length);
|
||||||
|
if (data_length > static_cast<size_t>(std::numeric_limits<db_size_t>::max()))
|
||||||
|
throw std::runtime_error("Too long data length when exporting to data dictionary.");
|
||||||
|
// if length is zero, reset ptr to nullptr
|
||||||
|
if (data_length == 0u) data = nullptr;
|
||||||
|
// write data
|
||||||
|
expctx.cache.data.field = field;
|
||||||
|
expctx.cache.data.data.ptr = data;
|
||||||
|
expctx.cache.data.data.length = static_cast<db_size_t>(data_length);
|
||||||
|
expctx.cache.data.parent = parent;
|
||||||
|
expctx.db.Write(expctx.cache.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DataDictWriter(ExportContext& expctx, const YYCC::yycc_u8string_view& field, const YYCC::yycc_u8string& data, CK_ID parent) {
|
||||||
|
DataDictWriter(expctx, field, data.c_str(), data.length(), parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class _Ty, std::enable_if_t<!std::is_same_v<_Ty, YYCC::yycc_u8string>, int> = 0>
|
||||||
|
static void DataDictWriter(ExportContext& expctx, const YYCC::yycc_u8string_view& field, const _Ty& data, CK_ID parent) {
|
||||||
|
DataDictWriter(expctx, field, &data, sizeof(_Ty), parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define REC_RAW_DATA(field, data, len) DataDictWriter(expctx, YYCC_U8(field), data, len, parent)
|
||||||
|
#define REC_DATA(field, data) DataDictWriter(expctx, YYCC_U8(field), data, parent)
|
||||||
|
|
||||||
|
void DigParameterData(ExportContext& expctx, CKParameter* p, CK_ID parent) {
|
||||||
|
// According to our algorithm, CKParameter passed in this function can not be duplicated.
|
||||||
|
// So we don't need check it anymore.
|
||||||
|
// Get CKGUID and Parameter Type first
|
||||||
|
CKGUID t = p->GetGUID();
|
||||||
|
CKParameterType pt = p->GetType();
|
||||||
|
|
||||||
|
// Record GUID
|
||||||
|
int64_t exported_t;
|
||||||
|
CP_GUID(exported_t, t);
|
||||||
|
REC_DATA("dumper.guid", exported_t);
|
||||||
|
// Record Parameter Type name
|
||||||
|
YYCC::yycc_u8string exported_pt;
|
||||||
|
CP_CKSTR(exported_pt, expctx.param_mgr->ParameterTypeToName(pt));
|
||||||
|
REC_DATA("dumper.type-name", exported_pt);
|
||||||
|
|
||||||
|
// Detect value object scenario (associated with an existing CKObject)
|
||||||
|
if (p->GetParameterClassID() && p->GetValueObject(false)) {
|
||||||
|
// Record CK_ID of associated object
|
||||||
|
CKObject* assoc_obj = p->GetValueObject(false);
|
||||||
|
REC_DATA("dumper.assoc-ckobj", assoc_obj->GetID());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nothing
|
||||||
|
if (t == CKPGUID_NONE) return;
|
||||||
|
|
||||||
|
// Float value
|
||||||
|
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
|
||||||
|
) {
|
||||||
|
REC_DATA("dumper.float", *static_cast<float*>(p->GetReadDataPtr(false)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Integral value
|
||||||
|
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) {
|
||||||
|
REC_DATA("dumper.int", *static_cast<int*>(p->GetReadDataPtr(false)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Vector value
|
||||||
|
if (t == CKPGUID_VECTOR) {
|
||||||
|
REC_DATA("dumper.vector", *static_cast<VxVector*>(p->GetReadDataPtr(false)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (t == CKPGUID_2DVECTOR) {
|
||||||
|
REC_DATA("dumper.2dvector", *static_cast<Vx2DVector*>(p->GetReadDataPtr(false)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (t == CKPGUID_MATRIX) {
|
||||||
|
REC_DATA("dumper.matrix", *static_cast<VxMatrix*>(p->GetReadDataPtr(false)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (t == CKPGUID_COLOR) {
|
||||||
|
REC_DATA("dumper.color", *static_cast<VxColor*>(p->GetReadDataPtr(false)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 2D Curve value
|
||||||
|
if (t == CKPGUID_2DCURVE) {
|
||||||
|
// Get instance
|
||||||
|
CK2dCurve* c = static_cast<CK2dCurve*>(p->GetReadDataPtr(false));
|
||||||
|
// We build our unique binary 2d curve data.
|
||||||
|
Utilities::Curve2DBuilder builder(c);
|
||||||
|
REC_RAW_DATA("dumper.2d-curve", builder.GetDataPtr(), builder.GetDataLength());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// String value
|
||||||
|
if (t == CKPGUID_STRING) {
|
||||||
|
// Virtools internal data may not have null terminal,
|
||||||
|
// so we use need copy it into container first.
|
||||||
|
std::string native_string(
|
||||||
|
static_cast<char*>(p->GetReadDataPtr(false)),
|
||||||
|
static_cast<size_t>(p->GetDataSize())
|
||||||
|
);
|
||||||
|
// Then do encoding convertion
|
||||||
|
YYCC::yycc_u8string utf8_string;
|
||||||
|
if (!YYCC::EncodingHelper::CharToUTF8(native_string, utf8_string, expctx.cp)) {
|
||||||
|
// If failed, report error
|
||||||
|
expctx.reporter.Err(YYCC_U8("Fail to convert string encoding for data of CKParameter. Some value may be empty!"));
|
||||||
|
// reset to blank string
|
||||||
|
utf8_string.clear();
|
||||||
|
}
|
||||||
|
REC_DATA("dumper.string", utf8_string);
|
||||||
|
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
|
||||||
|
|| true // All unknown type goes here.
|
||||||
|
) {
|
||||||
|
// Raw data is similar with string,
|
||||||
|
// but we don't need do encoding convertion.
|
||||||
|
const void* data_ptr = p->GetReadDataPtr(false);
|
||||||
|
size_t data_len = static_cast<size_t>(p->GetDataSize());
|
||||||
|
REC_RAW_DATA("dumper.raw", data_ptr, data_len);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Process Attribute Parameter
|
||||||
|
* @details
|
||||||
|
* pAttr do not have any explicit 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 issues,
|
||||||
|
* so we need check possible duplication in here.
|
||||||
|
* @param[in] expctx Reference to export context.
|
||||||
|
* @param[in] ckobj Pointer to CKParameter (actually is attribute parameter) for processing.
|
||||||
|
*/
|
||||||
|
static void Proc_pAttr(ExportContext& expctx, CKParameter* ckobj) {
|
||||||
|
// Check duplication.
|
||||||
|
// We should not export duplicated pAttr
|
||||||
|
auto insert_result = expctx.attr_set.emplace(ckobj->GetID());
|
||||||
|
if (!insert_result.second) return;
|
||||||
|
|
||||||
|
// Write self first
|
||||||
|
expctx.cache.pAttr.thisobj = ckobj->GetID();
|
||||||
|
CP_CKSTR(expctx.cache.pAttr.name, ckobj->GetName());
|
||||||
|
CP_GUID(expctx.cache.pAttr.type, ckobj->GetGUID());
|
||||||
|
expctx.cache.pAttr.owner = ckobj->GetOwner()->GetID();
|
||||||
|
expctx.db.Write(expctx.cache.pAttr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generate pLink and eLink from pIn
|
||||||
|
* @param[in] expctx Reference to export context.
|
||||||
|
* @param[in] analysed Pointer to CKParameterIn for analysing.
|
||||||
|
* @param[in] parent
|
||||||
|
* @param[in] grandparent
|
||||||
|
* @param[in] pin_index
|
||||||
|
* @param[in] executed_from_bb True if given CKParameterIn is belong to a CKBehavior, otherwise false (CKParamterOperation).
|
||||||
|
* @param[in] is_target True if this function is called from pTarget processor.
|
||||||
|
*/
|
||||||
|
static void Generate_pLink(ExportContext& expctx, CKParameterIn* analysed, CK_ID parent, CK_ID grandparent, int pin_index, bool executed_from_bb, bool is_target) {
|
||||||
|
// First, we analyse eLink.
|
||||||
|
// Check whether this is export parameter and write to database.
|
||||||
|
// If the behavior graph where this pIn's parent locate, also include this pIn,
|
||||||
|
// we can simply assume there is an eLink between them
|
||||||
|
CKBehavior* ckobj_grandparent = static_cast<CKBehavior*>(expctx.ctx->GetObjectA(grandparent));
|
||||||
|
if (ckobj_grandparent->GetInputParameterPosition(analysed) != -1) {
|
||||||
|
expctx.cache.eLink.export_obj = analysed->GetID();
|
||||||
|
expctx.cache.eLink.internal_obj = parent;
|
||||||
|
expctx.cache.eLink.is_in = true;
|
||||||
|
expctx.cache.eLink.index = pin_index;
|
||||||
|
expctx.cache.eLink.parent = grandparent;
|
||||||
|
expctx.db.Write(expctx.cache.eLink);
|
||||||
|
|
||||||
|
// if a eLink has been detected successfully, we returned immediately
|
||||||
|
// and do not analyse any pLink any more.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// start to analyse pLink
|
||||||
|
// first, analyse \c direct_source
|
||||||
|
CKParameter* direct_source = analysed->GetDirectSource();
|
||||||
|
if (direct_source != nullptr) {
|
||||||
|
expctx.cache.pLink.input = direct_source->GetID();
|
||||||
|
|
||||||
|
// For almost pIn, they are connected to a pLocal, so we use \c if statement to test it first
|
||||||
|
CK_CLASSID direct_source_cid = direct_source->GetClassID();
|
||||||
|
if (direct_source_cid == CKCID_PARAMETERLOCAL || direct_source_cid == CKCID_PARAMETERVARIABLE) {
|
||||||
|
// pLocal
|
||||||
|
expctx.cache.pLink.input_obj = direct_source->GetID(); // the owner of pLocal is itself.
|
||||||
|
expctx.cache.pLink.input_type = VSW::DataTypes::ParameterLinkIOType::PLOCAL;
|
||||||
|
expctx.cache.pLink.input_is_bb = false;
|
||||||
|
expctx.cache.pLink.input_index = Utilities::INVALID_INDEX;
|
||||||
|
} 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.
|
||||||
|
CKObject* ds_owner = direct_source->GetOwner();
|
||||||
|
switch (ds_owner->GetClassID()) {
|
||||||
|
case CKCID_BEHAVIOR:
|
||||||
|
{;
|
||||||
|
CKBehavior* ds_owner_cast = static_cast<CKBehavior*>(ds_owner);
|
||||||
|
CKParameterOut* direct_source_cast = static_cast<CKParameterOut*>(direct_source);
|
||||||
|
expctx.cache.pLink.input_obj = ds_owner->GetID();
|
||||||
|
expctx.cache.pLink.input_type = VSW::DataTypes::ParameterLinkIOType::POUT;
|
||||||
|
expctx.cache.pLink.input_is_bb = true;
|
||||||
|
expctx.cache.pLink.input_index = ds_owner_cast->GetOutputParameterPosition(direct_source_cast);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CKCID_PARAMETEROPERATION:
|
||||||
|
{
|
||||||
|
expctx.cache.pLink.input_obj = ds_owner->GetID();
|
||||||
|
expctx.cache.pLink.input_type = VSW::DataTypes::ParameterLinkIOType::POUT;
|
||||||
|
expctx.cache.pLink.input_is_bb = false;
|
||||||
|
expctx.cache.pLink.input_index = 0; // pOper only have 1 pOut
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CKCID_DATAARRAY:
|
||||||
|
{
|
||||||
|
// CKDataArray, see as virtual bb pLocal shortcut
|
||||||
|
expctx.cache.pLink.input_obj = direct_source->GetID();
|
||||||
|
expctx.cache.pLink.input_type = VSW::DataTypes::ParameterLinkIOType::PATTR;
|
||||||
|
expctx.cache.pLink.input_is_bb = false; // discard
|
||||||
|
expctx.cache.pLink.input_index = Utilities::INVALID_INDEX; // discard
|
||||||
|
Proc_pAttr(expctx, direct_source);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
// CKObject, because CKDataArray also a CKObject, so we test it first.
|
||||||
|
// see as virtual bb pLocal shortcut
|
||||||
|
expctx.cache.pLink.input_obj = direct_source->GetID();
|
||||||
|
expctx.cache.pLink.input_type = VSW::DataTypes::ParameterLinkIOType::PATTR;
|
||||||
|
expctx.cache.pLink.input_is_bb = false; // discard
|
||||||
|
expctx.cache.pLink.input_index = Utilities::INVALID_INDEX; // discard
|
||||||
|
Proc_pAttr(expctx, direct_source);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// \c direct_source reflect the real source of current analysed pIn,
|
||||||
|
// however \c direct_source can not reflect export link.
|
||||||
|
// So we need to analyse \c shared_source now for export link.
|
||||||
|
//
|
||||||
|
// If this pIn has established some export relation, its \c shared_source must be filled, so we can detect this in here.
|
||||||
|
// Once its \c shared_source is not nullptr, we should consider export link in here.
|
||||||
|
//
|
||||||
|
// We do not need to analyse any export link here,
|
||||||
|
// we just need to export some infos to tell that there is an export link.
|
||||||
|
CKParameterIn* shared_source = analysed->GetSharedSource();
|
||||||
|
if (shared_source != nullptr) {
|
||||||
|
// pIn from BB
|
||||||
|
// Get the owner of shared_source
|
||||||
|
CKObject* ss_owner = shared_source->GetOwner();
|
||||||
|
// Setup fields
|
||||||
|
expctx.cache.pLink.input = shared_source->GetID();
|
||||||
|
expctx.cache.pLink.input_obj = ss_owner->GetID();
|
||||||
|
|
||||||
|
switch (ss_owner->GetClassID()) {
|
||||||
|
case CKCID_BEHAVIOR: // CKBehavior
|
||||||
|
{
|
||||||
|
CKBehavior* ss_owner_cast = static_cast<CKBehavior*>(ss_owner);
|
||||||
|
if (ss_owner_cast->IsUsingTarget() && (ss_owner_cast->GetTargetParameter() == shared_source)) {
|
||||||
|
// pTarget
|
||||||
|
expctx.cache.pLink.input_type = VSW::DataTypes::ParameterLinkIOType::PTARGET;
|
||||||
|
expctx.cache.pLink.input_is_bb = true;
|
||||||
|
expctx.cache.pLink.input_index = Utilities::INVALID_INDEX; // discard
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// pIn
|
||||||
|
expctx.cache.pLink.input_type = VSW::DataTypes::ParameterLinkIOType::PIN;
|
||||||
|
expctx.cache.pLink.input_is_bb = true;
|
||||||
|
expctx.cache.pLink.input_index = ((CKBehavior*)ss_owner)->GetInputParameterPosition(shared_source);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CKCID_PARAMETEROPERATION: // CKParameterOperation
|
||||||
|
{
|
||||||
|
// pOper only can have pIn (there is no possibility to have pTarget).
|
||||||
|
CKParameterOperation* ss_owner_cast = static_cast<CKParameterOperation*>(ss_owner);
|
||||||
|
expctx.cache.pLink.input_type = VSW::DataTypes::ParameterLinkIOType::PIN;
|
||||||
|
expctx.cache.pLink.input_is_bb = false;
|
||||||
|
expctx.cache.pLink.input_index = ss_owner_cast->GetInParameter1() == shared_source ? 0 : 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
// The unexpected value.
|
||||||
|
// According to SDK manual, there are only 2 possible types.
|
||||||
|
throw std::runtime_error("unexpected shared_source owner class id!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the head of pLink has been analysed successfully,
|
||||||
|
// we can add tail info and push into database
|
||||||
|
if (shared_source != nullptr || direct_source != nullptr) {
|
||||||
|
expctx.cache.pLink.output = analysed->GetID();
|
||||||
|
expctx.cache.pLink.output_obj = parent;
|
||||||
|
expctx.cache.pLink.output_type = is_target ? VSW::DataTypes::ParameterLinkIOType::PTARGET : VSW::DataTypes::ParameterLinkIOType::PIN;
|
||||||
|
expctx.cache.pLink.output_is_bb = executed_from_bb;
|
||||||
|
expctx.cache.pLink.output_index = pin_index;
|
||||||
|
expctx.cache.pLink.parent = grandparent;
|
||||||
|
|
||||||
|
expctx.db.Write(expctx.cache.pLink);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generate pLink and eLink from pOut
|
||||||
|
* @param[in] expctx Reference to export context.
|
||||||
|
* @param[in] analysed Pointer to CKParameterIn for analysing.
|
||||||
|
* @param[in] parent
|
||||||
|
* @param[in] grandparent
|
||||||
|
* @param[in] pout_index
|
||||||
|
* @param[in] executed_from_bb True if given CKParameterIn is belong to a CKBehavior, otherwise false (CKParamterOperation).
|
||||||
|
*/
|
||||||
|
static void Generate_pLink(ExportContext& expctx, CKParameterOut* analysed, CK_ID parent, CK_ID grandparent, int pout_index, bool executed_from_bb) {
|
||||||
|
// Check eLink first
|
||||||
|
// Check whether there is an export parameter and write to database
|
||||||
|
// Same check method as another overload
|
||||||
|
CKBehavior* ckobj_grandparent = static_cast<CKBehavior*>(expctx.ctx->GetObjectA(grandparent));
|
||||||
|
if (ckobj_grandparent->GetOutputParameterPosition(analysed) != -1) {
|
||||||
|
expctx.cache.eLink.export_obj = analysed->GetID();
|
||||||
|
expctx.cache.eLink.internal_obj = parent;
|
||||||
|
expctx.cache.eLink.is_in = false;
|
||||||
|
expctx.cache.eLink.index = pout_index;
|
||||||
|
expctx.cache.eLink.parent = grandparent;
|
||||||
|
|
||||||
|
expctx.db.Write(expctx.cache.eLink);
|
||||||
|
// if an eLink has been generated, skip following pLink generation
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to generate pLink
|
||||||
|
for (int j = 0, j_count = analysed->GetDestinationCount(); j < j_count; j++) {
|
||||||
|
CKParameter* dest = analysed->GetDestination(j);
|
||||||
|
|
||||||
|
expctx.cache.pLink.input = analysed->GetID();
|
||||||
|
expctx.cache.pLink.input_obj = parent;
|
||||||
|
expctx.cache.pLink.input_type = VSW::DataTypes::ParameterLinkIOType::POUT;
|
||||||
|
expctx.cache.pLink.input_is_bb = executed_from_bb;
|
||||||
|
expctx.cache.pLink.input_index = pout_index;
|
||||||
|
|
||||||
|
expctx.cache.pLink.output = dest->GetID();
|
||||||
|
if (dest->GetClassID() == CKCID_PARAMETERLOCAL) {
|
||||||
|
// pLocal
|
||||||
|
expctx.cache.pLink.output_obj = dest->GetID();
|
||||||
|
expctx.cache.pLink.output_type = VSW::DataTypes::ParameterLinkIOType::PLOCAL;
|
||||||
|
expctx.cache.pLink.output_is_bb = false; // discard
|
||||||
|
expctx.cache.pLink.output_index = Utilities::INVALID_INDEX; // discard
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// pOut. It must belong to a graph BB
|
||||||
|
// (pOut can not be shared, and prototype bb or pOper do not have linkable pOut).
|
||||||
|
CKObject* dest_owner = dest->GetOwner();
|
||||||
|
switch (dest_owner->GetClassID()) {
|
||||||
|
case CKCID_BEHAVIOR:
|
||||||
|
{
|
||||||
|
CKBehavior* dest_owner_cast = static_cast<CKBehavior*>(dest_owner);
|
||||||
|
CKParameterOut* dest_cast = static_cast<CKParameterOut*>(dest);
|
||||||
|
expctx.cache.pLink.output_obj = dest_owner->GetID();
|
||||||
|
expctx.cache.pLink.output_type = VSW::DataTypes::ParameterLinkIOType::POUT;
|
||||||
|
expctx.cache.pLink.output_is_bb = true;
|
||||||
|
expctx.cache.pLink.output_index = dest_owner_cast->GetOutputParameterPosition(dest_cast);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CKCID_DATAARRAY:
|
||||||
|
{
|
||||||
|
// CKDataArray, see as virtual BB pLocal shortcut
|
||||||
|
expctx.cache.pLink.output_obj = dest->GetID();
|
||||||
|
expctx.cache.pLink.output_type = VSW::DataTypes::ParameterLinkIOType::PATTR;
|
||||||
|
expctx.cache.pLink.input_is_bb = false; // discard
|
||||||
|
expctx.cache.pLink.input_index = Utilities::INVALID_INDEX; // discard
|
||||||
|
Proc_pAttr(expctx, dest);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
// CKObject. Because CKDataArray also a CKObject, so we test it above this case statement.
|
||||||
|
// See this as virtual BB pLocal shortcut
|
||||||
|
expctx.cache.pLink.output_obj = dest->GetID();
|
||||||
|
expctx.cache.pLink.output_type = VSW::DataTypes::ParameterLinkIOType::PATTR;
|
||||||
|
expctx.cache.pLink.input_is_bb = false; // discard
|
||||||
|
expctx.cache.pLink.input_index = Utilities::INVALID_INDEX; // discard
|
||||||
|
Proc_pAttr(expctx, dest);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// setup parent and write into database
|
||||||
|
expctx.cache.pLink.parent = grandparent;
|
||||||
|
expctx.db.Write(expctx.cache.pLink);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Proc_pTarget(ExportContext& expctx, CKParameterIn* ckobj, CK_ID parent, CK_ID grandparent) {
|
||||||
|
expctx.cache.pTarget.thisobj = ckobj->GetID();
|
||||||
|
CP_CKSTR(expctx.cache.pTarget.name, ckobj->GetName());
|
||||||
|
CP_GUID(expctx.cache.pTarget.type, ckobj->GetGUID());
|
||||||
|
expctx.cache.pTarget.parent = parent;
|
||||||
|
expctx.cache.pTarget.direct_source = ckobj->GetDirectSource() ? ckobj->GetDirectSource()->GetID() : Utilities::INVALID_CK_ID;
|
||||||
|
expctx.cache.pTarget.shared_source = ckobj->GetSharedSource() ? ckobj->GetSharedSource()->GetID() : Utilities::INVALID_CK_ID;
|
||||||
|
expctx.db.Write(expctx.cache.pTarget);
|
||||||
|
|
||||||
|
// try to generate pLink and eLink
|
||||||
|
Generate_pLink(expctx, ckobj, parent, grandparent, Utilities::INVALID_INDEX, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Proc_pIn(ExportContext& expctx, CKParameterIn* ckobj, CK_ID parent, CK_ID grandparent, int index, bool executed_from_bb) {
|
||||||
|
expctx.cache.pIn.thisobj = ckobj->GetID();
|
||||||
|
expctx.cache.pIn.index = index;
|
||||||
|
CP_CKSTR(expctx.cache.pIn.name, ckobj->GetName());
|
||||||
|
CP_GUID(expctx.cache.pIn.type, ckobj->GetGUID());
|
||||||
|
expctx.cache.pIn.parent = parent;
|
||||||
|
expctx.cache.pIn.direct_source = ckobj->GetDirectSource() ? ckobj->GetDirectSource()->GetID() : Utilities::INVALID_CK_ID;
|
||||||
|
expctx.cache.pIn.shared_source = ckobj->GetSharedSource() ? ckobj->GetSharedSource()->GetID() : Utilities::INVALID_CK_ID;
|
||||||
|
expctx.db.Write(expctx.cache.pIn);
|
||||||
|
|
||||||
|
// try to generate pLink and eLink
|
||||||
|
Generate_pLink(expctx, ckobj, parent, grandparent, index, executed_from_bb, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Proc_pOut(ExportContext& expctx, CKParameterOut* ckobj, CK_ID parent, CK_ID grandparent, int index, bool executed_from_bb) {
|
||||||
|
expctx.cache.pOut.thisobj = ckobj->GetID();
|
||||||
|
expctx.cache.pOut.index = index;
|
||||||
|
CP_CKSTR(expctx.cache.pOut.name, ckobj->GetName());
|
||||||
|
CP_GUID(expctx.cache.pOut.type, ckobj->GetGUID());
|
||||||
|
expctx.cache.pOut.parent = parent;
|
||||||
|
expctx.db.Write(expctx.cache.pOut);
|
||||||
|
|
||||||
|
// try to generate pLink and eLink
|
||||||
|
Generate_pLink(expctx, ckobj, parent, grandparent, index, executed_from_bb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Proc_bIn(ExportContext& expctx, CKBehaviorIO* ckobj, CK_ID parent, int index) {
|
||||||
|
expctx.cache.bIn.thisobj = ckobj->GetID();
|
||||||
|
expctx.cache.bIn.index = index;
|
||||||
|
CP_CKSTR(expctx.cache.bIn.name, ckobj->GetName());
|
||||||
|
expctx.cache.bIn.parent = parent;
|
||||||
|
expctx.db.Write(expctx.cache.bIn);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Proc_bOut(ExportContext& expctx, CKBehaviorIO* ckobj, CK_ID parent, int index) {
|
||||||
|
expctx.cache.bOut.thisobj = ckobj->GetID();
|
||||||
|
expctx.cache.bOut.index = index;
|
||||||
|
CP_CKSTR(expctx.cache.bOut.name, ckobj->GetName());
|
||||||
|
expctx.cache.bOut.parent = parent;
|
||||||
|
expctx.db.Write(expctx.cache.bOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Proc_bLink(ExportContext& expctx, CKBehaviorLink* ckobj, CK_ID parent) {
|
||||||
|
// setup start terminal
|
||||||
|
CKBehaviorIO* io = ckobj->GetInBehaviorIO();
|
||||||
|
CKBehavior* beh = io->GetOwner();
|
||||||
|
expctx.cache.bLink.input = io->GetID();
|
||||||
|
expctx.cache.bLink.input_obj = beh->GetID();
|
||||||
|
expctx.cache.bLink.input_type = (io->GetType() == CK_BEHAVIORIO_IN ? VSW::DataTypes::BehaviorLinkIOType::INPUT : VSW::DataTypes::BehaviorLinkIOType::OUTPUT);
|
||||||
|
expctx.cache.bLink.input_index = (io->GetType() == CK_BEHAVIORIO_IN ? io->GetOwner()->GetInputPosition(io) : io->GetOwner()->GetOutputPosition(io));
|
||||||
|
// setup end terminal
|
||||||
|
io = ckobj->GetOutBehaviorIO();
|
||||||
|
beh = io->GetOwner();
|
||||||
|
expctx.cache.bLink.output = io->GetID();
|
||||||
|
expctx.cache.bLink.output_obj = beh->GetID();
|
||||||
|
expctx.cache.bLink.output_type = (io->GetType() == CK_BEHAVIORIO_IN ? VSW::DataTypes::BehaviorLinkIOType::INPUT : VSW::DataTypes::BehaviorLinkIOType::OUTPUT);
|
||||||
|
expctx.cache.bLink.output_index = (io->GetType() == CK_BEHAVIORIO_IN ? io->GetOwner()->GetInputPosition(io) : io->GetOwner()->GetOutputPosition(io));
|
||||||
|
// other properties
|
||||||
|
expctx.cache.bLink.delay = ckobj->GetActivationDelay();
|
||||||
|
expctx.cache.bLink.parent = parent;
|
||||||
|
// write to database
|
||||||
|
expctx.db.Write(expctx.cache.bLink);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Proc_pLocal(ExportContext& expctx, CKParameterLocal* ckobj, CK_ID parent, bool is_setting) {
|
||||||
|
expctx.cache.pLocal.thisobj = ckobj->GetID();
|
||||||
|
CP_CKSTR(expctx.cache.pLocal.name, ckobj->GetName());
|
||||||
|
CP_GUID(expctx.cache.pLocal.type, ckobj->GetGUID());
|
||||||
|
expctx.cache.pLocal.is_setting = is_setting;
|
||||||
|
expctx.cache.pLocal.parent = parent;
|
||||||
|
expctx.db.Write(expctx.cache.pLocal);
|
||||||
|
|
||||||
|
// Export pLocal internal data
|
||||||
|
DigParameterData(expctx, ckobj, ckobj->GetID());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Proc_pOper(ExportContext& expctx, CKParameterOperation* ckobj, CK_ID parent) {
|
||||||
|
expctx.cache.pOper.thisobj = ckobj->GetID();
|
||||||
|
CP_GUID(expctx.cache.pOper.op, ckobj->GetOperationGuid());
|
||||||
|
expctx.cache.pOper.parent = parent;
|
||||||
|
expctx.db.Write(expctx.cache.pOper);
|
||||||
|
|
||||||
|
// Process associated 2 pIn and 1 pOut
|
||||||
|
Proc_pIn(expctx, ckobj->GetInParameter1(), ckobj->GetID(), parent, 0, false);
|
||||||
|
Proc_pIn(expctx, ckobj->GetInParameter2(), ckobj->GetID(), parent, 1, false);
|
||||||
|
Proc_pOut(expctx, ckobj->GetOutParameter(), ckobj->GetID(), parent, 0, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Process CKBehavior
|
||||||
|
* @param[in] expctx Reference to export context.
|
||||||
|
* @param[in] behavior Pointer to CKBehavior for processing.
|
||||||
|
* @param[in] parent The parent of this CKBehavior. Set to \c INVALID_CK_ID if it was called from script iterator.
|
||||||
|
*/
|
||||||
|
static void Proc_Behavior(ExportContext& expctx, CKBehavior* behavior, CK_ID parent) {
|
||||||
|
// Write basic behavior infomation
|
||||||
|
expctx.cache.behavior.thisobj = behavior->GetID();
|
||||||
|
CP_CKSTR(expctx.cache.behavior.name, behavior->GetName());
|
||||||
|
expctx.cache.behavior.type = behavior->GetType();
|
||||||
|
CP_CKSTR(expctx.cache.behavior.proto_name, behavior->GetPrototypeName());
|
||||||
|
CP_GUID(expctx.cache.behavior.proto_guid, behavior->GetPrototypeGuid());
|
||||||
|
expctx.cache.behavior.flags = behavior->GetFlags();
|
||||||
|
expctx.cache.behavior.priority = behavior->GetPriority();
|
||||||
|
expctx.cache.behavior.version = behavior->GetVersion();
|
||||||
|
expctx.cache.behavior.pin_count_ptarget = (behavior->IsUsingTarget() ? 1 : 0);
|
||||||
|
expctx.cache.behavior.pin_count_pin = behavior->GetInputParameterCount();
|
||||||
|
expctx.cache.behavior.pin_count_pout = behavior->GetOutputParameterCount();
|
||||||
|
expctx.cache.behavior.pin_count_bin = behavior->GetInputCount();
|
||||||
|
expctx.cache.behavior.pin_count_bout = behavior->GetOutputCount();
|
||||||
|
expctx.cache.behavior.parent = parent;
|
||||||
|
expctx.db.Write(expctx.cache.behavior);
|
||||||
|
|
||||||
|
// pTarget
|
||||||
|
if (behavior->IsUsingTarget())
|
||||||
|
Proc_pTarget(expctx, behavior->GetTargetParameter(), behavior->GetID(), parent);
|
||||||
|
|
||||||
|
// pIn
|
||||||
|
for (int i = 0, count = behavior->GetInputParameterCount(); i < count; ++i)
|
||||||
|
Proc_pIn(expctx, behavior->GetInputParameter(i), behavior->GetID(), parent, i, true);
|
||||||
|
// pOut
|
||||||
|
for (int i = 0, count = behavior->GetOutputParameterCount(); i < count; ++i)
|
||||||
|
Proc_pOut(expctx, behavior->GetOutputParameter(i), behavior->GetID(), parent, i, true);
|
||||||
|
// bIn
|
||||||
|
for (int i = 0, count = behavior->GetInputCount(); i < count; ++i)
|
||||||
|
Proc_bIn(expctx, behavior->GetInput(i), behavior->GetID(), i);
|
||||||
|
// bOut
|
||||||
|
for (int i = 0, count = behavior->GetOutputCount(); i < count; ++i)
|
||||||
|
Proc_bOut(expctx, behavior->GetOutput(i), behavior->GetID(), i);
|
||||||
|
// bLink
|
||||||
|
for (int i = 0, count = behavior->GetSubBehaviorLinkCount(); i < count; ++i)
|
||||||
|
Proc_bLink(expctx, behavior->GetSubBehaviorLink(i), behavior->GetID());
|
||||||
|
// pLocal
|
||||||
|
for (int i = 0, count = behavior->GetLocalParameterCount(); i < count; ++i)
|
||||||
|
Proc_pLocal(expctx, behavior->GetLocalParameter(i), behavior->GetID(), behavior->IsLocalParameterSetting(i));
|
||||||
|
// pOper
|
||||||
|
for (int i = 0, count = behavior->GetParameterOperationCount(); i < count; ++i)
|
||||||
|
Proc_pOper(expctx, behavior->GetParameterOperation(i), behavior->GetID());
|
||||||
|
|
||||||
|
// Iterate sub behavior
|
||||||
|
for (int i = 0, count = behavior->GetSubBehaviorCount(); i < count; ++i)
|
||||||
|
Proc_Behavior(expctx, behavior->GetSubBehavior(i), behavior->GetID());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void IterateScript(ExportContext& expctx) {
|
||||||
|
// Get all CKBeObjects to try to get all scripts,
|
||||||
|
// because only CKBeObject can own script.
|
||||||
|
XObjectPointerArray obj_array = expctx.ctx->GetObjectListByType(CKCID_BEOBJECT, TRUE);
|
||||||
|
int obj_count = obj_array.Size();
|
||||||
|
for (int i = 0; i < obj_count; ++i) {
|
||||||
|
// Get CKBeObject
|
||||||
|
CKBeObject* beobj = static_cast<CKBeObject*>(obj_array.GetObjectA(i));
|
||||||
|
|
||||||
|
// Get script count. If no script, skip this object.
|
||||||
|
int script_count = beobj->GetScriptCount();
|
||||||
|
if (script_count == 0) continue;
|
||||||
|
|
||||||
|
// Iterate binding scripts
|
||||||
|
for (int j = 0; j < script_count; ++j) {
|
||||||
|
// Get associated behavior
|
||||||
|
CKBehavior* behavior = beobj->GetScript(j);
|
||||||
|
// Write to database
|
||||||
|
expctx.cache.script.beobj = beobj->GetID();
|
||||||
|
CP_CKSTR(expctx.cache.script.beobj_name, beobj->GetName());
|
||||||
|
expctx.cache.script.behavior_index = j;
|
||||||
|
expctx.cache.script.behavior = behavior->GetID();
|
||||||
|
expctx.db.Write(expctx.cache.script);
|
||||||
|
|
||||||
|
// Process this script
|
||||||
|
Proc_Behavior(expctx, behavior, Utilities::INVALID_CK_ID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Export(CKContext* ctx, const YYCC::yycc_u8string_view& db_path, UINT code_page) {
|
||||||
|
// create export context
|
||||||
|
ExportContext expctx(ctx, db_path, code_page);
|
||||||
|
if (!expctx.db.IsValid()) {
|
||||||
|
expctx.reporter.Err(YYCC_U8("Fail to open database. Export process aborted."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// export script
|
||||||
|
IterateScript(expctx);
|
||||||
|
|
||||||
|
// report success
|
||||||
|
expctx.reporter.EnableBeep();
|
||||||
|
expctx.reporter.Info(YYCC_U8("Exporting script database done."));
|
||||||
|
expctx.reporter.DisableBeep();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
LIBRARY "SuperScriptMaterializer"
|
LIBRARY "VSWMaterializer"
|
||||||
|
|
||||||
EXPORTS
|
EXPORTS
|
||||||
GetVirtoolsPluginInfoCount
|
GetVirtoolsPluginInfoCount
|
||||||
162
materializer/Materializer.rc
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
// Microsoft Visual C++ generated resource script.
|
||||||
|
//
|
||||||
|
#include "resource.h"
|
||||||
|
|
||||||
|
#define APSTUDIO_READONLY_SYMBOLS
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Generated from the TEXTINCLUDE 2 resource.
|
||||||
|
//
|
||||||
|
#include "winres.h"
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
#undef APSTUDIO_READONLY_SYMBOLS
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Chinese (Simplified, PRC) resources
|
||||||
|
|
||||||
|
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
|
||||||
|
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
|
||||||
|
#pragma code_page(936)
|
||||||
|
|
||||||
|
#ifdef APSTUDIO_INVOKED
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// TEXTINCLUDE
|
||||||
|
//
|
||||||
|
|
||||||
|
1 TEXTINCLUDE
|
||||||
|
BEGIN
|
||||||
|
"resource.h\0"
|
||||||
|
END
|
||||||
|
|
||||||
|
2 TEXTINCLUDE
|
||||||
|
BEGIN
|
||||||
|
"#include ""winres.h""\r\n"
|
||||||
|
"\0"
|
||||||
|
END
|
||||||
|
|
||||||
|
3 TEXTINCLUDE
|
||||||
|
BEGIN
|
||||||
|
"\r\n"
|
||||||
|
"\0"
|
||||||
|
END
|
||||||
|
|
||||||
|
#endif // APSTUDIO_INVOKED
|
||||||
|
|
||||||
|
#endif // Chinese (Simplified, PRC) resources
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// English resources
|
||||||
|
|
||||||
|
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||||
|
LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
|
||||||
|
#pragma code_page(1252)
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Version
|
||||||
|
//
|
||||||
|
|
||||||
|
VS_VERSION_INFO VERSIONINFO
|
||||||
|
FILEVERSION 2,0,0,0
|
||||||
|
PRODUCTVERSION 2,0,0,0
|
||||||
|
FILEFLAGSMASK 0x3fL
|
||||||
|
#ifdef _DEBUG
|
||||||
|
FILEFLAGS 0x1L
|
||||||
|
#else
|
||||||
|
FILEFLAGS 0x0L
|
||||||
|
#endif
|
||||||
|
FILEOS 0x40004L
|
||||||
|
FILETYPE 0x1L
|
||||||
|
FILESUBTYPE 0x0L
|
||||||
|
BEGIN
|
||||||
|
BLOCK "StringFileInfo"
|
||||||
|
BEGIN
|
||||||
|
BLOCK "000904b0"
|
||||||
|
BEGIN
|
||||||
|
VALUE "CompanyName", "yyc12345"
|
||||||
|
VALUE "FileDescription", "Virtools Script Weaver - Materializer"
|
||||||
|
VALUE "FileVersion", "2.0.0.0"
|
||||||
|
VALUE "InternalName", "RCEditor.dll"
|
||||||
|
VALUE "LegalCopyright", "Copyright (C) yyc12345 2020-2024"
|
||||||
|
VALUE "OriginalFilename", "RCEditor.dll"
|
||||||
|
VALUE "ProductName", "Virtools Script Weaver"
|
||||||
|
VALUE "ProductVersion", "2.0.0.0"
|
||||||
|
END
|
||||||
|
END
|
||||||
|
BLOCK "VarFileInfo"
|
||||||
|
BEGIN
|
||||||
|
VALUE "Translation", 0x9, 1200
|
||||||
|
END
|
||||||
|
END
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Dialog
|
||||||
|
//
|
||||||
|
|
||||||
|
IDD_EXPORT_DIALOG DIALOGEX 0, 0, 219, 134
|
||||||
|
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||||
|
CAPTION "Export Setting"
|
||||||
|
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||||
|
BEGIN
|
||||||
|
DEFPUSHBUTTON "OK",IDOK,108,114,50,14
|
||||||
|
PUSHBUTTON "Cancel",IDCANCEL,162,114,50,14
|
||||||
|
EDITTEXT IDC_EDIT1,12,22,138,14,ES_AUTOHSCROLL | ES_READONLY
|
||||||
|
PUSHBUTTON "Browse",IDC_BUTTON1,156,22,50,14
|
||||||
|
CONTROL "System",IDC_RADIO1,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,12,66,39,10
|
||||||
|
CONTROL "Custom",IDC_RADIO2,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,108,66,40,10
|
||||||
|
EDITTEXT IDC_EDIT2,12,84,192,14,ES_AUTOHSCROLL
|
||||||
|
GROUPBOX "Database",IDC_STATIC,6,6,204,36
|
||||||
|
GROUPBOX "Encoding",IDC_STATIC,6,48,204,60
|
||||||
|
END
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// DESIGNINFO
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifdef APSTUDIO_INVOKED
|
||||||
|
GUIDELINES DESIGNINFO
|
||||||
|
BEGIN
|
||||||
|
IDD_EXPORT_DIALOG, DIALOG
|
||||||
|
BEGIN
|
||||||
|
LEFTMARGIN, 7
|
||||||
|
RIGHTMARGIN, 212
|
||||||
|
TOPMARGIN, 7
|
||||||
|
BOTTOMMARGIN, 127
|
||||||
|
END
|
||||||
|
END
|
||||||
|
#endif // APSTUDIO_INVOKED
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// AFX_DIALOG_LAYOUT
|
||||||
|
//
|
||||||
|
|
||||||
|
IDD_EXPORT_DIALOG AFX_DIALOG_LAYOUT
|
||||||
|
BEGIN
|
||||||
|
0
|
||||||
|
END
|
||||||
|
|
||||||
|
#endif // English resources
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef APSTUDIO_INVOKED
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Generated from the TEXTINCLUDE 3 resource.
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif // not APSTUDIO_INVOKED
|
||||||
|
|
||||||
158
materializer/PluginMain.cpp
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
#include "PluginMain.hpp"
|
||||||
|
#include "ExportCore.hpp"
|
||||||
|
#include "ExportDialog.hpp"
|
||||||
|
|
||||||
|
namespace VSW::Materializer::PluginMain {
|
||||||
|
|
||||||
|
#ifdef MATERIALIZER_PLUGIN
|
||||||
|
|
||||||
|
#pragma region Export Dialog Setting
|
||||||
|
|
||||||
|
ConfigManager::ConfigManager() :
|
||||||
|
m_LastFilePath(YYCC_U8("last-file-path"), YYCC_U8("")),
|
||||||
|
m_Encoding(YYCC_U8("encoding"), CP_ACP),
|
||||||
|
m_Mgr(ConfigManager::GetConfigFilePath(), UINT64_C(0), {
|
||||||
|
&m_LastFilePath, &m_Encoding
|
||||||
|
}) {}
|
||||||
|
|
||||||
|
ConfigManager::~ConfigManager() {}
|
||||||
|
|
||||||
|
ConfigManager& ConfigManager::GetSingleton() {
|
||||||
|
static ConfigManager g_Singleton;
|
||||||
|
return g_Singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
YYCC::yycc_u8string ConfigManager::GetConfigFilePath() {
|
||||||
|
// get path to executable virtools
|
||||||
|
YYCC::yycc_u8string u8_virtools_path;
|
||||||
|
if (!YYCC::WinFctHelper::GetModuleFileName(NULL, u8_virtools_path))
|
||||||
|
u8_virtools_path.clear();
|
||||||
|
// get its parent folder and append with cfg file name
|
||||||
|
std::filesystem::path virtools_path(YYCC::StdPatch::ToStdPath(u8_virtools_path));
|
||||||
|
return YYCC::StdPatch::ToUTF8Path(virtools_path.parent_path() / YYCC::StdPatch::ToStdPath(YYCC_U8("vsw_materializer.cfg")));
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
|
||||||
|
PluginInterface* g_Plugininterface = nullptr;
|
||||||
|
PluginInfo g_PluginInfo;
|
||||||
|
CMenu* g_MainMenu = nullptr;
|
||||||
|
|
||||||
|
static void PluginMenuCallback(int command_id) {
|
||||||
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||||||
|
CKContext* ctx = g_Plugininterface->GetCKContext();
|
||||||
|
|
||||||
|
switch (command_id) {
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
ExportDialog dialog;
|
||||||
|
dialog.SetInitialDatabaseType(ExportDialog::InitialDatabaseType::Script);
|
||||||
|
if (dialog.DoModal() == IDOK) {
|
||||||
|
ExportScript::Export(ctx, dialog.GetDatabaseFileResult(), dialog.GetEncodingResult());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
ExportDialog dialog;
|
||||||
|
dialog.SetInitialDatabaseType(ExportDialog::InitialDatabaseType::Document);
|
||||||
|
if (dialog.DoModal() == IDOK) {
|
||||||
|
ExportDocument::Export(ctx, dialog.GetDatabaseFileResult(), dialog.GetEncodingResult());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
ExportDialog dialog;
|
||||||
|
dialog.SetInitialDatabaseType(ExportDialog::InitialDatabaseType::Environment);
|
||||||
|
if (dialog.DoModal() == IDOK) {
|
||||||
|
ExportEnvironment::Export(ctx, dialog.GetDatabaseFileResult(), dialog.GetEncodingResult());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3:
|
||||||
|
{
|
||||||
|
ShellExecuteW(NULL, L"open", L"https://github.com/yyc12345/SuperScriptMaterializer/issues", NULL, NULL, SW_SHOWNORMAL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
const wchar_t* body =
|
||||||
|
L"VSW Materializer v2.0.0 - Virtools Schematic Weaver Materializer.\n"
|
||||||
|
L"The exporter of universal Virtools scripts analyser.\n"
|
||||||
|
L"Under GPL v3 License.\n"
|
||||||
|
L"Project Home Page: https://github.com/yyc12345/SuperScriptMaterializer";
|
||||||
|
MessageBoxW(nullptr, body, L"About VSW Materializer", MB_ICONINFORMATION + MB_OK);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void InitMenu() {
|
||||||
|
if (!g_Plugininterface)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_MainMenu = g_Plugininterface->AddPluginMenu("VSW Materializer", 20, NULL, (VoidFunc1Param)PluginMenuCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void RemoveMenu() {
|
||||||
|
if (!g_Plugininterface || !g_MainMenu)
|
||||||
|
return;
|
||||||
|
g_Plugininterface->RemovePluginMenu(g_MainMenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void UpdateMenu() {
|
||||||
|
g_Plugininterface->ClearPluginMenu(g_MainMenu);
|
||||||
|
|
||||||
|
g_Plugininterface->AddPluginMenuItem(g_MainMenu, 0, "Export Script");
|
||||||
|
g_Plugininterface->AddPluginMenuItem(g_MainMenu, 1, "Export Document");
|
||||||
|
g_Plugininterface->AddPluginMenuItem(g_MainMenu, 2, "Export Environment");
|
||||||
|
g_Plugininterface->AddPluginMenuItem(g_MainMenu, -1, NULL, TRUE);
|
||||||
|
g_Plugininterface->AddPluginMenuItem(g_MainMenu, 3, "Report Bug");
|
||||||
|
g_Plugininterface->AddPluginMenuItem(g_MainMenu, 4, "About VSW Materializer");
|
||||||
|
|
||||||
|
|
||||||
|
g_Plugininterface->UpdatePluginMenu(g_MainMenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void PluginCallback(PluginInfo::CALLBACK_REASON reason, PluginInterface* plugininterface) {
|
||||||
|
switch (reason) {
|
||||||
|
case PluginInfo::CR_LOAD:
|
||||||
|
{
|
||||||
|
g_Plugininterface = plugininterface;
|
||||||
|
InitMenu();
|
||||||
|
UpdateMenu();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PluginInfo::CR_UNLOAD:
|
||||||
|
{
|
||||||
|
RemoveMenu();
|
||||||
|
g_Plugininterface = nullptr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PluginInfo::CR_NEWCOMPOSITIONNAME:
|
||||||
|
break;
|
||||||
|
case PluginInfo::CR_NOTIFICATION:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitializePluginInfo() {
|
||||||
|
strcpy(g_PluginInfo.m_Name, "VSW Materializer");
|
||||||
|
g_PluginInfo.m_PluginType = PluginInfo::PT_EDITOR;
|
||||||
|
g_PluginInfo.m_PluginType = (PluginInfo::PLUGIN_TYPE)(g_PluginInfo.m_PluginType | PluginInfo::PTF_RECEIVENOTIFICATION);
|
||||||
|
g_PluginInfo.m_PluginCallback = PluginCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
PluginInfo* GetPluginInfo() {
|
||||||
|
return &g_PluginInfo;
|
||||||
|
}
|
||||||
|
PluginInterface* GetPluginInterface() {
|
||||||
|
return g_Plugininterface;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
28
materializer/PluginMain.hpp
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "stdafx.hpp"
|
||||||
|
|
||||||
|
namespace VSW::Materializer::PluginMain {
|
||||||
|
|
||||||
|
#ifdef MATERIALIZER_PLUGIN
|
||||||
|
|
||||||
|
class ConfigManager {
|
||||||
|
public:
|
||||||
|
static ConfigManager& GetSingleton();
|
||||||
|
private:
|
||||||
|
static YYCC::yycc_u8string GetConfigFilePath();
|
||||||
|
ConfigManager();
|
||||||
|
~ConfigManager();
|
||||||
|
|
||||||
|
public:
|
||||||
|
YYCC::ConfigManager::StringSetting m_LastFilePath;
|
||||||
|
YYCC::ConfigManager::NumberSetting<UINT> m_Encoding;
|
||||||
|
YYCC::ConfigManager::CoreManager m_Mgr;
|
||||||
|
};
|
||||||
|
|
||||||
|
void InitializePluginInfo();
|
||||||
|
PluginInfo* GetPluginInfo();
|
||||||
|
PluginInterface* GetPluginInterface();
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
263
materializer/StandaloneMain.cpp
Normal file
@@ -0,0 +1,263 @@
|
|||||||
|
#include "StandaloneMain.hpp"
|
||||||
|
#include "ExportCore.hpp"
|
||||||
|
#include "GenericHelper.hpp"
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
namespace VSW::Materializer::StandaloneMain {
|
||||||
|
|
||||||
|
#ifdef MATERIALIZER_STANDALONE
|
||||||
|
|
||||||
|
#pragma region Program Command Line Parser
|
||||||
|
|
||||||
|
struct CmdArguments {
|
||||||
|
CmdArguments() :
|
||||||
|
m_InputFilePath(),
|
||||||
|
m_ScriptDbPath(), m_DocumentDbPath(), m_EnvironmentDbPath(),
|
||||||
|
m_CodePage(CP_ACP) {}
|
||||||
|
YYCC::yycc_u8string m_InputFilePath;
|
||||||
|
YYCC::yycc_u8string m_ScriptDbPath, m_DocumentDbPath, m_EnvironmentDbPath;
|
||||||
|
UINT m_CodePage;
|
||||||
|
};
|
||||||
|
static YYCC::Constraints::Constraint<UINT> GetCodePageConstraint() {
|
||||||
|
return YYCC::Constraints::Constraint<UINT> {
|
||||||
|
[](const UINT& val) -> bool {
|
||||||
|
return YYCC::WinFctHelper::IsValidCodePage(val);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
class CmdParser {
|
||||||
|
public:
|
||||||
|
CmdParser() :
|
||||||
|
m_InputFilePath(YYCC_U8("input"), YYCC_U8_CHAR('i'), YYCC_U8("The path to Virtools file for exporting."), YYCC_U8("example.cmo"), true),
|
||||||
|
m_ScriptDbPath(YYCC_U8("script"), YYCC_U8_CHAR('s'), YYCC_U8("The path to exported script database. Input file is required."), YYCC_U8("script.db"), true),
|
||||||
|
m_DocumentDbPath(YYCC_U8("document"), YYCC_U8_CHAR('d'), YYCC_U8("The path to exported document database. Input file is required."), YYCC_U8("doc.db"), true),
|
||||||
|
m_EnvironmentDbPath(YYCC_U8("environment"), YYCC_U8_CHAR('e'), YYCC_U8("The path to exported environment database. Input file is not required."), YYCC_U8("env.db"), true),
|
||||||
|
m_CodePage(YYCC_U8("code-page"), YYCC_U8_CHAR('c'), YYCC_U8("The code page used when reading Virtools document."), YYCC_U8("1252"), true, GetCodePageConstraint()),
|
||||||
|
m_Version(YYCC_U8("version"), YYCC_U8_CHAR('v'), YYCC_U8("Print version infomation about this program and exit.")),
|
||||||
|
m_Help(YYCC_U8("help"), YYCC_U8_CHAR('h'), YYCC_U8("Print this help page and exit.")),
|
||||||
|
m_OptionContext(YYCC_U8("Virtools Schematic Weaver - Materializer"), YYCC_U8("The exporter of Virtools Schematic Weaver"), {
|
||||||
|
&m_InputFilePath,
|
||||||
|
&m_ScriptDbPath, &m_DocumentDbPath, &m_EnvironmentDbPath, &m_CodePage,
|
||||||
|
&m_Version, &m_Help
|
||||||
|
}) {}
|
||||||
|
~CmdParser() {}
|
||||||
|
YYCC_DEL_CLS_COPY_MOVE(CmdParser);
|
||||||
|
|
||||||
|
public:
|
||||||
|
YYCC::ArgParser::StringArgument m_InputFilePath;
|
||||||
|
YYCC::ArgParser::StringArgument m_ScriptDbPath;
|
||||||
|
YYCC::ArgParser::StringArgument m_DocumentDbPath;
|
||||||
|
YYCC::ArgParser::StringArgument m_EnvironmentDbPath;
|
||||||
|
YYCC::ArgParser::NumberArgument<UINT> m_CodePage;
|
||||||
|
|
||||||
|
YYCC::ArgParser::SwitchArgument m_Version;
|
||||||
|
YYCC::ArgParser::SwitchArgument m_Help;
|
||||||
|
|
||||||
|
YYCC::ArgParser::OptionContext m_OptionContext;
|
||||||
|
};
|
||||||
|
static bool ParseCmd(int argc, char* argv[], CmdArguments& captured) {
|
||||||
|
// fetch argument list
|
||||||
|
#if YYCC_OS == YYCC_OS_WINDOWS
|
||||||
|
auto al = YYCC::ArgParser::ArgumentList::CreateFromWin32();
|
||||||
|
#else
|
||||||
|
auto al = YYCC::ArgParser::ArgumentList::CreateFromStd(argc, argv);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// do parse
|
||||||
|
CmdParser parser;
|
||||||
|
if (!parser.m_OptionContext.Parse(al)) {
|
||||||
|
YYCC::ConsoleHelper::WriteLine(YYCC_U8(YYCC_COLOR_LIGHT_RED("Invalid command line.")));
|
||||||
|
parser.m_OptionContext.Help();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check help command
|
||||||
|
if (parser.m_Help.IsCaptured()) {
|
||||||
|
parser.m_OptionContext.Help();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// check version command
|
||||||
|
if (parser.m_Version.IsCaptured()) {
|
||||||
|
YYCC::ConsoleHelper::WriteLine(YYCC_U8("Virtools Schematic Weaver - Materializer v2.0.0"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check command relation
|
||||||
|
// if specify script or document export, user must provide input file
|
||||||
|
if (parser.m_ScriptDbPath.IsCaptured() || parser.m_DocumentDbPath.IsCaptured()) {
|
||||||
|
if (!parser.m_InputFilePath.IsCaptured()) {
|
||||||
|
YYCC::ConsoleHelper::WriteLine(YYCC_U8(YYCC_COLOR_LIGHT_RED("You must specify one input file if you want to export script or document.")));
|
||||||
|
parser.m_OptionContext.Help();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// setup argument
|
||||||
|
if (parser.m_InputFilePath.IsCaptured()) captured.m_InputFilePath = parser.m_InputFilePath.Get();
|
||||||
|
else captured.m_InputFilePath.clear();
|
||||||
|
if (parser.m_ScriptDbPath.IsCaptured()) captured.m_ScriptDbPath = parser.m_ScriptDbPath.Get();
|
||||||
|
else captured.m_ScriptDbPath.clear();
|
||||||
|
if (parser.m_DocumentDbPath.IsCaptured()) captured.m_DocumentDbPath = parser.m_DocumentDbPath.Get();
|
||||||
|
else captured.m_DocumentDbPath.clear();
|
||||||
|
if (parser.m_EnvironmentDbPath.IsCaptured()) captured.m_EnvironmentDbPath = parser.m_EnvironmentDbPath.Get();
|
||||||
|
else captured.m_EnvironmentDbPath.clear();
|
||||||
|
if (parser.m_CodePage.IsCaptured()) captured.m_CodePage = parser.m_CodePage.Get();
|
||||||
|
else captured.m_CodePage = CP_ACP;
|
||||||
|
// okey, return
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region Assistant Functions
|
||||||
|
|
||||||
|
class TemporaryFile {
|
||||||
|
public:
|
||||||
|
TemporaryFile(CKContext* ctx, const YYCC::yycc_u8string_view& u8_vt_file) :
|
||||||
|
m_IsSuccess(false), m_TempFile() {
|
||||||
|
if (ctx == nullptr) throw std::invalid_argument("Invalid CKContext");
|
||||||
|
if (u8_vt_file.empty()) throw std::invalid_argument("Invalid Virtools file path");
|
||||||
|
|
||||||
|
// build source virtools file
|
||||||
|
auto vt_file = YYCC::StdPatch::ToStdPath(u8_vt_file);
|
||||||
|
|
||||||
|
// build cache path located in Windows temp path and keep its extension
|
||||||
|
YYCC::yycc_u8string u8_temp_dir;
|
||||||
|
if (!YYCC::WinFctHelper::GetTempDirectory(u8_temp_dir))
|
||||||
|
throw std::runtime_error("Fail to fetch Windows Temp directory");
|
||||||
|
auto temp_dir = YYCC::StdPatch::ToStdPath(u8_temp_dir);
|
||||||
|
temp_dir /= YYCC::StdPatch::ToStdPath(YYCC_U8("07159749-81e5-4ec2-b649-87b8eb9c1f5a"));
|
||||||
|
temp_dir.replace_extension(vt_file.extension());
|
||||||
|
m_TempFile = YYCC::StdPatch::ToUTF8Path(temp_dir);
|
||||||
|
|
||||||
|
// copy it to temp directory
|
||||||
|
if (!YYCC::WinFctHelper::CopyFile(u8_vt_file, m_TempFile, FALSE))
|
||||||
|
throw std::runtime_error("Fail to copy file.");
|
||||||
|
|
||||||
|
// okey
|
||||||
|
m_IsSuccess = true;
|
||||||
|
}
|
||||||
|
~TemporaryFile() {
|
||||||
|
if (m_IsSuccess) {
|
||||||
|
std::wstring w_temp_file;
|
||||||
|
if (!YYCC::EncodingHelper::UTF8ToWchar(m_TempFile, w_temp_file)) return;
|
||||||
|
::DeleteFileW(w_temp_file.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TemporaryFile(TemporaryFile&& rhs) :
|
||||||
|
m_IsSuccess(rhs.m_IsSuccess), m_TempFile(rhs.m_TempFile) {
|
||||||
|
rhs.m_IsSuccess = false;
|
||||||
|
rhs.m_TempFile.clear();
|
||||||
|
}
|
||||||
|
TemporaryFile& operator=(TemporaryFile&& rhs) {
|
||||||
|
this->m_IsSuccess = rhs.m_IsSuccess;
|
||||||
|
this->m_TempFile = rhs.m_TempFile;
|
||||||
|
rhs.m_IsSuccess = false;
|
||||||
|
rhs.m_TempFile.clear();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
YYCC_DEL_CLS_COPY(TemporaryFile);
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool IsSuccess() const { return m_IsSuccess; }
|
||||||
|
const YYCC::yycc_u8string& GetPath() const { return m_TempFile; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_IsSuccess;
|
||||||
|
YYCC::yycc_u8string m_TempFile;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void CustomAssert(VSW::Reporter& reporter, bool condition, const YYCC::yycc_char8_t* msg) {
|
||||||
|
if (!condition) {
|
||||||
|
if (msg != nullptr)
|
||||||
|
reporter.Err(msg);
|
||||||
|
std::abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#define CUSTOM_ASSERT(condition, msg) CustomAssert(reporter, (condition), YYCC_U8(msg))
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
void PlayerMain(int argc, char* argv[]) {
|
||||||
|
// ========== Check Passed Arguments ==========
|
||||||
|
CmdArguments captured;
|
||||||
|
if (!ParseCmd(argc, argv, captured)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== Print Header ==========
|
||||||
|
YYCC::ConsoleHelper::WriteLine(YYCC_U8("Virtools Schematic Weaver - Materializer"));
|
||||||
|
YYCC::ConsoleHelper::WriteLine(YYCC_U8("Homepage: https://github.com/yyc12345/SuperScriptMaterializer"));
|
||||||
|
YYCC::ConsoleHelper::WriteLine(YYCC_U8("Report bug: https://github.com/yyc12345/SuperScriptMaterializer/issues"));
|
||||||
|
|
||||||
|
// ========== Init CK2 Engine ==========
|
||||||
|
// Prepare reporter
|
||||||
|
VSW::Reporter reporter;
|
||||||
|
|
||||||
|
CUSTOM_ASSERT(CKStartUp() == CK_OK, "CKStartUp() Error");
|
||||||
|
CKPluginManager* plugin_mgr = CKGetPluginManager();
|
||||||
|
CUSTOM_ASSERT(plugin_mgr != nullptr, "CKPluginManager is nullptr");
|
||||||
|
CUSTOM_ASSERT(plugin_mgr->ParsePlugins("RenderEngines") > 0, "Error loading RenderEngines");
|
||||||
|
CUSTOM_ASSERT(plugin_mgr->ParsePlugins("Managers") > 0, "Error loading Managers");
|
||||||
|
CUSTOM_ASSERT(plugin_mgr->ParsePlugins("BuildingBlocks") > 0, "Error loading BuildingBlocks");
|
||||||
|
CUSTOM_ASSERT(plugin_mgr->ParsePlugins("Plugins") > 0, "Error loading Plugins");
|
||||||
|
|
||||||
|
// ========== Create CKContext ==========
|
||||||
|
CKContext* ctx = nullptr;
|
||||||
|
#if defined(VIRTOOLS_21)
|
||||||
|
CUSTOM_ASSERT(CKCreateContext(&ctx, NULL, 0, 0) == CK_OK, "CKCreateContext Error");
|
||||||
|
#else
|
||||||
|
CUSTOM_ASSERT(CKCreateContext(&ctx, NULL) == CK_OK, "CKCreateContext Error");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ========== Load File ==========
|
||||||
|
std::optional<TemporaryFile> loaded_file;
|
||||||
|
CKObjectArray* loaded_file_objs = CreateCKObjectArray();
|
||||||
|
if (!captured.m_InputFilePath.empty()) {
|
||||||
|
TemporaryFile cache(ctx, captured.m_InputFilePath);
|
||||||
|
if (cache.IsSuccess()) {
|
||||||
|
std::string temp_file;
|
||||||
|
if (YYCC::EncodingHelper::UTF8ToChar(cache.GetPath(), temp_file, CP_ACP)) {
|
||||||
|
if (ctx->Load(const_cast<CKSTRING>(temp_file.c_str()), loaded_file_objs) == CK_OK) {
|
||||||
|
loaded_file = std::move(cache);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CUSTOM_ASSERT(loaded_file.has_value(), "Fail to open specified file.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== Export Data ==========
|
||||||
|
if (!captured.m_ScriptDbPath.empty()) {
|
||||||
|
reporter.Info(YYCC_U8("Exporting script database..."));
|
||||||
|
ExportScript::Export(ctx, captured.m_ScriptDbPath, captured.m_CodePage);
|
||||||
|
}
|
||||||
|
if (!captured.m_DocumentDbPath.empty()) {
|
||||||
|
reporter.Info(YYCC_U8("Exporting document database..."));
|
||||||
|
ExportDocument::Export(ctx, captured.m_DocumentDbPath, captured.m_CodePage);
|
||||||
|
}
|
||||||
|
if (!captured.m_EnvironmentDbPath.empty()) {
|
||||||
|
reporter.Info(YYCC_U8("Exporting environment database..."));
|
||||||
|
ExportEnvironment::Export(ctx, captured.m_EnvironmentDbPath, captured.m_CodePage);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== Unload File and Clear CKContext ==========
|
||||||
|
DeleteCKObjectArray(loaded_file_objs);
|
||||||
|
loaded_file.reset();
|
||||||
|
ctx->Reset();
|
||||||
|
ctx->ClearAll();
|
||||||
|
|
||||||
|
// ========== Destroy CKContext ==========
|
||||||
|
// todo: Virtools 4.0 standalone version throw exception in there, but i don't know why
|
||||||
|
// but it doesn't affect SSMaterializerDatabase export, perhaps
|
||||||
|
CKCloseContext(ctx);
|
||||||
|
|
||||||
|
// ========== Shutdown CK2 Engine ==========
|
||||||
|
CKShutdown();
|
||||||
|
|
||||||
|
// todo: Virtools 2.5 standalone version throw exception in there, but i don't know why
|
||||||
|
// but it doesn't affect SSMaterializerDatabase export, perhaps
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
10
materializer/StandaloneMain.hpp
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "stdafx.hpp"
|
||||||
|
|
||||||
|
namespace VSW::Materializer::StandaloneMain {
|
||||||
|
|
||||||
|
#ifdef MATERIALIZER_STANDALONE
|
||||||
|
void PlayerMain(int argc, char* argv[]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
204
materializer/Utilities.cpp
Normal file
@@ -0,0 +1,204 @@
|
|||||||
|
#include "Utilities.hpp"
|
||||||
|
|
||||||
|
namespace VSW::Materializer::Utilities {
|
||||||
|
|
||||||
|
#pragma region Enhanced Reporter
|
||||||
|
|
||||||
|
EnhancedReporter::EnhancedReporter(CKContext* ctx) :
|
||||||
|
m_Ctx(ctx), m_OrderBeep(false) {}
|
||||||
|
|
||||||
|
EnhancedReporter::~EnhancedReporter() {}
|
||||||
|
|
||||||
|
void EnhancedReporter::EnableBeep() { m_OrderBeep = true; }
|
||||||
|
|
||||||
|
void EnhancedReporter::DisableBeep() { m_OrderBeep = false; }
|
||||||
|
|
||||||
|
void EnhancedReporter::PrePrint(const YYCC::yycc_char8_t* strl) const {
|
||||||
|
// only write when CKContext is not nullptr and we are in Interface Mode (Dev mode).
|
||||||
|
if (m_Ctx != nullptr && m_Ctx->IsInInterfaceMode())
|
||||||
|
m_Ctx->OutputToConsole(const_cast<CKSTRING>(YYCC::EncodingHelper::UTF8ToChar(strl, CP_ACP).c_str()), m_OrderBeep);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region Curve 2D Builder
|
||||||
|
|
||||||
|
Curve2DBuilder::Curve2DBuilder(CK2dCurve* curve_2d) : m_Cache() {
|
||||||
|
BuildCurve(curve_2d);
|
||||||
|
}
|
||||||
|
|
||||||
|
Curve2DBuilder::~Curve2DBuilder() {}
|
||||||
|
|
||||||
|
const void* Curve2DBuilder::GetDataPtr() const { return m_Cache.c_str(); }
|
||||||
|
size_t Curve2DBuilder::GetDataLength() const { return m_Cache.size(); }
|
||||||
|
|
||||||
|
void Curve2DBuilder::BuildCurve(CK2dCurve* c) {
|
||||||
|
// check curve
|
||||||
|
if (c == nullptr) return;
|
||||||
|
// get curve control point count
|
||||||
|
int cp_count = c->GetControlPointCount();
|
||||||
|
// reserve enough space
|
||||||
|
// count * (x + y + is_linear + is_tcb + (io_tangent_tuple / tcb_tuple))
|
||||||
|
m_Cache.reserve(static_cast<size_t>(cp_count) * (sizeof(float) * 2u + sizeof(float) * 4u + sizeof(uint32_t) + sizeof(uint32_t)));
|
||||||
|
|
||||||
|
// iterate control point
|
||||||
|
for (int i = 0; i < cp_count; ++i) {
|
||||||
|
BuildCurvePoint(c->GetControlPoint(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Curve2DBuilder::BuildCurvePoint(CK2dCurvePoint* cp) {
|
||||||
|
// check control point
|
||||||
|
if (cp == nullptr) return;
|
||||||
|
// prepare variable
|
||||||
|
uint32_t int_cache;
|
||||||
|
Vx2DVector vector_cache;
|
||||||
|
float float_cache;
|
||||||
|
|
||||||
|
#define APPEND_DATA(data) m_Cache.append(reinterpret_cast<decltype(m_Cache)::value_type*>(&data), sizeof(data))
|
||||||
|
|
||||||
|
// x y value
|
||||||
|
vector_cache = cp->GetPosition();
|
||||||
|
APPEND_DATA(vector_cache);
|
||||||
|
|
||||||
|
// is linear
|
||||||
|
int_cache = static_cast<uint32_t>(cp->IsLinear());
|
||||||
|
APPEND_DATA(int_cache);
|
||||||
|
// is tcb
|
||||||
|
int_cache = static_cast<uint32_t>(cp->IsTCB());
|
||||||
|
APPEND_DATA(int_cache);
|
||||||
|
|
||||||
|
if (cp->IsTCB()) {
|
||||||
|
// TCB control point
|
||||||
|
float_cache = cp->GetTension();
|
||||||
|
APPEND_DATA(float_cache);
|
||||||
|
float_cache = cp->GetContinuity();
|
||||||
|
APPEND_DATA(float_cache);
|
||||||
|
float_cache = cp->GetBias();
|
||||||
|
APPEND_DATA(float_cache);
|
||||||
|
// To keep balance with non-TCB control point,
|
||||||
|
// We add a blank 0.0f in there
|
||||||
|
float_cache = 0.0f;
|
||||||
|
APPEND_DATA(float_cache);
|
||||||
|
} else {
|
||||||
|
// non-TCB control point
|
||||||
|
vector_cache = cp->GetInTangent();
|
||||||
|
APPEND_DATA(vector_cache);
|
||||||
|
vector_cache = cp->GetOutTangent();
|
||||||
|
APPEND_DATA(vector_cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef APPEND_DATA
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
void RelativeAddress(const EnhancedReporter& reporter, YYCC::yycc_u8string& relative_addr_str, const void* absolute_addr) {
|
||||||
|
// If address is nullptr, return directly
|
||||||
|
if (absolute_addr == nullptr) {
|
||||||
|
relative_addr_str = YYCC_U8("<nullptr>");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the module handle which given function address belongs to
|
||||||
|
// Reference: https://stackoverflow.com/questions/557081/how-do-i-get-the-hmodule-for-the-currently-executing-code
|
||||||
|
HMODULE hModule = NULL;
|
||||||
|
GetModuleHandleExW(
|
||||||
|
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, // get address and do not inc ref counter.
|
||||||
|
(LPCWSTR)absolute_addr,
|
||||||
|
&hModule);
|
||||||
|
if (hModule == NULL) {
|
||||||
|
reporter.ErrF(YYCC_U8("Fail to get module of given absolute address 0x%" PRI_XPTR_LEFT_PADDING PRIXPTR ". Some relative address may be empty."), absolute_addr);
|
||||||
|
relative_addr_str.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get full path to module
|
||||||
|
YYCC::yycc_u8string u8_module_path;
|
||||||
|
if (!YYCC::WinFctHelper::GetModuleFileName(hModule, u8_module_path)) {
|
||||||
|
reporter.ErrF(YYCC_U8("Fail to get file name of given module 0x%" PRI_XPTR_LEFT_PADDING PRIXPTR ". Some relative address may be empty."), hModule);
|
||||||
|
relative_addr_str.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Then get its file name part
|
||||||
|
auto module_path = YYCC::StdPatch::ToStdPath(u8_module_path);
|
||||||
|
auto u8_module_name = YYCC::StdPatch::ToUTF8Path(module_path.filename());
|
||||||
|
|
||||||
|
// Get the base address of current module
|
||||||
|
// HMODULE is the base address of loaded module
|
||||||
|
// Reference: https://stackoverflow.com/questions/4298331/exe-or-dll-image-base-address
|
||||||
|
uintptr_t relative_addr = reinterpret_cast<uintptr_t>(absolute_addr) - reinterpret_cast<uintptr_t>(hModule);
|
||||||
|
|
||||||
|
// get final result
|
||||||
|
if (!YYCC::StringHelper::Printf(relative_addr_str, YYCC_U8("%s+0x%" PRI_XPTR_LEFT_PADDING PRIXPTR), u8_module_name.c_str(), relative_addr)) {
|
||||||
|
reporter.Err(YYCC_U8("Fail to format relative address. Some relative address may be empty."));
|
||||||
|
relative_addr_str.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//void GetBase64(YYCC::yycc_u8string& dst, const char* data, size_t data_len) {
|
||||||
|
// // Reference: https://stackoverflow.com/questions/342409/how-do-i-base64-encode-decode-in-c
|
||||||
|
// static const YYCC::yycc_char8_t* BASE64_TABLE = YYCC_U8("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
|
||||||
|
// static const int MOD_TABLE[] = { 0, 2, 1 };
|
||||||
|
|
||||||
|
// // compute size
|
||||||
|
// size_t output_length = 4u * ((data_len + 2u) / 3u);
|
||||||
|
// dst.resize(output_length);
|
||||||
|
|
||||||
|
// // compute
|
||||||
|
// for (size_t i = 0, j = 0; i < data_len;) {
|
||||||
|
|
||||||
|
// uint32_t octet_a = i < data_len ? (unsigned char)data[i++] : 0;
|
||||||
|
// uint32_t octet_b = i < data_len ? (unsigned char)data[i++] : 0;
|
||||||
|
// uint32_t octet_c = i < data_len ? (unsigned char)data[i++] : 0;
|
||||||
|
|
||||||
|
// uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
|
||||||
|
|
||||||
|
// dst[j++] = BASE64_TABLE[(triple >> 3 * 6) & 0x3F];
|
||||||
|
// dst[j++] = BASE64_TABLE[(triple >> 2 * 6) & 0x3F];
|
||||||
|
// dst[j++] = BASE64_TABLE[(triple >> 1 * 6) & 0x3F];
|
||||||
|
// dst[j++] = BASE64_TABLE[(triple >> 0 * 6) & 0x3F];
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // fill blank
|
||||||
|
// for (int i = 0; i < MOD_TABLE[data_len % 3]; i++)
|
||||||
|
// dst[output_length - 1 - i] = '=';
|
||||||
|
//}
|
||||||
|
|
||||||
|
void CopyStrGuid(const EnhancedReporter& reporter, YYCC::yycc_u8string& dst, const CKGUID& src) {
|
||||||
|
if (!YYCC::StringHelper::Printf(dst, YYCC_U8("<0x%08" PRIX32 ", 0x%08" PRIX32 ">"), src.d1, src.d2)) {
|
||||||
|
reporter.Err(YYCC_U8("Fail to format CKGUID. Some stringified GUID may be empty."));
|
||||||
|
dst.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CopyGuid(int64_t& dst, const CKGUID& src) {
|
||||||
|
// reset dst to zero
|
||||||
|
uint64_t* pdst = reinterpret_cast<uint64_t*>(&dst);
|
||||||
|
// CKGUID.d1 to high 32 bits
|
||||||
|
*pdst = static_cast<uint64_t>(src.d1);
|
||||||
|
*pdst <<= 32u;
|
||||||
|
// CKGUID.d2 to low 32 bits
|
||||||
|
*pdst = (*pdst) | static_cast<uint64_t>(src.d2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CopyCKString(const EnhancedReporter& reporter, YYCC::yycc_u8string& storage, const char* str, UINT code_page, const YYCC::yycc_char8_t* fallback) {
|
||||||
|
// check whether callback is nullptr.
|
||||||
|
if (fallback == nullptr)
|
||||||
|
throw std::invalid_argument("fallback string should not be nullptr!");
|
||||||
|
|
||||||
|
// if given string is nullptr, use fallback instead
|
||||||
|
if (str == nullptr) {
|
||||||
|
storage = fallback;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise do encoding convertion of original string.
|
||||||
|
if (!YYCC::EncodingHelper::CharToUTF8(str, storage, code_page)) {
|
||||||
|
reporter.Err(YYCC_U8("Fail to convert encoding. Some string may use fallback string accidently."));
|
||||||
|
storage = fallback;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
73
materializer/Utilities.hpp
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "stdafx.hpp"
|
||||||
|
#include <GenericHelper.hpp>
|
||||||
|
|
||||||
|
namespace VSW::Materializer::Utilities {
|
||||||
|
|
||||||
|
/// @brief The value representing a invalid CK_ID.
|
||||||
|
constexpr CK_ID INVALID_CK_ID = static_cast<CK_ID>(-1);
|
||||||
|
constexpr int INVALID_INDEX = static_cast<int>(-1);
|
||||||
|
constexpr char NULLPTR_CKSTRING[] = "<null>";
|
||||||
|
|
||||||
|
class EnhancedReporter : public VSW::Reporter {
|
||||||
|
public:
|
||||||
|
EnhancedReporter(CKContext* ctx);
|
||||||
|
~EnhancedReporter();
|
||||||
|
|
||||||
|
public:
|
||||||
|
void EnableBeep();
|
||||||
|
void DisableBeep();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void PrePrint(const YYCC::yycc_char8_t* strl) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
CKContext* m_Ctx;
|
||||||
|
bool m_OrderBeep;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Curve2DBuilder {
|
||||||
|
public:
|
||||||
|
Curve2DBuilder(CK2dCurve* curve_2d);
|
||||||
|
~Curve2DBuilder();
|
||||||
|
|
||||||
|
public:
|
||||||
|
const void* GetDataPtr() const;
|
||||||
|
size_t GetDataLength() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void BuildCurve(CK2dCurve* c);
|
||||||
|
void BuildCurvePoint(CK2dCurvePoint* cp);
|
||||||
|
std::basic_string<uint8_t> m_Cache;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get relative address from given absolute address
|
||||||
|
* @details This function is used when exporting function pointer into database.
|
||||||
|
* @param[out] relative_addr_str
|
||||||
|
* The variable holding relative address result.
|
||||||
|
* The result is module based relative address like \c xxx.dll+0x00000000.
|
||||||
|
* @param[in] absolute_addr The absolute address
|
||||||
|
*/
|
||||||
|
void RelativeAddress(const EnhancedReporter& reporter, YYCC::yycc_u8string& relative_addr_str, const void* absolute_addr);
|
||||||
|
void CopyStrGuid(const EnhancedReporter& reporter, YYCC::yycc_u8string& dst, const CKGUID& src);
|
||||||
|
void CopyGuid(int64_t& dst, const CKGUID& src);
|
||||||
|
void CopyCKString(
|
||||||
|
const EnhancedReporter& reporter,
|
||||||
|
YYCC::yycc_u8string& storage,
|
||||||
|
const char* str,
|
||||||
|
UINT code_page,
|
||||||
|
const YYCC::yycc_char8_t* fallback = YYCC::EncodingHelper::ToUTF8(NULLPTR_CKSTRING)
|
||||||
|
);
|
||||||
|
|
||||||
|
#pragma region Convenient Macros
|
||||||
|
|
||||||
|
#define CP_ADDR(dst, src) ::VSW::Materializer::Utilities::RelativeAddress(expctx.reporter, (dst), (src))
|
||||||
|
#define CP_STR_GUID(dst, src) ::VSW::Materializer::Utilities::CopyStrGuid(expctx.reporter, (dst), (src))
|
||||||
|
#define CP_GUID(dst, src) ::VSW::Materializer::Utilities::CopyGuid((dst), (src))
|
||||||
|
#define CP_CKSTR(dst, src, ...) ::VSW::Materializer::Utilities::CopyCKString(expctx.reporter, (dst), (src), expctx.cp, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
71
materializer/main.cpp
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
#include "stdafx.hpp"
|
||||||
|
#include "PluginMain.hpp"
|
||||||
|
#include "StandaloneMain.hpp"
|
||||||
|
|
||||||
|
#if defined(MATERIALIZER_PLUGIN)
|
||||||
|
|
||||||
|
int GetVirtoolsPluginInfoCount() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
PluginInfo* GetVirtoolsPluginInfo(int index) {
|
||||||
|
switch (index) {
|
||||||
|
case 0:
|
||||||
|
return VSW::Materializer::PluginMain::GetPluginInfo();
|
||||||
|
default:
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CMaterializer : CWinApp {
|
||||||
|
public:
|
||||||
|
virtual BOOL InitInstance() override {
|
||||||
|
// register unhandler exception handler
|
||||||
|
#ifdef MATERIALIZER_RELEASE
|
||||||
|
YYCC::ExceptionHelper::Register(vtobjplugin::VirtoolsMenu::UnhandledExceptionCallback);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// load config from file
|
||||||
|
auto& config_manager = VSW::Materializer::PluginMain::ConfigManager::GetSingleton();
|
||||||
|
config_manager.m_Mgr.Load();
|
||||||
|
|
||||||
|
// init plugin info
|
||||||
|
VSW::Materializer::PluginMain::InitializePluginInfo();
|
||||||
|
|
||||||
|
return CWinApp::InitInstance();
|
||||||
|
}
|
||||||
|
virtual int ExitInstance() override {
|
||||||
|
// save config to file
|
||||||
|
auto& config_manager = VSW::Materializer::PluginMain::ConfigManager::GetSingleton();
|
||||||
|
config_manager.m_Mgr.Save();
|
||||||
|
|
||||||
|
// unregister unhandler exception handler
|
||||||
|
#ifdef MATERIALIZER_RELEASE
|
||||||
|
YYCC::ExceptionHelper::Unregister();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return CWinApp::ExitInstance();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
CMaterializer theApp;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
// register unhandler exception handler
|
||||||
|
#ifdef MATERIALIZER_RELEASE
|
||||||
|
YYCC::ExceptionHelper::Register(vtobjplugin::VirtoolsMenu::UnhandledExceptionCallback);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Run core code.
|
||||||
|
VSW::Materializer::StandaloneMain::PlayerMain(argc, argv);
|
||||||
|
|
||||||
|
// unregister unhandler exception handler
|
||||||
|
#ifdef MATERIALIZER_RELEASE
|
||||||
|
YYCC::ExceptionHelper::Unregister();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
21
materializer/resource.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
//{{NO_DEPENDENCIES}}
|
||||||
|
// Microsoft Visual C++ generated include file.
|
||||||
|
// Used by RCEditor.rc
|
||||||
|
//
|
||||||
|
#define IDD_EXPORT_DIALOG 101
|
||||||
|
#define IDC_EDIT1 1001
|
||||||
|
#define IDC_BUTTON1 1002
|
||||||
|
#define IDC_RADIO1 1003
|
||||||
|
#define IDC_RADIO2 1004
|
||||||
|
#define IDC_EDIT2 1005
|
||||||
|
|
||||||
|
// Next default values for new objects
|
||||||
|
//
|
||||||
|
#ifdef APSTUDIO_INVOKED
|
||||||
|
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||||
|
#define _APS_NEXT_RESOURCE_VALUE 103
|
||||||
|
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||||
|
#define _APS_NEXT_CONTROL_VALUE 1006
|
||||||
|
#define _APS_NEXT_SYMED_VALUE 101
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
76
materializer/stdafx.hpp
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
// stdafx.h : include file for standard system include files,
|
||||||
|
// or project specific include files that are used frequently, but
|
||||||
|
// are changed infrequently
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Check build macros
|
||||||
|
#if !defined(MATERIALIZER_PLUGIN) && !defined(MATERIALIZER_STANDALONE)
|
||||||
|
#error "You must define one of MATERIALIZER_PLUGIN or MATERIALIZER_STANDALONE to represent the build type of materializer!"
|
||||||
|
#endif
|
||||||
|
#if !defined(MATERIALIZER_DEBUG) && !defined(MATERIALIZER_RELEASE)
|
||||||
|
#error "You must define one of MATERIALIZER_DEBUG or MATERIALIZER_RELEASE!"
|
||||||
|
#endif
|
||||||
|
#if !defined(VIRTOOLS_50) && !defined(VIRTOOLS_40) && !defined(VIRTOOLS_35) && !defined(VIRTOOLS_30) && !defined(VIRTOOLS_25) && !defined(VIRTOOLS_21)
|
||||||
|
#error "Lost essential Virtools version macro!"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#pragma region Windows and Virtools
|
||||||
|
#include <WinImportPrefix.hpp>
|
||||||
|
|
||||||
|
#pragma region Windows Headers
|
||||||
|
|
||||||
|
#include <SDKDDKVer.h>
|
||||||
|
|
||||||
|
// Only plugin mode involve MFC headers
|
||||||
|
#if defined(MATERIALIZER_PLUGIN)
|
||||||
|
#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 database classes
|
||||||
|
#endif // _AFX_NO_DB_SUPPORT
|
||||||
|
|
||||||
|
#ifndef _AFX_NO_DAO_SUPPORT
|
||||||
|
#include <afxdao.h> // MFC DAO database 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
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region Virtools Headers
|
||||||
|
|
||||||
|
#include "CKAll.h"
|
||||||
|
|
||||||
|
// Only plugi mode need include extra headers
|
||||||
|
#if defined(MATERIALIZER_PLUGIN)
|
||||||
|
#include "VIControls.h"
|
||||||
|
#include "CKControlsAll.h"
|
||||||
|
#include "VEP_ScriptActionMenu.h"
|
||||||
|
#include "VEP_KeyboardShortcutManager.h"
|
||||||
|
#include "VEP_All.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#include <WinImportSuffix.hpp>
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region YYCC Headers
|
||||||
|
#include <YYCCommonplace.hpp>
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
BIN
preview.png
|
Before Width: | Height: | Size: 342 KiB |
10
script/build.bat
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
MKDIR bin
|
||||||
|
CD bin
|
||||||
|
|
||||||
|
cmake -G "Visual Studio 16 2019" -A Win32 -DVSW_BUILD_MATERIALIZER=ON -DVSW_BUILD_DECORATOR=OFF -DMATERIALIZER_BUILD_TYPE=plugin -DVIRTOOLS_VERSION=50 -DVIRTOOLS_PATH="E:\Virtools\Virtools Dev 5.0" -DSQLITE_AMALGAMATION_PATH="D:\CppLib\SQLite\sqlite-amalgamation-3450300" -DSQLITE_DLL_PATH="D:\CppLib\SQLite\sqlite-dll-win-x86-3450300" -DYYCC_PATH="J:\YYCCommonplace\bin\install\Win32_Debug" ../..
|
||||||
|
cmake --build . --config Debug
|
||||||
|
cmake -G "Visual Studio 16 2019" -A Win32 -DVSW_BUILD_MATERIALIZER=OFF -DVSW_BUILD_DECORATOR=ON -DSQLITE_AMALGAMATION_PATH="D:\CppLib\SQLite\sqlite-amalgamation-3450300" -DSQLITE_DLL_PATH="D:\CppLib\SQLite\sqlite-dll-win-x86-3450300" -DYYCC_PATH="J:\YYCCommonplace\bin\install\Win32_Debug" ../..
|
||||||
|
cmake --build . --config Debug
|
||||||
|
|
||||||
|
CD ..
|
||||||
|
ECHO Build Done!
|
||||||
153
script/sqlite_helper.py
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
import typing
|
||||||
|
import re
|
||||||
|
|
||||||
|
class FieldDecl():
|
||||||
|
c_EnumTuple: typing.ClassVar[tuple[str, ...]] = (
|
||||||
|
'VSW::DataTypes::ParameterLinkIOType',
|
||||||
|
'VSW::DataTypes::BehaviorLinkIOType'
|
||||||
|
)
|
||||||
|
|
||||||
|
m_DeclType: str
|
||||||
|
m_DeclName: str
|
||||||
|
|
||||||
|
def __init__(self, decl_type: str, decl_name: str):
|
||||||
|
self.m_DeclType = decl_type
|
||||||
|
self.m_DeclName = decl_name
|
||||||
|
|
||||||
|
def is_bool(self):
|
||||||
|
return self.m_DeclType == 'bool'
|
||||||
|
|
||||||
|
def is_string(self):
|
||||||
|
return self.m_DeclType == 'YYCC::yycc_u8string'
|
||||||
|
|
||||||
|
def is_blob(self):
|
||||||
|
return self.m_DeclType == 'BlobDescriptor'
|
||||||
|
|
||||||
|
def is_int64(self):
|
||||||
|
return self.m_DeclType == 'int64_t'
|
||||||
|
|
||||||
|
def is_enum(self):
|
||||||
|
return self.m_DeclType in FieldDecl.c_EnumTuple
|
||||||
|
|
||||||
|
class StructDecl():
|
||||||
|
m_StructName: str
|
||||||
|
m_StructFields: tuple[FieldDecl, ...]
|
||||||
|
|
||||||
|
def __init__(self, name: str, fields: tuple[FieldDecl, ...]):
|
||||||
|
self.m_StructName = name
|
||||||
|
self.m_StructFields = fields
|
||||||
|
|
||||||
|
def accept_input() -> str:
|
||||||
|
cache: list[str] = list()
|
||||||
|
blank_line: bool = False
|
||||||
|
|
||||||
|
while True:
|
||||||
|
recv: str = input("> ")
|
||||||
|
if len(recv) == 0:
|
||||||
|
# If double blank line, exit
|
||||||
|
# Otherwise set blank line flag
|
||||||
|
if blank_line: break
|
||||||
|
else: blank_line = True
|
||||||
|
else:
|
||||||
|
# Reset blank line flag
|
||||||
|
blank_line = False
|
||||||
|
cache.append(recv)
|
||||||
|
|
||||||
|
return '\n'.join(cache)
|
||||||
|
|
||||||
|
def analyse_input(val: str) -> tuple[StructDecl, ...]:
|
||||||
|
# result container
|
||||||
|
ret: list[StructDecl] = list()
|
||||||
|
# regex for capturing struct declarations
|
||||||
|
struct_matcher: re.Pattern = re.compile('struct[ \t]+([a-zA-Z0-9_]+)[ \t]+{([^}]*)};')
|
||||||
|
# regex for capturing struct field declarations
|
||||||
|
field_matcher: re.Pattern = re.compile('([a-zA-Z0-9_:]+)[ \t]+([a-zA-Z0-9_]+)[ \t]*;')
|
||||||
|
|
||||||
|
# capture struct declaration part
|
||||||
|
found_match: re.Match
|
||||||
|
for found_match in struct_matcher.finditer(val):
|
||||||
|
# get struct name
|
||||||
|
struct_name: str = found_match.group(1)
|
||||||
|
# analyse struct body
|
||||||
|
struct_body: str = found_match.group(2)
|
||||||
|
struct_fields: list[FieldDecl] = []
|
||||||
|
for ln in struct_body.split('\n'):
|
||||||
|
# Skip annotation
|
||||||
|
ln = ln.strip()
|
||||||
|
if ln.startswith('//'): continue
|
||||||
|
# Check whether it is declaration
|
||||||
|
found_field_match: re.Match = field_matcher.match(ln)
|
||||||
|
if found_field_match is not None:
|
||||||
|
field_decl_type: str = found_field_match.group(1)
|
||||||
|
field_decl_name: str = found_field_match.group(2)
|
||||||
|
struct_fields.append(FieldDecl(field_decl_type, field_decl_name))
|
||||||
|
# add into result
|
||||||
|
ret.append(StructDecl(struct_name, tuple(struct_fields)))
|
||||||
|
|
||||||
|
return tuple(ret)
|
||||||
|
|
||||||
|
def output_result(decls: tuple[StructDecl, ...]) -> None:
|
||||||
|
# assistant function for sql create table statement
|
||||||
|
def conv_sql_create_table(decl_pair: FieldDecl) -> str:
|
||||||
|
if decl_pair.is_string(): return f'[{decl_pair.m_DeclName}] TEXT'
|
||||||
|
elif decl_pair.is_blob(): return f'[{decl_pair.m_DeclName}] BLOB'
|
||||||
|
else: return f'[{decl_pair.m_DeclName}] INTEGER'
|
||||||
|
# assistant function for sql insert statement
|
||||||
|
def conv_sql_insert(decl_pair: FieldDecl) -> str:
|
||||||
|
return '?'
|
||||||
|
# assistant function for c++ bind statement
|
||||||
|
def conv_cpp(decl_pair: FieldDecl) -> str:
|
||||||
|
if decl_pair.is_string():
|
||||||
|
return f'WRITER_BIND(sqlite3_bind_text(WRITER_STMT, WRITER_INDEX, REVEAL_U8STR(data.{decl_pair.m_DeclName})));'
|
||||||
|
elif decl_pair.is_int64():
|
||||||
|
return f'WRITER_BIND(sqlite3_bind_int64(WRITER_STMT, WRITER_INDEX, data.{decl_pair.m_DeclName}));'
|
||||||
|
elif decl_pair.is_blob():
|
||||||
|
return f'WRITER_BIND(sqlite3_bind_blob(WRITER_STMT, WRITER_INDEX, REVEAL_BLOB(data.{decl_pair.m_DeclName})));'
|
||||||
|
elif decl_pair.is_enum():
|
||||||
|
return f'WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, REVEAL_ENUM(data.{decl_pair.m_DeclName})));'
|
||||||
|
elif decl_pair.is_bool():
|
||||||
|
return f'WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, REVEAL_BOOL(data.{decl_pair.m_DeclName})));'
|
||||||
|
else:
|
||||||
|
return f'WRITER_BIND(sqlite3_bind_int(WRITER_STMT, WRITER_INDEX, data.{decl_pair.m_DeclName}));'
|
||||||
|
|
||||||
|
ret_sql_drop_table: list[str] = []
|
||||||
|
ret_sql_create_table: list[str] = []
|
||||||
|
ret_sql_insert: list[str] = []
|
||||||
|
ret_cpp_bind: list[tuple[str, str]] = []
|
||||||
|
for struct_decl in decls:
|
||||||
|
# generate drop table statement
|
||||||
|
gen_statement: str = f'DROP TABLE IF EXISTS [{struct_decl.m_StructName}];'
|
||||||
|
ret_sql_drop_table.append(gen_statement)
|
||||||
|
|
||||||
|
# generate sql create table statement
|
||||||
|
table_string: str = ', '.join(map(conv_sql_create_table, struct_decl.m_StructFields))
|
||||||
|
gen_statement = f'CREATE TABLE [{struct_decl.m_StructName}] ({table_string});'
|
||||||
|
ret_sql_create_table.append(gen_statement)
|
||||||
|
|
||||||
|
# generate sql insert statement
|
||||||
|
table_string = ', '.join(map(conv_sql_insert, struct_decl.m_StructFields))
|
||||||
|
gen_statement = f'INSERT INTO [{struct_decl.m_StructName}] VALUES ({table_string});'
|
||||||
|
ret_sql_insert.append(gen_statement)
|
||||||
|
|
||||||
|
# generate c++ bind statement
|
||||||
|
bind_string: str = '\n'.join(map(conv_cpp, struct_decl.m_StructFields))
|
||||||
|
ret_cpp_bind.append((struct_decl.m_StructName, bind_string))
|
||||||
|
|
||||||
|
print('========== SQL Drop Table ==========')
|
||||||
|
for item in ret_sql_drop_table:
|
||||||
|
print(item)
|
||||||
|
print('========== SQL Create Table ==========')
|
||||||
|
for item in ret_sql_create_table:
|
||||||
|
print(item)
|
||||||
|
print('========== SQL Insert ==========')
|
||||||
|
for item in ret_sql_insert:
|
||||||
|
print(item)
|
||||||
|
print('========== C++ Bind ==========')
|
||||||
|
for name, item in ret_cpp_bind:
|
||||||
|
print(f'===== {name} =====')
|
||||||
|
print(item)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
input_str: str = accept_input()
|
||||||
|
decls: tuple[StructDecl, ...] = analyse_input(input_str)
|
||||||
|
output_result(decls)
|
||||||
@@ -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()
|
|
||||||
@@ -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')
|
|
||||||
@@ -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')
|
|
||||||
|
|
||||||