Skip to content

Commit

Permalink
Merge pull request #578 from niftools/develop for version 0.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Candoran2 authored Jun 20, 2023
2 parents e8ede44 + 09dae59 commit 43341a1
Show file tree
Hide file tree
Showing 77 changed files with 1,717 additions and 1,648 deletions.
2 changes: 1 addition & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion AUTHORS.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,14 @@ Contributors
------------

* Aaron1178
* Allofich
* Alphax
* Arcimaestro
* Arthmoor
* Artorp

* Deedes
* Eli2
* enpinion
* Entim
* Eugenius-v
* Fritz_fretz
Expand All @@ -37,11 +38,13 @@ Contributors
* mgm101
* opusGlass
* Pacificmorrowind
* paulgreenG
* Pentinen
* @reddraconi
* shon
* @SubhadeepG
* @TagnumElite
* TackYs
* Tamira
* Thedaywalker
* Tijer
Expand Down
33 changes: 33 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,36 @@
Version v0.1.00
===============

- #576 Updates to documentation, changelog and makezip.bat (copies over generated folder from cobra-tools).
- #572 Extra development of NiMesh import and some fixes
- Fix to BSInvMarker rotation export.
- Fix for bs_data_flags setting in export - now also applied to other games where applicable, not just Skyrim.
- Fix to transform on packed collision vertices export.
- Adjust StringProperty arguments to prevent crash in Blender 3.2 or lower.
- Fix to mistake in BhkMalleableConstraint info import.
- Added processing of regions to NiMesh bone import.
- Basic DisplayList import (NiMesh with a specific type of datastream, which encodes the geometry). Bone weights for this type of nif are still unimplemented.
- #543 Use "Color" type for "InvertY" group
- #541 NiMesh import and updates for newer xml
- Nif file glob now partially dependent on xml.
- Support for NiMesh import (except those using DisplayList).
- Support for BSDynamicTriShape import.
- Update to Object properties ui (now only show relevant properties)
- Closes #533 "Unknown block type BSDynamicTriShape".
- Closes #421 "Can't import catherine classic .nif files."
- #535 Pyffi overhaul
- Change kf and nif import to make use of the new statically generated nif reading/writing library.
- Added support for SSE mesh import.
- Closes #521.
- #526 Allow setting armature axis manually
- #524 int cast in add_dummy_markers to comply with blender 3.1+'s python and check for interpolator attribute on controller before accessing it.
- #506 Speedup anim import & various other fixes
- Closes #180
- Closes #495
- Closes #500
- Closes #510
- Closes #517

Version v0.0.14
===============

Expand Down
12 changes: 12 additions & 0 deletions docs/user/features/geometry/geometry.rst
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,15 @@ Vertex Color & Alpha
* `This image should clarify per-face vertex colouring
<http://i211.photobucket.com/albums/bb189/NifTools/Blender/documentation/per_face_vertex_color.jpg>`_
* On export, the scripts will create extra vertices for different vertex colors per face.


.. _geometry-shapekeys:

Shape Key Animations
--------------------

**Example:**

#. :ref:`Create a mesh-object <geometry-mesh>`.
#. Add relative shape keys to your mesh.
#. Keyframe each shape key's value so that the key influences the shape of the mesh at the desired time.
4 changes: 2 additions & 2 deletions docs/user/features/object/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,8 @@ First, we complete the object panel:
#. Set your **BSX Flags**.
#. Select a **Consistency Flag** from the drop-down box. See `this comment
<https://github.com/niftools/nifskope/issues/69#issuecomment-61427385>`_ for discussion of what they might do.
#. The **Object Flag** is ???????. Set it to an appropriate number.
#. The **Nif Long Name** is ???????. Set it to an appropriate string.
#. The **Object Flag** corresponds to the flags field on NiAVObjects. The exact meaning will differ based on the block type. Set it to an appropriate number. If left to 0, will use a default value.
#. The **Nif Long Name** is the actual name used for the corresponding block in the nif. You can either set it to an appropriate string, or leave it empty. In the latter case, the nif name will be determined based on the blender name of the object.
#. The **Skeleton Root** determines the root bone used in this mesh's SkinInstance. Can usually be ignored / left empty, falls back to the armature object = root node.

.. Extra Data and InvMarkers I have no idea how to fill them in. Help?
Expand Down
19 changes: 17 additions & 2 deletions install/makezip.bat
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,26 @@ mkdir "%DEPS%"

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

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

xcopy "%ROOT%"\AUTHORS.rst io_scene_niftools
xcopy "%ROOT%"\CHANGELOG.rst io_scene_niftools
xcopy "%ROOT%"\LICENSE.rst io_scene_niftools
xcopy "%ROOT%"\README.rst io_scene_niftools

