diff --git a/ChunkMerge.ahk b/ChunkMerge.ahk index 2a2494e..685a224 100644 --- a/ChunkMerge.ahk +++ b/ChunkMerge.ahk @@ -1,38 +1,28 @@ SetTitleMatchMode, RegEx WinWait, ahk_exe i)ChunkMerge.exe -WinActivate, ahk_exe i)ChunkMerge.exe - -ControlFocus Button1, A -Send {Space} - -WinWaitNotActive, i)ChunkMerge +WinGet, ChunkMain, ID, ahk_exe i)ChunkMerge.exe +WinActivate, ahk_id %ChunkMain% Clipboard := ChunkMerge_NifFile +ControlFocus Edit1, ahk_id %ChunkMain% Send +{Insert} -Send {Enter} - -WinWaitActive, i)ChunkMerge - -ControlFocus Button2, A -Send {Space} - -WinWaitNotActive, i)ChunkMerge Clipboard := ChunkMerge_CollisionFile +ControlFocus Edit2, ahk_id %ChunkMain% Send +{Insert} -Send {Enter} -WinWaitActive, i)ChunkMerge - -ControlFocus, ComboBox1, A +ControlFocus, ComboBox1, ahk_id %ChunkMain% Send, %ChunkMerge_TemplateFile% -ControlFocus, Mesh Data, A -Send {Space} -ControlFocus, Name of NiTriShape, A -Send {Space} +ControlClick, Mesh Data, ahk_id %ChunkMain% +ControlClick, Name of NiTriShape, ahk_id %ChunkMain% -Send {Enter} +ControlSend Convert, {Space}, ahk_id %ChunkMain% -Sleep 3000 - -WinClose, ahk_exe i)ChunkMerge.exe \ No newline at end of file +Loop { + Sleep 100 + ControlGetText, FinishedText, RichEdit20W1, ahk_id %ChunkMain% + IfInString, FinishedText, Nif converted successfully + { + Break + } +} \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..76250d0 --- /dev/null +++ b/Makefile @@ -0,0 +1,107 @@ +PATH=/sbin:/bin:/usr/sbin:/usr/bin:/c/ProgramData/chocolatey/bin:$(SystemRoot)/System32/WindowsPowerShell/v1.0 + +mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST))) +current_dir := $(patsubst %/,%,$(dir $(mkfile_path))) + +scriptFiles := $(patsubst Source/Scripts/%.psc,plugin/Data/Scripts/%.pex,$(wildcard Source/Scripts/*.psc)) +textureFiles := $(patsubst Source/Textures/%.xcf,plugin/Data/Textures/%.dds,$(wildcard Source/Textures/_EQ_ItemRoulette/*.xcf)) +modelFiles := $(patsubst Source/Meshes/%_mesh.blend,plugin/Data/Meshes/%_final.nif,$(wildcard Source/Meshes/_EQ_ItemRoulette/*_mesh.blend)) + +.ONESHELL: + +all: zip + +clean: + rm -rf \ + plugin/Data/Meshes \ + plugin/Data/Scripts \ + plugin/Data/Textures && true + +distclean: clean + rm -rf build && true + mkdir build + +zip: build/Item_Roulette_for_VRIK.zip + +build/Item_Roulette_for_VRIK.zip: plugin + rm -rf "$@" + powershell -Command 'Compress-Archive -Path "plugin/*" -DestinationPath "$@"' + +plugin: scripts models + +scripts: $(scriptFiles) + +plugin/Data/Scripts/%.pex: Source/Scripts/%.psc + "$(SKYRIM_BASE)/Papyrus Compiler/PapyrusCompiler.exe" \ + "$^" \ + "-f=$(SKYRIM_BASE)/Data/Source/Scripts/TESV_Papyrus_Flags.flg" \ + "-i=$(SKYRIM_BASE)/Data/Source/Scripts;Source/Scripts" \ + "-o=$@" \ + +textures: $(textureFiles) + GIMP=$$(powershell -Command '(Get-Item "$(ProgramW6432)/GIMP*/bin/gimp-console*.exe").FullName') + "$$GIMP" -n -i --batch-interpreter python-fu-eval -b "import export_gimp_textures" + +models: $(modelFiles) + +build/ChunkMerge/ChunkMerge.exe: build/chunkmerge.7z + 7z x -y "-obuild" "$<" + +build/chunkmerge.7z: + powershell -Command 'Invoke-WebRequest -Uri "https://github.com/downloads/skyfox69/NifUtils/ChunkMerge0155.7z" -OutFile build/chunkmerge.7z' + +build/ChunkMerge/ChunkMerge.xml: build/ChunkMerge/ChunkMerge.exe + cat > "$@" <<'HERE' + + $(SKYRIM_BASE) + $(current_dir)/nif.xml + $(current_dir)\\Source\\Meshes\\_EQ_ItemRoulette + + + + + + 0 + 0 + 1 + 1 + 1 + -553455049 + + SkyrimHavokMaterial + SKY_HAV_ + + Material + + + Unknown + + + + 1 + 0 + 0 + 0 + ffffffff + ffffff00 + ff200020 + ffff00ff + + + + + HERE + + +plugin/Data/Meshes/_EQ_ItemRoulette/%_final.nif: Source/Meshes/_EQ_ItemRoulette/%_template.nif plugin/Data/Meshes/_EQ_ItemRoulette/%_collision.nif plugin/Data/Meshes/_EQ_ItemRoulette/%_mesh.nif build/ChunkMerge/ChunkMerge.xml + cp "$(filter %_mesh.nif,$^)" "$@" + build/ChunkMerge/ChunkMerge.exe & + powershell -Command '$$env:ChunkMerge_NifFile=Split-Path (Join-Path "$@" "."); $$env:ChunkMerge_CollisionFile=Split-Path (Join-Path "$(filter %_collision.nif,$^)" ".") ; $$env:ChunkMerge_TemplateFile="$(notdir $(filter %_template.nif,$^))" ; Start-Process -Wait -FilePath AutoHotKey -ArgumentList @("ChunkMerge.ahk") ; Stop-Process -Name ChunkMerge' + +plugin/Data/Meshes/_EQ_ItemRoulette/%_mesh.nif: Source/Meshes/_EQ_ItemRoulette/%_mesh.blend + BLENDER=$$(powershell -Command '(Get-Item "$(ProgramW6432)/Blender*/Blender*/blender.exe").FullName') + "$$BLENDER" --background --python "./export_blender_models.py" -- "$^" "$@" + +plugin/Data/Meshes/_EQ_ItemRoulette/%_collision.nif: Source/Meshes/_EQ_ItemRoulette/%_collision.blend + BLENDER=$$(powershell -Command '(Get-Item "$(ProgramW6432)/Blender*/Blender*/blender.exe").FullName') + "$$BLENDER" --background --python "./export_blender_models.py" -- "$^" "$@" \ No newline at end of file diff --git a/Source/Meshes/_EQ_ItemRoulette/roulette_container.blend b/Source/Meshes/_EQ_ItemRoulette/roulette_container.blend index 0eff22b..11ba423 100644 Binary files a/Source/Meshes/_EQ_ItemRoulette/roulette_container.blend and b/Source/Meshes/_EQ_ItemRoulette/roulette_container.blend differ diff --git a/Source/Meshes/_EQ_ItemRoulette/roulette_container_collision.blend b/Source/Meshes/_EQ_ItemRoulette/roulette_container_collision.blend index 34d6b98..84c4fb5 100644 Binary files a/Source/Meshes/_EQ_ItemRoulette/roulette_container_collision.blend and b/Source/Meshes/_EQ_ItemRoulette/roulette_container_collision.blend differ diff --git a/Source/Meshes/_EQ_ItemRoulette/roulette_container_mesh.blend b/Source/Meshes/_EQ_ItemRoulette/roulette_container_mesh.blend index 924b3e7..2da1e05 100644 Binary files a/Source/Meshes/_EQ_ItemRoulette/roulette_container_mesh.blend and b/Source/Meshes/_EQ_ItemRoulette/roulette_container_mesh.blend differ diff --git a/Source/Scripts/_EQ_ItemRoulette_Quest.psc b/Source/Scripts/_EQ_ItemRoulette_Quest.psc index 5f443b2..d93359a 100644 --- a/Source/Scripts/_EQ_ItemRoulette_Quest.psc +++ b/Source/Scripts/_EQ_ItemRoulette_Quest.psc @@ -4,9 +4,12 @@ Actor Property PlayerRef Auto Static Property _EQ_ItemRoulette_Roulette Auto ObjectReference[] DisplayItems +ObjectReference Roulette -Int MAX_ITEMS = 6 -Int CIRCLE_RADIUS = 16 +Int MAX_ITEMS = 5 +Float UI_DISTANCE = 32.0 +Float UI_DEGREES = 7.0 +Float UI_ZEES = 4.0 Event OnInit() DisplayItems = New ObjectReference[127] @@ -21,15 +24,38 @@ EndEvent Function Main() Debug.Trace("Item Roulette loaded") + Roulette = PlayerRef.PlaceAtMe(_EQ_ItemRoulette_Roulette) RegisterForModEvent("_EQ_ItemRoulette_Activate", "OnMyAction") VRIK.VrikAddGestureAction("_EQ_ItemRoulette_Activate", "Activate Item Roulette") RegisterForSingleUpdate(0.01) EndFunction Event OnUpdate() + Float handX = VRIK.VrikGetHandX(true) + Float handY = VRIK.VrikGetHandY(true) + Float handZ = VRIK.VrikGetHandZ(true) + Float playerAngle = PlayerRef.GetAngleZ() + + Roulette.MoveTo(PlayerRef, UI_DISTANCE * Math.sin(playerAngle), UI_DISTANCE * Math.cos(playerAngle), VRIK.VrikGetHmdZ(), true) + Int index = 0 While index < MAX_ITEMS && DisplayItems[index] != None - DisplayItems[index].SetPosition(VRIK.VrikGetHandX(true) + CIRCLE_RADIUS * Math.sin(60 * index), VRIK.VrikGetHandY(true), VRIK.VrikGetHandZ(true) + CIRCLE_RADIUS * Math.cos(60 * index)) + ; TLRB + Float top = 0 + Float left = 0 + If index == 0 + top = -UI_ZEES + ElseIf index == 1 + left = -UI_DEGREES + ElseIf index == 2 + top = 0 + left = 0 + ElseIf index == 3 + left = UI_DEGREES + Else + top = UI_ZEES + EndIf + DisplayItems[index].MoveTo(PlayerRef, UI_DISTANCE * Math.sin(playerAngle - left), UI_DISTANCE * Math.cos(playerAngle - left), (VRIK.VrikGetHmdZ() - PlayerRef.Z) + top) index += 1 EndWhile @@ -38,8 +64,6 @@ EndEvent Event OnMyAction(string eventName, string strArg, float numArg, Form sender) Debug.Trace("VRIK activated me!") - PlayerRef.PlaceAtMe(_EQ_ItemRoulette_Roulette) - ;/ Int numItems = PlayerRef.getNumItems() Int formIndex = numItems Int count = 0 @@ -52,5 +76,4 @@ Event OnMyAction(string eventName, string strArg, float numArg, Form sender) invItemInst.SetMotionType(invItemInst.Motion_Keyframed) DisplayItems[count - 1] = invItemInst EndWhile - /; EndEvent \ No newline at end of file diff --git a/build.ps1 b/build.ps1 index 3138b6b..03b02e3 100644 --- a/build.ps1 +++ b/build.ps1 @@ -5,17 +5,11 @@ .PARAMETER InstallDependencies Installs script dependencies with Chocolatey, except Papyrus, and quit - .PARAMETER Scripts - Build Papyrus scripts + .PARAMETER StartVortex + Start Vortex on the appropriate port and do nothing else. - .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 Target + Build a specific Makefile target .PARAMETER KickVortex Syncs the plugin with Vortex. This option requires Node.js and pnpm to @@ -37,20 +31,13 @@ param ( [Parameter(Mandatory = $False)] [Switch] $InstallDependencies, + [Parameter(Mandatory = $False)] + [Switch] + $StartVortex, [Parameter(Mandatory = $False)] - [Switch] - $Scripts, - [Parameter(Mandatory = $False)] - [Switch] - $Models, - [Parameter(Mandatory = $False)] - [Switch] - $Textures, - - [Parameter(Mandatory = $False)] - [Switch] - $Zip, + [String] + $Target, [Parameter(Mandatory = $False)] [Switch] @@ -70,14 +57,16 @@ if($InstallDependencies) { [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072 Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')) - choco install blender gimp 7zip autohotkey + choco install blender gimp 7zip autohotkey make nodejs + return 0 } -if(-not $Scripts -and -not $Models -and -not $Textures -and -not $Zip) { - $Scripts = $true - $Textures = $true - $Models = $true - $Zip = $true +if($StartVortex) { + Stop-Process -Name Vortex -ErrorAction SilentlyContinue + $VortexPath = (Get-ItemProperty HKLM:\SOFTWARE\57979c68-f490-55b8-8fed-8b017a5af2fe).InstallLocation + $GameId = (Get-Item "$env:APPDATA/Vortex/skyrim*").BaseName + & "$VortexPath/Vortex.exe" --remote-debugging-port=$KickPort --game=$GameId + return 0 } New-Item -ItemType Directory "$PSScriptRoot/build" -ErrorAction SilentlyContinue @@ -143,139 +132,26 @@ if($Reload) { } } -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" +make -C "$PSScriptRoot" SKYRIM_BASE=$SkyrimBase $Target - if($LastExitCode -ne 0) { - return $LastExitCode - } -} - -if($Textures) { - Push-Location "$PSScriptRoot" - - $Gimp = (Get-Item -Path @("$Env:ProgramFiles/GIMP*/bin/gimp-console*.exe", "${env:ProgramFiles(x86)}/GIMP*/bin/gimp-console*.exe")).FullName - & $Gimp -n -i --batch-interpreter python-fu-eval -b "import export_gimp_textures" - - if($LastExitCode -ne 0) { - return $LastExitCode - } - - Pop-Location -} - - -if($Models) { - $Blender = (Get-Item -Path @("${env:ProgramFiles(x86)}/blender*/blender*/blender.exe", "$env:ProgramFiles/blender*/blender*/blender.exe")).FullName - & $Blender --background --python "$PSScriptRoot/export_blender_models.py" - - if($LastExitCode -ne 0) { - return $LastExitCode - } - - $ChunkmergeBase = "$PSScriptRoot/build/ChunkMerge" - $MeshSourceDir = "$PSScriptRoot/Source/Meshes/_EQ_ItemRoulette" - $MeshDestDir = "$PSScriptRoot/plugin/Data/Meshes/_EQ_ItemRoulette" - $ChunkMergeZip = "$PSScriptRoot/build/chunkmerge.7z" - if(-not (Test-Path $ChunkmergeBase)) { - Invoke-WebRequest -Uri "https://github.com/downloads/skyfox69/NifUtils/ChunkMerge0155.7z" -OutFile $ChunkMergeZip - 7z x "-o$PSScriptRoot/build" $ChunkMergeZip - } - - $ChunkMergeConfig = @" - - $SkyrimBase - $PSScriptRoot/nif.xml - $MeshSourceDir - - - - - - 0 - 0 - 1 - 1 - 1 - -553455049 - - SkyrimHavokMaterial - SKY_HAV_ - - Material - - - Unknown - - - - 1 - 0 - 0 - 0 - ffffffff - ffffff00 - ff200020 - ffff00ff - - - - -"@ - - Out-File -Encoding ascii -FilePath "$ChunkmergeBase/ChunkMerge.xml" -InputObject $ChunkMergeConfig - - $ChunkMerge = "$ChunkmergeBase/ChunkMerge.exe" - & $ChunkMerge - - # FIXME This path is not recursive because ChunkMerge can't handle it - foreach($ChunkTemplate in (Get-Item "$MeshSourceDir/*_template.nif")) { - $env:ChunkMerge_NifFile = Join-Path $MeshDestDir ($ChunkTemplate.Name -replace "_template.", ".") - $env:ChunkMerge_CollisionFile = Join-Path $MeshDestDir ($ChunkTemplate.Name -replace "_template.", "_collision.") - $env:ChunkMerge_TemplateFile = $ChunkTemplate.Name - Start-Process -Wait -FilePath AutoHotkey -ArgumentList @("$PSScriptRoot/ChunkMerge.ahk") - - 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(-not $LastExitCode -eq 0) { + return $LastExitCode } if($KickVortex) { - # Restart Vortex and kick off deploy-mods event via Chrome Debug Protocol. - $VortexRunningWithDebuggingPortActive = ` - (Get-NetTCPConnection -State Listen -LocalPort $KickPort -ErrorAction SilentlyContinue) ` - | Where-Object { - $tcpConn = $_ - Get-Process -Name Vortex | Where-Object { $tcpConn.OwningProcess -eq $_.Id } - } - $env:KICK_PORT=$KickPort - if (-not $VortexRunningWithDebuggingPortActive) { - Stop-Process -Name Vortex -ErrorAction SilentlyContinue - $VortexPath = (Get-ItemProperty HKLM:\SOFTWARE\57979c68-f490-55b8-8fed-8b017a5af2fe).InstallLocation - $GameId = (Get-Item "$env:APPDATA/Vortex/skyrim*").BaseName - & "$VortexPath/Vortex.exe" --remote-debugging-port=$KickPort --game=$GameId - } - pnpm install -C "$PSScriptRoot" + if(-not $LastExitCode -eq 0) { + return $LastExitCode + } + node "$PSScriptRoot/kick-vortex.js" + + if(-not $LastExitCode -eq 0) { + return $LastExitCode + } } if($Reload) { diff --git a/export_blender_models.py b/export_blender_models.py index efb3f1b..821dccf 100644 --- a/export_blender_models.py +++ b/export_blender_models.py @@ -2,24 +2,25 @@ import bpy import os import itertools from pathlib import Path +import sys + +argv = sys.argv +try: + index = argv.index("--") + 1 +except ValueError: + index = len(argv) + +argv = argv[index:] curdir = Path(__file__).parent -print("Current directory: " + str(curdir)) -plugin_data_dir = curdir.joinpath("plugin/Data") -print("Plugin directory: " + str(plugin_data_dir)) -mesh_src_dir = curdir.joinpath("Source/Meshes") -print("Mesh Source directory: " + str(mesh_src_dir)) -mesh_dest_dir = plugin_data_dir.joinpath("Meshes") -print("Mesh Dest directory: " + str(mesh_dest_dir)) -blend_paths = itertools.chain(Path(mesh_src_dir).rglob("*_mesh.blend"), Path(mesh_src_dir).rglob("*_collision.blend")) -for blend_path in blend_paths: - dest_blend_path = mesh_dest_dir.joinpath(blend_path.relative_to(mesh_src_dir)) - nif_parent = dest_blend_path.parent - nif_path = nif_parent.joinpath(dest_blend_path.stem.replace('_mesh', '') + '.nif') - print("CONVERTING: " + str(blend_path) + " -> " + str(nif_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)) \ No newline at end of file +blend_path = Path(argv[0]) +nif_path = Path(argv[1]) +nif_parent = nif_path.parent + +print("CONVERTING: " + str(blend_path) + " -> " + str(nif_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)) \ No newline at end of file