Skip to content

Commit

Permalink
Merge pull request #615 from niftools/develop
Browse files Browse the repository at this point in the history
Develop to master
  • Loading branch information
Candoran2 authored Nov 3, 2023
2 parents c649495 + 33cff83 commit 0305c8d
Show file tree
Hide file tree
Showing 67 changed files with 714 additions and 413 deletions.
28 changes: 27 additions & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,4 +1,30 @@
Version v0.1.00
Version v0.1.1
===============

- #591 Expansion of DisplayList processing and small fixes.
- Rigged meshes with DisplayLists will now have functional weights.
- 4-component normals are now handled correctly for DisplayLists.
- Added multiple UV layer support for DisplayLists.
- Rudimentary support for Fallout NV (Fallout New Vegas) by treating it the same as Fallout 3.
- Fixes #582
- Fixes #589
- Fix for animation support for Shin Megami Tensei: Imagine.
- Fixes #584
- Fixes #554 and overhauls/isolates the way the nif geometry data is obtained during export.
- Added option for splitting on tangents (did not happen before). Needs to be disabled for Oblivion head meshes.
- Warn rather than silent fail during egm import.
- Export: Move UV coordinates that are completely in another UV tile to the 0-1 tile.
- Added support for weighted Fallout 4 meshes, fixing #598
- Fixes #599
- Fixes #600
- Add exported tangents to Bully SE.
- Always return copy for get_object_bind to prevent accidental modification.
- Added support for basic (unweighted) Skyrim SE export.
- Change generated module name from generated to nifgen to prevent collision with cobra-tools.
- #592 Update to documentation
- #593 Supported export for Sid Meier's Pirates!.

Version v0.1.0
===============

- #576 Updates to documentation, changelog and makezip.bat (copies over generated folder from cobra-tools).
Expand Down
3 changes: 2 additions & 1 deletion install/install.bat
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ for %%I in ("%DIR%\..") do set "ROOT=%%~fI"
set "NAME=blender_niftools_addon"
set /p VERSION=<%ROOT%\io_scene_niftools\VERSION.txt
for /f %%i in ('git rev-parse --short HEAD') do set HASH=%%i
for /f %%i in ('echo %date%') do set DATE=%%i
:: Use PowerShell to get current date in YYYY-MM-DD format independent of local format
for /f %%i in ('powershell -executionpolicy bypass -Command Get-Date -Format "yyyy-MM-dd"') do set DATE=%%i
set "ZIP_NAME=%NAME%-%VERSION%-%DATE%-%HASH%"

if "%BLENDER_ADDONS_DIR%" == "" if not exist "%BLENDER_ADDONS_DIR%" (
Expand Down
2 changes: 1 addition & 1 deletion install/makezip.bat
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ mkdir "%DEPS%"

python -m pip install "PyFFI==%PYFFI_VERSION%" --target="%DEPS%"

xcopy "%GENERATED_FOLDER%" "%DEPS%\generated" /s /q /i
xcopy "%GENERATED_FOLDER%" "%DEPS%\nifgen" /s /q /i

xcopy "%ROOT%"\AUTHORS.rst io_scene_niftools
xcopy "%ROOT%"\CHANGELOG.rst io_scene_niftools
Expand Down
2 changes: 1 addition & 1 deletion install/makezip.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ echo "Creating dependencies folder ${DEPS_OUT:-${BUILD_DIR}/dependencies}"
python -m pip install "PyFFI==${PYFFI_VERSION}" --target="${DEPS_OUT:-${BUILD_DIR}/dependencies}"

echo "Copying loose files"
cp -r "$GENERATED_FOLDER" "${DEPS_OUT:-${BUILD_DIR}/dependencies}/generated"
cp -r "$GENERATED_FOLDER" "${DEPS_OUT:-${BUILD_DIR}/dependencies}/nifgen"
cp "${ROOT}"/AUTHORS.rst "${ADDON_OUT}"
cp "${ROOT}"/CHANGELOG.rst "${ADDON_OUT}"
cp "${ROOT}"/LICENSE.rst "${ADDON_OUT}"
Expand Down
15 changes: 14 additions & 1 deletion install/zip.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,20 @@ write ("Existing archive removed successfully")
}