:: remove all __pycache__ folders
for /d /r %%x in (*) do if "%%~nx" == "__pycache__" rd %%x /s /q

popd

powershell -executionpolicy bypass -Command "%DIR%\zip.ps1" -source "%DIR%\temp\io_scene_niftools" -destination "%DIR%\%ZIP_NAME%.zip"
rmdir /s /q %DIR%\temp
set "COMMAND_FILE=%DIR%\zip.ps1"
set "COMMAND_FILE=%COMMAND_FILE: =` %"

set "SOURCE_DIR=%DIR%\temp\io_scene_niftools"
set "SOURCE_DIR=%SOURCE_DIR: =` %"

set "DESTINATION_DIR=%DIR%\%ZIP_NAME%.zip"
set "DESTINATION_DIR=%DESTINATION_DIR: =` %"

powershell -executionpolicy bypass -Command "%COMMAND_FILE%" -source "%SOURCE_DIR%" -destination "%DESTINATION_DIR%"
rmdir /s /q "%DIR%\temp"
2 changes: 1 addition & 1 deletion io_scene_niftools/VERSION.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v0.0.14
v0.1.0
6 changes: 3 additions & 3 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, 0, 14), # can't read from VERSION, blender wants it hardcoded
"version": (0, 1, 0), # 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,8 +72,8 @@ def locate_dependencies():

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


locate_dependencies()
Expand Down
69 changes: 0 additions & 69 deletions io_scene_niftools/file_io/kf.py

This file was deleted.

17 changes: 9 additions & 8 deletions io_scene_niftools/file_io/nif.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,9 @@
#
# ***** END LICENSE BLOCK *****

import os.path as path

from pyffi.formats.nif import NifFormat
import generated.formats.nif as NifFormat

from io_scene_niftools.utils.logging import NifLog, NifError

Expand All @@ -51,18 +52,18 @@ def load_nif(file_path):
"""Loads a nif from the given file path"""
NifLog.info(f"Importing {file_path}")

data = NifFormat.Data()
file_ext = path.splitext(file_path)[1]

# open file for binary reading
with open(file_path, "rb") as nif_stream:
# check if nif file is valid
data.inspect_version_only(nif_stream)
if data.version >= 0:
modification, (version, user_version, bs_version) = NifFormat.NifFile.inspect_version_only(nif_stream)
if version >= 0:
# it is valid, so read the file
NifLog.info(f"NIF file version: {data.version:x}")
NifLog.info("Reading file")
data.read(nif_stream)
elif data.version == -1:
NifLog.info(f"NIF file version: {version:x}")
NifLog.info(f"Reading {file_ext} file")
data = NifFormat.NifFile.from_stream(nif_stream)
elif version == -1:
raise NifError("Unsupported NIF version.")
else:
raise NifError("Not a NIF file.")
Expand Down
8 changes: 3 additions & 5 deletions io_scene_niftools/kf_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,6 @@
import os
import bpy

import pyffi.spells.nif.fix

from io_scene_niftools.file_io.kf import KFFile
from io_scene_niftools.modules.nif_export import armature
from io_scene_niftools.modules.nif_export.animation.transform import TransformAnimation
from io_scene_niftools.nif_common import NifCommon
from io_scene_niftools.utils import math
Expand All @@ -69,7 +65,7 @@ def execute(self):
directory = os.path.dirname(NifOp.props.filepath)
filebase, fileext = os.path.splitext(os.path.basename(NifOp.props.filepath))

if bpy.context.scene.niftools_scene.game == 'NONE':
if bpy.context.scene.niftools_scene.game == 'UNKNOWN':
raise NifError("You have not selected a game. Please select a game in the scene tab.")

prefix = "x" if bpy.context.scene.niftools_scene.game in ('MORROWIND',) else ""
Expand All @@ -95,6 +91,8 @@ def execute(self):
# scale correction for the skeleton
self.apply_scale(data, round(1 / NifOp.props.scale_correction))

data.validate()

kffile = os.path.join(directory, prefix + filebase + ext)
with open(kffile, "wb") as stream:
data.write(stream)
Expand Down
7 changes: 2 additions & 5 deletions io_scene_niftools/kf_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,7 @@

import os

import pyffi.spells.nif.fix

