Skip to content

Commit

Permalink
Merge pull request #72 from MrClock8163/dev
Browse files Browse the repository at this point in the history
v2.4.1
  • Loading branch information
MrClock8163 authored Sep 30, 2024
2 parents 0398697 + 95744bf commit 93aaa9c
Show file tree
Hide file tree
Showing 41 changed files with 642 additions and 603 deletions.
13 changes: 13 additions & 0 deletions Arma3ObjectBuilder/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# Changelog

## [v2.4.1](https://github.com/MrClock8163/Arma3ObjectBuilder/releases/tag/v2.4.1) (Blender 2.90 -> 4.2)

### Changes

- internal handling of the P3D data was simplified and improved
- internal code structure and dependencies were cleaned up
- improved add-on reloading

### Fixed

- named properties were not properly lowercased with the Force Lowercase export option during P3D export
- animation action property classes were not properly unregistered when the add-on was deactivated or reloaded

## [v2.4.0](https://github.com/MrClock8163/Arma3ObjectBuilder/releases/tag/v2.4.0) (Blender 2.90 -> 4.2)

### Added
Expand Down
94 changes: 71 additions & 23 deletions Arma3ObjectBuilder/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,56 @@
"name": "Arma 3 Object Builder",
"description": "Collection of tools for editing Arma 3 content",
"author": "MrClock (present add-on), Hans-Joerg \"Alwarren\" Frieden (original ArmaToolbox add-on)",
"version": (2, 4, 0),
"version": (2, 4, 1),
"blender": (2, 90, 0),
"location": "Object Builder panels",
"warning": "",
"warning": "Development",
"doc_url": "https://mrcmodding.gitbook.io/arma-3-object-builder/home",
"tracker_url": "https://github.com/MrClock8163/Arma3ObjectBuilder/issues",
"category": "Import-Export"
}


import os

if "bpy" in locals():
import importlib
from importlib import reload

importlib.reload(props)
importlib.reload(ui)
importlib.reload(flagutils)

else:
from . import props
from . import ui
from .utilities import flags as flagutils
if "utilities" in locals():
reload(utilities)
if "io" in locals():
reload(io)
if "props" in locals():
reload(props)
if "ui" in locals():
reload(ui)

import bpy


addon_prefs = None
addon_dir = os.path.abspath(os.path.dirname(os.path.realpath(__file__)))
addon_icons = {}

def get_icon(name):
icon = 0
try:
icon = addon_icons[addon_prefs.icon_theme.lower()][name].icon_id
except Exception:
pass

return icon

def get_prefs():
return addon_prefs


from . import utilities
from . import io
from . import props
from . import ui


def outliner_enable_update(self, context):
if self.outliner == 'ENABLED' and ui.tool_outliner.depsgraph_update_post_handler not in bpy.app.handlers.depsgraph_update_post:
bpy.app.handlers.depsgraph_update_post.append(ui.tool_outliner.depsgraph_update_post_handler)
Expand All @@ -52,8 +77,7 @@ def execute(self, context):
from winreg import OpenKey, QueryValueEx, HKEY_CURRENT_USER
key = OpenKey(HKEY_CURRENT_USER, r"software\bohemia interactive\arma 3 tools")
value, _type = QueryValueEx(key, "path")
prefs = context.preferences.addons[__package__].preferences
prefs.a3_tools = value
addon_prefs.a3_tools = value

except Exception:
self.report({'ERROR'}, "The Arma 3 Tools installation could not be found, it has to be set manually")
Expand Down Expand Up @@ -124,13 +148,13 @@ def poll(cls, context):

def invoke(self, context, event):
prefs = context.preferences.addons[__package__].preferences
flagutils.set_flag_vertex(self, prefs.flag_vertex)
utilities.flags.set_flag_vertex(self, prefs.flag_vertex)

return context.window_manager.invoke_props_dialog(self)

def execute(self, context):
prefs = context.preferences.addons[__package__].preferences
prefs.flag_vertex = flagutils.get_flag_vertex(self)
prefs.flag_vertex = utilities.flags.get_flag_vertex(self)

return {'FINISHED'}

Expand Down Expand Up @@ -176,13 +200,13 @@ def poll(cls, context):

def invoke(self, context, event):
prefs = context.preferences.addons[__package__].preferences
flagutils.set_flag_face(self, prefs.flag_face)
utilities.flags.set_flag_face(self, prefs.flag_face)

return context.window_manager.invoke_props_dialog(self)

def execute(self, context):
prefs = context.preferences.addons[__package__].preferences
prefs.flag_face = flagutils.get_flag_face(self)
prefs.flag_face = utilities.flags.get_flag_face(self)

return {'FINISHED'}

Expand Down Expand Up @@ -345,30 +369,54 @@ def draw(self, context):
)