Add-Type -assembly "system.io.compression.filesystem"
[io.compression.zipfile]::CreateFromDirectory($source, $destination, 1, 1)

$EncoderClass=@"
public class FixedEncoder : System.Text.UTF8Encoding {
public FixedEncoder() : base(true) { }
public override byte[] GetBytes(string s) {
s = s.Replace("\\", "/");
return base.GetBytes(s);
}
}
"@
Add-Type -TypeDefinition $EncoderClass

$Encoder = New-Object FixedEncoder
[io.compression.zipfile]::CreateFromDirectory($source, $destination, 1, 1, $Encoder)
If(Test-path $destination) {
write("File successully written")
}
2 changes: 1 addition & 1 deletion io_scene_niftools/VERSION.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v0.1.0
v0.1.1
4 changes: 2 additions & 2 deletions io_scene_niftools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
"description": "Import and export files in the NetImmerse/Gamebryo formats (.nif, .kf, .egm)",
"author": "Niftools team",
"blender": (2, 82, 0),
"version": (0, 1, 0), # can't read from VERSION, blender wants it hardcoded
"version": (0, 1, 1), # can't read from VERSION, blender wants it hardcoded
"api": 39257,
"location": "File > Import-Export",
"warning": "Generally stable port of the Niftool's Blender NifScripts, many improvements, still work in progress",
Expand All @@ -72,7 +72,7 @@ def locate_dependencies():

with open(os.path.join(current_dir, "VERSION.txt")) as version:
NifLog.info(f"Loading: Blender Niftools Addon: {version.read()}")
import generated.formats.nif as NifFormat
import nifgen.formats.nif as NifFormat
NifLog.info(f"Loading: NifFormat: {NifFormat.__xml_version__}") # todo [generated] update this and library to have actual versioning


Expand Down
2 changes: 2 additions & 0 deletions io_scene_niftools/egm_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ def execute(self):
b_obj = bpy.context.view_layer.objects.active
if b_obj and b_obj.type == "MESH":
self.morph_anim.import_egm_morphs(b_obj)
else:
NifLog.warn(f'Selected object {b_obj.name} is not a mesh object, nothing will be imported.')
except NifError:
return {'CANCELLED'}

Expand Down
2 changes: 1 addition & 1 deletion io_scene_niftools/file_io/nif.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@

import os.path as path

import generated.formats.nif as NifFormat
import nifgen.formats.nif as NifFormat

from io_scene_niftools.utils.logging import NifLog, NifError

Expand Down
2 changes: 1 addition & 1 deletion io_scene_niftools/kf_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ def execute(self):
data.neosteam = (bpy.context.scene.niftools_scene.game == 'NEOSTEAM')

# scale correction for the skeleton
self.apply_scale(data, round(1 / NifOp.props.scale_correction))
self.apply_scale(data, 1 / NifOp.props.scale_correction)

data.validate()

Expand Down
2 changes: 1 addition & 1 deletion io_scene_niftools/modules/nif_export/animation/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
from abc import ABC

import bpy
from generated.formats.nif import classes as NifClasses
from nifgen.formats.nif import classes as NifClasses

from io_scene_niftools.modules.nif_export.block_registry import block_store
from io_scene_niftools.utils.singleton import NifOp, NifData
Expand Down
2 changes: 1 addition & 1 deletion io_scene_niftools/modules/nif_export/animation/material.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
#
# ***** END LICENSE BLOCK *****

from generated.formats.nif import classes as NifClasses
from nifgen.formats.nif import classes as NifClasses

from io_scene_niftools.modules.nif_export.animation import Animation
from io_scene_niftools.modules.nif_export.block_registry import block_store
Expand Down
2 changes: 1 addition & 1 deletion io_scene_niftools/modules/nif_export/animation/morph.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
#
# ***** END LICENSE BLOCK *****

from generated.formats.nif import classes as NifClasses
from nifgen.formats.nif import classes as NifClasses
from pyffi.formats.egm import EgmFormat