from io_scene_niftools.file_io.kf import KFFile
from io_scene_niftools.modules.nif_export import armature
from io_scene_niftools.file_io.nif import NifFile as KFFile
from io_scene_niftools.modules.nif_import.animation.transform import TransformAnimation
from io_scene_niftools.nif_common import NifCommon
from io_scene_niftools.utils import math
Expand Down Expand Up @@ -72,7 +69,7 @@ def execute(self):
# get nif space bind pose of armature here for all anims
self.transform_anim.get_bind_data(b_armature)
for kf_file in kf_files:
kfdata = KFFile.load_kf(kf_file)
kfdata = KFFile.load_nif(kf_file)

self.apply_scale(kfdata, NifOp.props.scale_correction)

Expand Down
24 changes: 12 additions & 12 deletions 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 pyffi.formats.nif import NifFormat
from generated.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 Expand Up @@ -93,14 +93,14 @@ def get_controllers(nodes):
"""find all nodes and relevant controllers"""
node_kfctrls = {}
for node in nodes:
if not isinstance(node, NifFormat.NiAVObject):
if not isinstance(node, NifClasses.NiAVObject):
continue
# get list of all controllers for this node
ctrls = node.get_controllers()
for ctrl in ctrls:
if bpy.context.scene.niftools_scene.game == 'MORROWIND':
# morrowind: only keyframe controllers
if not isinstance(ctrl, NifFormat.NiKeyframeController):
if not isinstance(ctrl, NifClasses.NiKeyframeController):
continue
if node not in node_kfctrls:
node_kfctrls[node] = []
Expand Down Expand Up @@ -132,14 +132,14 @@ def create_controller(self, parent_block, target_name, priority=0):
# link interpolator from the controller
n_kfc.interpolator = n_kfi
# if parent is a node, attach controller to that node
if isinstance(parent_block, NifFormat.NiNode):
if isinstance(parent_block, NifClasses.NiNode):
parent_block.add_controller(n_kfc)
if n_kfi:
# set interpolator default data
n_kfi.scale, n_kfi.rotation, n_kfi.translation = parent_block.get_transform().get_scale_quat_translation()

# else ControllerSequence, so create a link
elif isinstance(parent_block, NifFormat.NiControllerSequence):
elif isinstance(parent_block, NifClasses.NiControllerSequence):
controlled_block = parent_block.add_controlled_block()
controlled_block.priority = priority
# todo - pyffi adds the names to the NiStringPalette, but it creates one per controller link...
Expand All @@ -159,15 +159,15 @@ def create_controller(self, parent_block, target_name, priority=0):
controlled_block.controller_type = "NiTransformController"
# get the parent's string palette
if not parent_block.string_palette:
parent_block.string_palette = NifFormat.NiStringPalette()
parent_block.string_palette = NifClasses.NiStringPalette(NifData.data)
# assign string palette to controller
controlled_block.string_palette = parent_block.string_palette
# add the strings and store their offsets
palette = controlled_block.string_palette.palette
controlled_block.node_name_offset = palette.add_string(controlled_block.node_name)
controlled_block.controller_type_offset = palette.add_string(controlled_block.controller_type)
# morrowind style
elif isinstance(parent_block, NifFormat.NiSequenceStreamHelper):
elif isinstance(parent_block, NifClasses.NiSequenceStreamHelper):
# create node reference by name
nodename_extra = block_store.create_block("NiStringExtraData")
nodename_extra.bytes_remaining = len(target_name) + 4
Expand All @@ -184,14 +184,14 @@ def create_controller(self, parent_block, target_name, priority=0):
@staticmethod
def get_n_interp_from_b_interp(b_ipol):
if b_ipol == "LINEAR":
return NifFormat.KeyType.LINEAR_KEY
return NifClasses.KeyType.LINEAR_KEY
elif b_ipol == "BEZIER":
return NifFormat.KeyType.QUADRATIC_KEY
return NifClasses.KeyType.QUADRATIC_KEY
elif b_ipol == "CONSTANT":
return NifFormat.KeyType.CONST_KEY
return NifClasses.KeyType.CONST_KEY

NifLog.warn(f"Unsupported interpolation mode ({b_ipol}) in blend, using quadratic/bezier.")
return NifFormat.KeyType.QUADRATIC_KEY
return NifClasses.KeyType.QUADRATIC_KEY

def add_dummy_markers(self, b_action):
# if we exported animations, but no animation groups are defined,
Expand All @@ -201,4 +201,4 @@ def add_dummy_markers(self, b_action):
NifLog.info("Defining default action pose markers.")
for frame, text in zip(b_action.frame_range, ("Idle: Start/Idle: Loop Start", "Idle: Loop Stop/Idle: Stop")):
marker = b_action.pose_markers.new(text)
marker.frame = frame
marker.frame = int(frame)
Loading

0 comments on commit 43341a1

Please sign in to comment.