-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 916545f
Showing
10 changed files
with
372 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
.pyenv | ||
build/ | ||
__pycache__/ | ||
*.pyc | ||
*.pyo |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
################################################## | ||
# List of files ignored when packaging the plugin | ||
################################################## | ||
|
||
# Ignore the packaging script. | ||
makepackage.py | ||
|
||
# Ignore the build directory. | ||
build/ | ||
|
||
# Ignore compiled python modules. | ||
*.pyc | ||
__pycache__ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# VTF Exporter for Substance 3D Designer | ||
|
||
Todo | ||
|
||
# Installing | ||
|
||
Todo |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
########################################################################## | ||
# ADOBE CONFIDENTIAL | ||
# ___________________ | ||
# Copyright 2010-2024 Adobe | ||
# All Rights Reserved. | ||
# * NOTICE: Adobe permits you to use, modify, and distribute this file in | ||
# accordance with the terms of the Adobe license agreement accompanying it. | ||
# If you have received this file from a source other than Adobe, | ||
# then your use, modification, or distribution of it requires the prior | ||
# written permission of Adobe. | ||
########################################################################## | ||
|
||
import os | ||
import sys | ||
import fnmatch | ||
import json | ||
from zipfile import ZipFile | ||
|
||
|
||
class IgnoreFileFilter(object): | ||
def __init__(self, filename): | ||
self.__globs = [] | ||
self.__dirs_to_ignore = [] | ||
|
||
if os.path.exists(filename): | ||
with open(filename, 'rt') as f: | ||
lines = f.readlines() | ||
|
||
for line in lines: | ||
line = line.strip() | ||
|
||
if line == '' or line.startswith('#'): | ||
continue | ||
|
||
if line.endswith('/'): | ||
self.__dirs_to_ignore.append(line[:-1]) | ||
else: | ||
self.__globs.append(line) | ||
|
||
def filter(self, filepath): | ||
# Ignore filter config files. | ||
if filepath.endswith('.sdpackageignore'): | ||
return False | ||
|
||
# Check that the file is not included in any glob. | ||
if self.__globs: | ||
filename = os.path.basename(filepath) | ||
|
||
for pattern in self.__globs: | ||
if fnmatch.fnmatch(filename, pattern): | ||
return False | ||
|
||
# Check that the file is not inside any ignored directory. | ||
if self.__dirs_to_ignore: | ||
dirname = os.path.normpath(os.path.dirname(filepath)) | ||
dirs = dirname.split(os.sep) | ||
|
||
for pattern in self.__dirs_to_ignore: | ||
for d in dirs: | ||
if pattern == d: | ||
return False | ||
|
||
return True | ||
|
||
|
||
def read_metadata(): | ||
if not os.path.exists('pluginInfo.json'): | ||
print("Missing metadata file") | ||
return None | ||
|
||
try: | ||
f = open('pluginInfo.json', 'rt') | ||
return json.load(f) | ||
except Exception as e: | ||
print('Error while checking metadata: %s' % e) | ||
f.close() | ||
return None | ||
|
||
def check_metadata(metadata): | ||
if not 'name' in metadata: | ||
print('"name" metadata entry is missing') | ||
return False | ||
|
||
return True | ||
|
||
def walk(directory): | ||
for dirpath, dirnames, filenames in os.walk(directory, topdown=True): | ||
for filename in filenames: | ||
yield os.path.join(dirpath, filename) | ||
|
||
def add_file_to_package(zfile, plugin_name, filepath): | ||
print("Adding file %s to package" % filepath) | ||
archive_filepath = os.path.join(plugin_name, filepath) | ||
zfile.write(filepath, arcname=archive_filepath) | ||
|
||
def main(): | ||
this_dir = os.path.abspath(os.path.dirname(__file__)) | ||
|
||
build_dir = os.path.join(this_dir, "build") | ||
|
||
if not os.path.exists(build_dir): | ||
try: | ||
os.makedirs(build_dir) | ||
except Exception as e: | ||
print('Could not create build directory') | ||
sys.exit(1) | ||
|
||
package_parent_dir = os.path.abspath(os.path.join(this_dir, '..')) | ||
package_dir_name = os.path.basename(this_dir) | ||
|
||
# Save the current dir and switch to the package dir. | ||
saved_dir = os.getcwd() | ||
os.chdir(this_dir) | ||
|
||
metadata = read_metadata() | ||
if not metadata: | ||
sys.exit(1) | ||
|
||
if not check_metadata(metadata): | ||
sys.exit(1) | ||
|
||
plugin_name = metadata['name'] | ||
package_filepath = os.path.join(build_dir, plugin_name) + '.sdplugin' | ||
|
||
try: | ||
file_filter = IgnoreFileFilter('.sdpackageignore') | ||
|
||
with ZipFile(package_filepath, 'w') as zfile: | ||
for filepath in walk('.'): | ||
if os.path.abspath(filepath) == os.path.join(this_dir, 'pluginInfo.json'): | ||
add_file_to_package(zfile, plugin_name, filepath) | ||
elif file_filter.filter(filepath): | ||
add_file_to_package(zfile, plugin_name, filepath) | ||
|
||
except Exception as e: | ||
print("Error while packaging plugin: %s" % e) | ||
sys.exit(1) | ||
finally: | ||
# Restore the saved directory. | ||
os.chdir(saved_dir) | ||
|
||
if __name__ == '__main__': | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"metadata_format_version": "1", | ||
"name": "vtf_exporter", | ||
"version": "0.1.1", | ||
"author": "Zeus", | ||
"email": "https://tf2maps.net/members/zeus.28272/", | ||
"min_designer_version": "2019.2", | ||
"platform": "any" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
########################################################################## | ||
# ADOBE CONFIDENTIAL | ||
# ___________________ | ||
# Copyright 2010-2024 Adobe | ||
# All Rights Reserved. | ||
# * NOTICE: Adobe permits you to use, modify, and distribute this file in | ||
# accordance with the terms of the Adobe license agreement accompanying it. | ||
# If you have received this file from a source other than Adobe, | ||
# then your use, modification, or distribution of it requires the prior | ||
# written permission of Adobe. | ||
########################################################################## | ||
|
||
import sd | ||
|
||
from vtf_exporter import menu | ||
|
||
|
||
def initializeSDPlugin(): | ||
menu.create_menu() | ||
|
||
|
||
def uninitializeSDPlugin(): | ||
menu.destroy_menu() | ||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import sd | ||
from sd.api.sdproperty import * | ||
from sd.api.sdvaluetexture import SDValueTexture | ||
|
||
from pathlib import Path | ||
import subprocess | ||
import os | ||
import tempfile | ||
|
||
from vtf_exporter import config | ||
|
||
|
||
def bulk_export(): | ||
ctx = sd.getContext() | ||
app = ctx.getSDApplication() | ||
uiMgr = app.getQtForPythonUIMgr() | ||
|
||
graph = uiMgr.getCurrentGraph() | ||
|
||
# Get current graph inputs | ||
|
||
for preset in graph.getPresets(): | ||
set_preset(graph, preset) | ||
save_outputs_as_vtf(graph, preset.getLabel()) | ||
|
||
# Reset graph inputs | ||
|
||
|
||
def set_preset(graph, preset): | ||
for preset_input in preset.getInputs(): | ||
value = preset_input.getValue() | ||
id = preset_input.getIdentifier() | ||
graph.setInputPropertyValueFromId(id, value) | ||
|
||
graph.compute() | ||
|
||
|
||
def save_outputs_as_vtf(graph, preset_name): | ||
plugin_config = config.get_vtex_config_file() | ||
vtex_exe = plugin_config.get("vtex_path") | ||
# TODO Error handling if vtex path is not configured | ||
|
||
for node in graph.getOutputNodes(): | ||
props = node.getProperties(SDPropertyCategory.Output) | ||
value = node.getPropertyValue(props[0]) | ||
texture = SDValueTexture.get(value) | ||
|
||
output_name = props[0].getId() | ||
|
||
file_name = f"{graph.getIdentifier()}_{preset_name}_{output_name}" | ||
|
||
save_temp_dir = tempfile.mkdtemp() | ||
save_temp_file = os.path.join(str(save_temp_dir), f"{file_name}.tga") | ||
save_vtex_config_file = os.path.join(str(save_temp_dir), f"{file_name}.txt") | ||
|
||
# TODO Take a filepath in config? | ||
save_dir = Path(f'C:/Users/phenn/Desktop') | ||
|
||
# TODO Take additional args based on alpha channel | ||
with open(save_vtex_config_file, "w") as file: | ||
file.write("stripalphachannel 1\n") | ||
|
||
texture.save(save_temp_file) | ||
|
||
command = [str(vtex_exe), "-nopause", "-outdir", str(save_dir), save_vtex_config_file] | ||
output = subprocess.run(command, shell=True, capture_output=True) | ||
|
||
os.remove(save_temp_file) | ||
os.remove(save_vtex_config_file) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import os | ||
import json | ||
from vtf_exporter.constants import * | ||
|
||
|
||
def get_vtex_config_file(): | ||
if os.path.exists(CONFIG_DIR): | ||
if os.path.exists(CONFIG_FILE): | ||
with open(CONFIG_FILE) as file: | ||
return json.load(file) | ||
|
||
return {} | ||
|
||
|
||
def save_vtex_config_file(config_data): | ||
if not os.path.exists(CONFIG_DIR): | ||
os.mkdir(CONFIG_DIR) | ||
|
||
with open(CONFIG_FILE, "w") as file: | ||
file.write(json.dumps(config_data, indent=4)) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import os | ||
|
||
SUBSTANCE_DIR = os.path.join(os.getenv('APPDATA') , "Allegorithmic", "Substance Designer") | ||
CONFIG_DIR = os.path.join(SUBSTANCE_DIR, "vtf_exporter") | ||
CONFIG_FILE = os.path.join(CONFIG_DIR, "config.json") | ||
|
||
PLUGIN_VERSION = "0.1.0" | ||
MAIN_MENU_NAME = "vtf_exporter_main" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import sd | ||
from PySide2 import QtWidgets | ||
|
||
from vtf_exporter import config | ||
from vtf_exporter.bulk_export import bulk_export | ||
|
||
|
||
def create_menu(): | ||
app = sd.getContext().getSDApplication() | ||
uiMgr = app.getQtForPythonUIMgr() | ||
|
||
menu = uiMgr.newMenu( | ||
menuTitle="VTF Exporter", | ||
objectName="vtf_exporter_main" | ||
) | ||
|
||
act_bulk_export = QtWidgets.QAction("Bulk Export Graph Presets", menu) | ||
act_bulk_export.triggered.connect(bulk_export) | ||
menu.addAction(act_bulk_export) | ||
|
||
menu.addSeparator() | ||
|
||
configure = QtWidgets.QAction("Configure", menu) | ||
configure.triggered.connect(create_config_dialog) | ||
menu.addAction(configure) | ||
|
||
|
||
|
||
def destroy_menu(): | ||
app = sd.getContext().getSDApplication() | ||
uiMgr = app.getQtForPythonUIMgr() | ||
uiMgr.deleteMenu("vtf_exporter_main") | ||
|
||
|
||
def create_config_dialog(): | ||
app = sd.getContext().getSDApplication() | ||
uiMgr = app.getQtForPythonUIMgr() | ||
|
||
mainWindow = uiMgr.getMainWindow() | ||
dialog = QtWidgets.QDialog(parent=mainWindow) | ||
|
||
layout = QtWidgets.QVBoxLayout() | ||
layout2 = QtWidgets.QHBoxLayout() | ||
|
||
label_vtex_location = QtWidgets.QLabel("vtex.exe") | ||
|
||
vtex_path = config.get_vtex_config_file().get("vtex_path") | ||
if vtex_path: | ||
txt_vtex_location = QtWidgets.QLineEdit(vtex_path) | ||
else: | ||
txt_vtex_location = QtWidgets.QLineEdit() | ||
|
||
layout2.addWidget(label_vtex_location) | ||
layout2.addWidget(txt_vtex_location) | ||
|
||
layout.addLayout(layout2) | ||
|
||
btn_save = QtWidgets.QPushButton("Save") | ||
def save_config(): | ||
config_data = {"vtex_path": txt_vtex_location.text()} | ||
save_vtex_config_file(config_data) | ||
dialog.accept() | ||
|
||
btn_save.clicked.connect(save_config) | ||
|
||
layout.addWidget(btn_save) | ||
|
||
dialog.setLayout(layout) | ||
|
||
dialog.show() |