from io_scene_niftools.modules.nif_export.animation import Animation
Expand Down
2 changes: 1 addition & 1 deletion io_scene_niftools/modules/nif_export/animation/object.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
# ***** END LICENSE BLOCK *****

import bpy
from generated.formats.nif import classes as NifClasses
from nifgen.formats.nif import classes as NifClasses

from io_scene_niftools.modules.nif_export.animation import Animation
from io_scene_niftools.modules.nif_export.block_registry import block_store
Expand Down
13 changes: 7 additions & 6 deletions io_scene_niftools/modules/nif_export/animation/transform.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
import bpy
import mathutils

from generated.formats.nif import classes as NifClasses
from nifgen.formats.nif import classes as NifClasses

from io_scene_niftools.modules.nif_export.animation import Animation
from io_scene_niftools.modules.nif_export.block_registry import block_store
Expand Down Expand Up @@ -69,12 +69,13 @@ def iter_frame_key(fcurves, mathutilclass):
def export_kf_root(self, b_armature=None):
"""Creates and returns a KF root block and exports controllers for objects and bones"""
scene = bpy.context.scene
game = scene.niftools_scene.game
nif_scene = scene.niftools_scene
game = nif_scene.game
if game in ('MORROWIND', 'FREEDOM_FORCE'):
kf_root = block_store.create_block("NiSequenceStreamHelper")
elif game in (
'SKYRIM', 'OBLIVION', 'FALLOUT_3', 'CIVILIZATION_IV', 'ZOO_TYCOON_2', 'FREEDOM_FORCE_VS_THE_3RD_REICH',
'MEGAMI_TENSEI_IMAGINE', 'SID_MEIER_S_PIRATES'):
elif nif_scene.is_bs() or game in (
'CIVILIZATION_IV', 'ZOO_TYCOON_2', 'FREEDOM_FORCE_VS_THE_3RD_REICH',
'SHIN_MEGAMI_TENSEI_IMAGINE', 'SID_MEIER_S_PIRATES'):
kf_root = block_store.create_block("NiControllerSequence")
else:
raise NifError(f"Keyframe export for '{game}' is not supported.")
Expand All @@ -87,7 +88,7 @@ def export_kf_root(self, b_armature=None):
b_action = self.get_active_action(b_armature)
for b_bone in b_armature.data.bones:
self.export_transforms(kf_root, b_armature, b_action, b_bone)
if game in ('SKYRIM',):
if nif_scene.is_skyrim():
targetname = "NPC Root [Root]"
else:
# quick hack to set correct target name
Expand Down
2 changes: 1 addition & 1 deletion io_scene_niftools/modules/nif_export/armature/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ def export_bone_flags(self, b_bone, n_node):
n_node.flags = b_bone.niftools.flags
else:
game = bpy.context.scene.niftools_scene.game
if game in ('OBLIVION', 'FALLOUT_3', 'SKYRIM'):
if bpy.context.scene.niftools_scene.is_bs():
# default for Oblivion bones
# note: bodies have 0x000E, clothing has 0x000F
n_node.flags = 0x000E
Expand Down
2 changes: 1 addition & 1 deletion io_scene_niftools/modules/nif_export/block_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
#
# ***** END LICENSE BLOCK *****

import generated.formats.nif as NifFormat
import nifgen.formats.nif as NifFormat

import io_scene_niftools.utils.logging
from io_scene_niftools.utils import math
Expand Down
18 changes: 9 additions & 9 deletions io_scene_niftools/modules/nif_export/collision/havok.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
import bpy
import mathutils

from generated.formats.nif import classes as NifClasses
from nifgen.formats.nif import classes as NifClasses

import io_scene_niftools.utils.logging
from io_scene_niftools.modules.nif_export.block_registry import block_store
Expand All @@ -57,7 +57,8 @@ class BhkCollision(Collision):
EXPORT_OB_SOLID = True

def __init__(self):
self.HAVOK_SCALE = consts.HAVOK_SCALE
# to be filled during the export process:
self.HAVOK_SCALE = None