def register_icons():
import bpy.utils.previews

themes_dir = os.path.join(addon_dir, "icons")
for theme in os.listdir(themes_dir):
theme_icons = bpy.utils.previews.new()

icons_dir = os.path.join(themes_dir, theme)
for filename in os.listdir(icons_dir):
theme_icons.load(os.path.splitext(os.path.basename(filename))[0].lower(), os.path.join(icons_dir, filename), 'IMAGE')

addon_icons[theme.lower()] = theme_icons


def unregister_icons():
import bpy.utils.previews

for icon in addon_icons.values():
bpy.utils.previews.remove(icon)

addon_icons.clear()


def register():
from bpy.utils import register_class
from .utilities import generic


print("Registering Arma 3 Object Builder ( '" + __package__ + "' )")

for cls in classes:
register_class(cls)

global addon_prefs
addon_prefs = bpy.context.preferences.addons[__package__].preferences

for mod in modules:
mod.register()

generic.register_icons()
register_icons()

print("Register done")


def unregister():
from bpy.utils import unregister_class
from .utilities import generic

print("Unregistering Arma 3 Object Builder ( '" + __package__ + "' )")

generic.unregister_icons()
unregister_icons()

for mod in reversed(modules):
mod.unregister()
Expand Down
2 changes: 1 addition & 1 deletion Arma3ObjectBuilder/blender_manifest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ type = "add-on"
id = "Arma3ObjectBuilder"
name = "Arma 3 Object Builder"
tagline = "Comprehensive add-on for modding Arma 3"
version = "2.4.0"
version = "2.4.1"
blender_version_min = "4.2.0"
website = "https://mrcmodding.gitbook.io/arma-3-object-builder/home"
tags = ["Import-Export", "Game Engine", "Object"]
Expand Down
44 changes: 44 additions & 0 deletions Arma3ObjectBuilder/io/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,46 @@
if "binary_handler" in locals():
from importlib import reload

if "binary_handler" in locals():
reload(binary_handler)
if "compression" in locals():
reload(compression)
if "data_asc" in locals():
reload(data_asc)
if "data_p3d" in locals():
reload(data_p3d)
if "data_rap" in locals():
reload(data_rap)
if "data_rtm" in locals():
reload(data_rtm)
if "data_tbcsv" in locals():
reload(data_tbcsv)
if "export_asc" in locals():
reload(export_asc)
if "export_mcfg" in locals():
reload(export_mcfg)
if "export_p3d" in locals():
reload(export_p3d)
if "export_rtm" in locals():
reload(export_rtm)
if "export_tbcsv" in locals():
reload(export_tbcsv)
if "import_armature" in locals():
reload(import_armature)
if "import_asc" in locals():
reload(import_asc)
if "import_mcfg" in locals():
reload(import_mcfg)
if "import_p3d" in locals():
reload(import_p3d)
if "import_rtm" in locals():
reload(import_rtm)
if "import_tbcsv" in locals():
reload(import_tbcsv)


from . import binary_handler
from . import compression
from . import data_asc
from . import data_p3d
from . import data_rap
Expand All @@ -8,8 +50,10 @@
from . import export_mcfg
from . import export_p3d
from . import export_rtm
from . import export_tbcsv
from . import import_armature
from . import import_asc
from . import import_mcfg
from . import import_p3d
from . import import_rtm
from . import import_tbcsv
26 changes: 8 additions & 18 deletions Arma3ObjectBuilder/io/binary_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@


import struct
import functools
import itertools


def read_byte(file):
Expand Down Expand Up @@ -76,33 +78,21 @@ def read_char(file, count = 1):
# In theory all strings in BI files should be strictly ASCII,
# but on the off chance that a corrupt character is present, the method would fail.
# Therefore using UTF-8 decoding is more robust, and gives the same result for valid ASCII values.
# https://stackoverflow.com/a/32775270
def read_asciiz(file):
res = b''

while True:
a = file.read(1)
if a == b'\x00' or a == b'':
break

res += a

return res.decode('utf8', errors="replace")
eof = iter(functools.partial(file.read, 1), "")
return b"".join(itertools.takewhile(b"\x00".__ne__, eof)).decode('utf8', errors="replace")

def read_asciiz_field(file, field_len):
field = file.read(field_len)
if len(field) < field_len:
raise EOFError("ASCIIZ field ran into unexpected EOF")

result = bytearray()
for value in field:
if value == 0:
break

result.append(value)
else:
parts = field.split(b"\x00")
if len(parts) < 2:
raise ValueError("ASCIIZ field length overflow")

return result.decode('utf8', errors="replace")
return parts[0].decode('utf8', errors="replace")

def read_lascii(file):
length = read_byte(file)
Expand Down
Loading

0 comments on commit 93aaa9c

Please sign in to comment.