Workflow established for texturing and modeling.
This commit is contained in:
parent
fcd515095e
commit
5b116f357a
9 changed files with 199 additions and 34 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1,6 +1,9 @@
|
|||
*.zip
|
||||
*.pyc
|
||||
*.log
|
||||
/plugin/Data/Scripts/
|
||||
/plugin/Data/Meshes/
|
||||
/plugin/Data/Textures/
|
||||
/build/
|
||||
node_modules/
|
||||
*.blend[0-9]*
|
15
.vscode/tasks.json
vendored
15
.vscode/tasks.json
vendored
|
@ -11,7 +11,20 @@
|
|||
"kind": "build"
|
||||
},
|
||||
"command": "${workspaceFolder}/build.ps1",
|
||||
"args": ["-Reload"],
|
||||
"args": ["-KickVortex"],
|
||||
"problemMatcher": [
|
||||
"$PapyrusCompiler"
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "Build and Reload",
|
||||
"type": "shell",
|
||||
"group": {
|
||||
"isDefault": true,
|
||||
"kind": "build"
|
||||
},
|
||||
"command": "${workspaceFolder}/build.ps1",
|
||||
"args": ["-KickVortex", "-Reload"],
|
||||
"problemMatcher": [
|
||||
"$PapyrusCompiler"
|
||||
]
|
||||
|
|
14
README.md
14
README.md
|
@ -1,3 +1,17 @@
|
|||
# skyrim-item-roulette
|
||||
|
||||
Roulettes items
|
||||
|
||||
## Notes
|
||||
|
||||
* NIF export from Blender is perfectly fine if you're working from scratch.
|
||||
Skyrim doesn't seem to care that the models are an old format.
|
||||
* It should go without saying that if you change a model texture or any
|
||||
resource other than the main plugin file, make sure you redeploy from Vortex
|
||||
or you won't see the changes.
|
||||
* Likewise, if you change the texture in GIMP, you must rebuild the textures
|
||||
or you won't see them anywhere.
|
||||
* If you include a texture it must be connected to the Color node of the Material
|
||||
in the Shader node view, and the **node name** must be `Base`. The image path must
|
||||
be the DDS in the /plugin folder. The NIF plugin is intelligent enough to relativize
|
||||
the path when exporting.
|
Binary file not shown.
BIN
Source/Textures/_EQ_ItemRoulette/roulette_container.xcf
Normal file
BIN
Source/Textures/_EQ_ItemRoulette/roulette_container.xcf
Normal file
Binary file not shown.
116
build.ps1
116
build.ps1
|
@ -2,18 +2,57 @@
|
|||
.SYNOPSIS
|
||||
Builds the plugin and optionally reloads it in Vortex.
|
||||
|
||||
.PARAMETER Scripts
|
||||
Build Papyrus scripts
|
||||
|
||||
.PARAMETER Models
|
||||
Build Blender models
|
||||
|
||||
.PARAMETER Textures
|
||||
Build GIMP textures
|
||||
|
||||
.PARAMETER Zip
|
||||
Build the ZIP AND NOTHING ELSE. You probably don't want this option
|
||||
|
||||
.PARAMETER KickVortex
|
||||
Syncs the plugin with Vortex. If there are file conflicts, take changes
|
||||
from the game directory! This will have changes from the ESP that were
|
||||
made in Creation Kit! You need to symlink the /plugin directory into
|
||||
the staging area, preferably using setup-dev.ps1 script.
|
||||
|
||||
.PARAMETER Reload
|
||||
Reloads Skyrim after building. Reloading assumes you have symlinked the mod
|
||||
into Vortex's staging area using the method in setup-dev.ps1. It completely
|
||||
kills and restarts the game as I had trouble getting hlp and reloadscript
|
||||
commands to work.
|
||||
Reloads Skyrim after building. It completely kills and restarts the game
|
||||
as I had trouble getting hlp and reloadscript commands to work.
|
||||
#>
|
||||
param (
|
||||
[Parameter(Mandatory = $False)]
|
||||
[Switch]
|
||||
$Scripts,
|
||||
[Parameter(Mandatory = $False)]
|
||||
[Switch]
|
||||
$Models,
|
||||
[Parameter(Mandatory = $False)]
|
||||
[Switch]
|
||||
$Textures,
|
||||
[Parameter(Mandatory = $False)]
|
||||
[Switch]
|
||||
$Zip,
|
||||
|
||||
[Parameter(Mandatory = $False)]
|
||||
[Switch]
|
||||
$KickVortex,
|
||||
[Parameter(Mandatory = $False)]
|
||||
[Switch]
|
||||
$Reload
|
||||
)
|
||||
|
||||
if(-not $Scripts -and -not $Models -and -not $Textures -and -not $Zip) {
|
||||
$Scripts = $true
|
||||
$Textures = $true
|
||||
$Models = $true
|
||||
$Zip = $true
|
||||
}
|
||||
|
||||
New-Item -ItemType Directory "$PSScriptRoot/build" -ErrorAction SilentlyContinue
|
||||
|
||||
Add-Type -Path "$PSScriptRoot/Gameloop.Vdf.dll" -ErrorAction SilentlyContinue
|
||||
|
@ -71,36 +110,49 @@ if(-not $SkyrimBase) {
|
|||
)).FullName
|
||||
}
|
||||
|
||||
# Compile the scripts
|
||||
& "$SkyrimBase/Papyrus Compiler/PapyrusCompiler.exe" `
|
||||
"$PsScriptRoot/Source/Scripts" `
|
||||
"-f=$SkyrimBase/Data/Source/Scripts/TESV_Papyrus_Flags.flg" `
|
||||
"-i=$SkyrimBase/Data/Source/Scripts;$PsScriptRoot/Source/Scripts" `
|
||||
"-o=$PsScriptRoot/plugin/Data/Scripts" `
|
||||
"-all"
|
||||
if($Scripts) {
|
||||
# Compile the scripts
|
||||
& "$SkyrimBase/Papyrus Compiler/PapyrusCompiler.exe" `
|
||||
"$PsScriptRoot/Source/Scripts" `
|
||||
"-f=$SkyrimBase/Data/Source/Scripts/TESV_Papyrus_Flags.flg" `
|
||||
"-i=$SkyrimBase/Data/Source/Scripts;$PsScriptRoot/Source/Scripts" `
|
||||
"-o=$PsScriptRoot/plugin/Data/Scripts" `
|
||||
"-all"
|
||||
|
||||
if($LastExitCode -ne 0) {
|
||||
return $LastExitCode
|
||||
if($LastExitCode -ne 0) {
|
||||
return $LastExitCode
|
||||
}
|
||||
}
|
||||
|
||||
# Build the models
|
||||
blender.exe --background --python "$PSScriptRoot/export-blender-models.py"
|
||||
if($Textures) {
|
||||
Push-Location "$PSScriptRoot"
|
||||
|
||||
if($LastExitCode -ne 0) {
|
||||
return $LastExitCode
|
||||
}
|
||||
gimp-console -n -i --batch-interpreter python-fu-eval -b "import export_gimp_textures"
|
||||
|
||||
# ZIP up the deployment package
|
||||
$ZipPath = "$PSScriptRoot/build/Item Roulette for VRIK.zip"
|
||||
|
||||
Remove-Item $ZipPath -ErrorAction SilentlyContinue
|
||||
Compress-Archive -Path $PSScriptRoot/plugin/* -DestinationPath $ZipPath
|
||||
|
||||
if($Reload) {
|
||||
if($Proc) {
|
||||
Stop-Process $Proc
|
||||
if($LastExitCode -ne 0) {
|
||||
return $LastExitCode
|
||||
}
|
||||
|
||||
Pop-Location
|
||||
}
|
||||
|
||||
if($Models) {
|
||||
blender --background --python "$PSScriptRoot/export_blender_models.py"
|
||||
|
||||
if($LastExitCode -ne 0) {
|
||||
return $LastExitCode
|
||||
}
|
||||
}
|
||||
|
||||
if($Zip) {
|
||||
# ZIP up the deployment package
|
||||
$ZipPath = "$PSScriptRoot/build/Item Roulette for VRIK.zip"
|
||||
|
||||
Remove-Item $ZipPath -ErrorAction SilentlyContinue
|
||||
Compress-Archive -Path $PSScriptRoot/plugin/* -DestinationPath $ZipPath
|
||||
}
|
||||
|
||||
if($KickVortex) {
|
||||
# Restart Vortex and kick off deploy-mods event via Chrome Debug Protocol.
|
||||
Stop-Process -Name Vortex
|
||||
$env:KICK_PORT=6969
|
||||
|
@ -110,8 +162,14 @@ if($Reload) {
|
|||
|
||||
pnpm install -C "$PSScriptRoot"
|
||||
|
||||
node.exe "$PSScriptRoot/kick-vortex.js"
|
||||
node "$PSScriptRoot/kick-vortex.js"
|
||||
Stop-Process -Name Vortex -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
if($Reload) {
|
||||
if($Proc) {
|
||||
Stop-Process $Proc
|
||||
}
|
||||
|
||||
# Prefer SKSE loader if we have it installed
|
||||
$SkyrimExe = Get-Item -Path @(
|
||||
|
@ -135,3 +193,5 @@ if($Reload) {
|
|||
"@
|
||||
} while ($wrFail)
|
||||
}
|
||||
|
||||
return 0
|
|
@ -1,7 +1,7 @@
|
|||
import bpy
|
||||
import os
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
curdir = Path(__file__).parent
|
||||
print("Current directory: " + str(curdir))
|
||||
plugin_data_dir = curdir.joinpath("plugin/Data")
|
||||
|
@ -16,9 +16,9 @@ for blend_path in blend_paths:
|
|||
nif_parent = dest_blend_path.parent
|
||||
nif_path = nif_parent.joinpath(dest_blend_path.stem + '.nif')
|
||||
print(str(blend_path) + " -> " + str(nif_path))
|
||||
bpy.ops.wm.open_mainfile(filepath=str(blend_path))
|
||||
try:
|
||||
nif_parent.mkdir(parents=True)
|
||||
except FileExistsError:
|
||||
pass
|
||||
bpy.ops.wm.open_mainfile(filepath=str(blend_path))
|
||||
bpy.ops.export_scene.nif(filepath=str(nif_path))
|
75
export_gimp_textures.py
Normal file
75
export_gimp_textures.py
Normal file
|
@ -0,0 +1,75 @@
|
|||
from gimpfu import pdb
|
||||
import platform
|
||||
import sys
|
||||
|
||||
pdb.gimp_message("Started exporting textures.")
|
||||
pdb.gimp_message(platform.python_version())
|
||||
|
||||
try:
|
||||
import glob
|
||||
import os
|
||||
import pydoc
|
||||
|
||||
curdir = os.path.dirname(os.path.abspath(__file__))
|
||||
pdb.gimp_message("Current directory: " + curdir)
|
||||
plugin_data_dir = os.path.join(curdir, "plugin/Data")
|
||||
pdb.gimp_message("Plugin directory: " + plugin_data_dir)
|
||||
texture_src_dir = os.path.join(curdir, "Source/Textures/_EQ_ItemRoulette")
|
||||
pdb.gimp_message("Texture Source directory: " + texture_src_dir)
|
||||
texture_dest_dir = os.path.join(plugin_data_dir, "Textures/_EQ_ItemRoulette")
|
||||
pdb.gimp_message("Texture Dest directory: " + texture_dest_dir)
|
||||
|
||||
# FIXME This won't recurse
|
||||
xcf_paths = glob.glob(texture_src_dir + "/*.xcf")
|
||||
for xcf_path in xcf_paths:
|
||||
dest_xcf_path = os.path.join(texture_dest_dir, os.path.relpath(path=xcf_path, start=texture_src_dir))
|
||||
dds_parent = os.path.dirname(dest_xcf_path)
|
||||
dds_path = os.path.join(os.path.splitext(dest_xcf_path)[0] + '.dds')
|
||||
pdb.gimp_message(xcf_path + " -> " + dds_path)
|
||||
try:
|
||||
os.makedirs(dds_parent)
|
||||
except:
|
||||
pass
|
||||
image = pdb.gimp_xcf_load(1, xcf_path, xcf_path)
|
||||
#pdb.gimp_message(str(pdb.file_dds_save.params))
|
||||
pdb.file_dds_save(
|
||||
image,
|
||||
# (13, 'image', 'Input image'),
|
||||
image.flatten(),
|
||||
# (16, 'drawable', 'Drawable to save'),
|
||||
dds_path,
|
||||
# (4, 'filename', 'The name of the file to save the image as'),
|
||||
dds_path,
|
||||
# (4, 'raw-filename', 'The name entered'),
|
||||
0,
|
||||
# (0, 'compression-format', 'Compression format # (0 = None, 1 = BC1/DXT1, 2 = BC2/DXT3, 3 = BC3/DXT5, 4 = BC3n/DXT5nm, 5 = BC4/ATI1N, 6 = BC5/ATI2N, 7 = RXGB # (DXT5), 8 = Alpha Exponent # (DXT5), 9 = YCoCg # (DXT5), 10 = YCoCg scaled # (DXT5))'),
|
||||
1,
|
||||
# (0, 'mipmaps', 'How to handle mipmaps # (0 = No mipmaps, 1 = Generate mipmaps, 2 = Use existing mipmaps # (layers)'),
|
||||
0,
|
||||
# (0, 'savetype', 'How to save the image # (0 = selected layer, 1 = cube map, 2 = volume map, 3 = texture array'),
|
||||
0,
|
||||
# (0, 'format', 'Custom pixel format # (0 = default, 1 = R5G6B5, 2 = RGBA4, 3 = RGB5A1, 4 = RGB10A2)'),
|
||||
-1,
|
||||
# (0, 'transparent-index', 'Index of transparent color or -1 to disable # (for indexed images only).'),
|
||||
0,
|
||||
# (0, 'mipmap-filter', 'Filtering to use when generating mipmaps # (0 = default, 1 = nearest, 2 = box, 3 = triangle, 4 = quadratic, 5 = bspline, 6 = mitchell, 7 = lanczos, 8 = kaiser)'),
|
||||
0,
|
||||
# (0, 'mipmap-wrap', 'Wrap mode to use when generating mipmaps # (0 = default, 1 = mirror, 2 = repeat, 3 = clamp)'),
|
||||
0,
|
||||
# (0, 'gamma-correct', 'Use gamma correct mipmap filtering'),
|
||||
0,
|
||||
# (0, 'srgb', 'Use sRGB colorspace for gamma correction'),
|
||||
0,
|
||||
# (3, 'gamma', 'Gamma value to use for gamma correction # (i.e. 2.2)'),
|
||||
2.2,
|
||||
# (0, 'perceptual-metric', 'Use a perceptual error metric during compression'),
|
||||
0,
|
||||
# (0, 'preserve-alpha-coverage', 'Preserve alpha test converage for alpha channel maps'),
|
||||
0
|
||||
# (3, 'alpha-test-threshold', 'Alpha test threshold value for which alpha test converage should be preserved')
|
||||
)
|
||||
pdb.gimp_image_delete(image)
|
||||
except:
|
||||
pdb.gimp_message("An unhandled error occurred: " + str(sys.exc_info()[0]) + ": " + str(sys.exc_info()[1]))
|
||||
|
||||
pdb.gimp_quit(0)
|
Binary file not shown.
Loading…
Add table
Reference in a new issue