def export_collision_helper(self, b_obj, parent_block):
"""Helper function to add collision objects to a node. This function
Expand All @@ -77,9 +78,7 @@ def export_collision_helper(self, b_obj, parent_block):
coll_ispacked = (rigid_body.collision_shape == 'MESH')

# Set Havok Scale ratio
b_scene = bpy.context.scene.niftools_scene
if b_scene.user_version == 12 and b_scene.user_version_2 == 83:
self.HAVOK_SCALE = consts.HAVOK_SCALE * 10
self.HAVOK_SCALE = NifData.data.havok_scale

# find physics properties/defaults
# get havok material name from material name
Expand Down Expand Up @@ -175,6 +174,7 @@ def export_bhk_collison_object(self, b_obj):
col_filter = b_obj.nifcollision.col_filter

n_col_obj = block_store.create_block("bhkCollisionObject", b_obj)
n_col_obj.flags._value = 0
if layer == NifClasses.OblivionLayer.OL_ANIM_STATIC and col_filter != 128:
# animated collision requires flags = 41
# unless it is a constrainted but not keyframed object
Expand Down Expand Up @@ -203,7 +203,7 @@ def export_bhk_blend_controller(self, b_obj, parent_block):

# TODO [collision] Move to collision
def update_rigid_bodies(self):
if bpy.context.scene.niftools_scene.game in ('OBLIVION', 'FALLOUT_3', 'SKYRIM'):
if bpy.context.scene.niftools_scene.is_bs():
n_rigid_bodies = [n_rigid_body for n_rigid_body in block_store.block_to_obj if isinstance(n_rigid_body, NifClasses.BhkRigidBody)]

# update rigid body center of gravity and mass
Expand Down Expand Up @@ -244,9 +244,9 @@ def export_bhk_packed_nitristrip_shape(self, b_obj, n_col_mopp):
n_col_shape = block_store.create_block("bhkPackedNiTriStripsShape", b_obj)
# TODO [collision] radius has default of 0.1, but maybe let depend on margin
scale = n_col_shape.scale
scale.x = 0
scale.y = 0
scale.z = 0
scale.x = 1.0
scale.y = 1.0
scale.z = 1.0
scale.w = 0
n_col_shape.scale_copy = scale
n_col_mopp.shape = n_col_shape
Expand Down
16 changes: 10 additions & 6 deletions io_scene_niftools/modules/nif_export/constraint/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,20 @@
import bpy
import mathutils

from generated.formats.nif import classes as NifClasses
from nifgen.formats.nif import classes as NifClasses

import io_scene_niftools.utils.logging
from io_scene_niftools.modules.nif_export.block_registry import block_store
from io_scene_niftools.utils import math, consts
from io_scene_niftools.utils import math
from io_scene_niftools.utils.logging import NifLog
from io_scene_niftools.utils.singleton import NifOp
from io_scene_niftools.utils.singleton import NifOp, NifData


class Constraint:

def __init__(self):
self.HAVOK_SCALE = consts.HAVOK_SCALE
# to be filled during the export process:
self.HAVOK_SCALE = None

def export_constraints(self, b_obj, root_block):
"""Export the constraints of an object.
Expand All @@ -70,10 +71,13 @@ def export_constraints(self, b_obj, root_block):
# skip text buffers etc
return

# Set Havok Scale ratio
self.HAVOK_SCALE = NifData.data.havok_scale

for b_constr in b_obj.constraints:
# rigid body joints
if b_constr.type == 'RIGID_BODY_JOINT':
if bpy.context.scene.niftools_scene.game not in ('OBLIVION', 'FALLOUT_3', 'SKYRIM'):
if bpy.context.scene.niftools_scene.is_bs():
NifLog.warn(f"Only Oblivion/Fallout/Skyrim rigid body constraints currently supported: Skipping {b_constr}.")
continue
# check that the object is a rigid body
Expand Down Expand Up @@ -126,7 +130,7 @@ def export_constraints(self, b_obj, root_block):
max_friction = 0
else:
# non-malleable typically have 10
if bpy.context.scene.niftools_scene.game == 'FALLOUT_3':
if bpy.context.scene.niftools_scene.is_fo3():
max_friction = 100
else: # oblivion
max_friction = 10
Expand Down
Loading

0 comments on commit 0305c8d

Please sign in to comment.