From 7b2d51e2a85062f78179810286569b53f5dc5ee6 Mon Sep 17 00:00:00 2001 From: Vakhurin Sergey Date: Tue, 5 Jul 2016 06:04:20 +0300 Subject: [PATCH] fix #88: armature was imported with obsolete version of this plugin implemented a more accurate warning --- io_scene_xray/fmt_object_exp.py | 12 +++++++++--- io_scene_xray/fmt_object_imp.py | 3 ++- io_scene_xray/plugin.py | 2 +- io_scene_xray/shape_edit_helper.py | 2 ++ io_scene_xray/xray_inject.py | 31 +++++++++++++++++++++++++++++- io_scene_xray/xray_inject_ui.py | 11 +++++++++-- tests/external | 2 +- tests/utils.py | 4 ++-- 8 files changed, 56 insertions(+), 11 deletions(-) diff --git a/io_scene_xray/fmt_object_exp.py b/io_scene_xray/fmt_object_exp.py index d1dfb528..b78614ac 100644 --- a/io_scene_xray/fmt_object_exp.py +++ b/io_scene_xray/fmt_object_exp.py @@ -200,11 +200,11 @@ def _export_mesh(bpy_obj, bpy_root, cw, cx): __matrix_bone_inv = __matrix_bone.inverted() -def _export_bone(bpy_arm_obj, bpy_root, bpy_bone, writers, bonemap): +def _export_bone(bpy_arm_obj, bpy_root, bpy_bone, writers, bonemap, cx): real_parent = find_bone_real_parent(bpy_bone) if real_parent: if bonemap.get(real_parent) is None: - _export_bone(bpy_arm_obj, bpy_root, real_parent, bonemap) + _export_bone(bpy_arm_obj, bpy_root, real_parent, bonemap, cx) xr = bpy_bone.xray cw = ChunkedWriter() @@ -225,6 +225,12 @@ def _export_bone(bpy_arm_obj, bpy_root, bpy_bone, writers, bonemap): .putf('fff', -e.x, -e.z, -e.y) .putf('f', xr.length)) cw.put(Chunks.Bone.MATERIAL, PackedWriter().puts(xr.gamemtl)) + v = xr.shape.check_version_different() + if v != 0: + cx.report({'WARNING'}, 'bone {} edited with {} version of this plugin'.format( + bpy_bone.name, + xr.shape.fmt_version_different(v), + )) cw.put(Chunks.Bone.SHAPE, PackedWriter() .putf('H', int(xr.shape.type)) .putf('H', xr.shape.flags) @@ -298,7 +304,7 @@ def scan_r(bpy_obj): for b in bpy_arm_obj.data.bones: if is_fake_bone(b): continue - _export_bone(bpy_arm_obj, bpy_root, b, bones, bonemap) + _export_bone(bpy_arm_obj, bpy_root, b, bones, bonemap, cx) for mw in meshes: msw.put(idx, mw) idx += 1 diff --git a/io_scene_xray/fmt_object_imp.py b/io_scene_xray/fmt_object_imp.py index 37bb61b3..dc6ce66c 100644 --- a/io_scene_xray/fmt_object_imp.py +++ b/io_scene_xray/fmt_object_imp.py @@ -361,6 +361,7 @@ def _import_bone(cx, cr, bpy_arm_obj, renamemap): elif cid == Chunks.Bone.MATERIAL: xray.gamemtl = PackedReader(data).gets() elif cid == Chunks.Bone.SHAPE: + from io_scene_xray.xray_inject import XRayBoneProperties pr = PackedReader(data) _safe_assign_enum_property(cx, xray.shape, 'type', str(pr.getf('H')[0]), desc=('bone', name, 'shape')) xray.shape.flags = pr.getf('H')[0] @@ -373,6 +374,7 @@ def _import_bone(cx, cr, bpy_arm_obj, renamemap): xray.shape.cyl_dir = pr.getf('fff') xray.shape.cyl_hgh = pr.getf('f')[0] xray.shape.cyl_rad = pr.getf('f')[0] + xray.shape.version_data = XRayBoneProperties.ShapeProperties.CURVER_DATA elif cid == Chunks.Bone.IK_JOINT: pr = PackedReader(data) bp = bpy_arm_obj.pose.bones[name] @@ -515,7 +517,6 @@ def _import_main(fpath, cx, cr): bpy_armature = cx.bpy.data.armatures.new(object_name) bpy_armature.use_auto_ik = True bpy_armature.draw_type = 'STICK' - bpy_armature.xray.version = cx.version bpy_arm_obj = cx.bpy.data.objects.new(object_name, bpy_armature) bpy_arm_obj.show_x_ray = True bpy_arm_obj.parent = bpy_obj diff --git a/io_scene_xray/plugin.py b/io_scene_xray/plugin.py index a5226eec..c69b9dae 100644 --- a/io_scene_xray/plugin.py +++ b/io_scene_xray/plugin.py @@ -235,7 +235,7 @@ class _WithExportMotions: export_motions = plugin_prefs.PropObjectMotionsExport() -class OpExportObjects(bpy.types.Operator, _WithExportMotions): +class OpExportObjects(TestReadyOperator, _WithExportMotions): bl_idname = 'export_object.xray_objects' bl_label = 'Export selected .object-s' diff --git a/io_scene_xray/shape_edit_helper.py b/io_scene_xray/shape_edit_helper.py index b43000f8..26e95d4f 100644 --- a/io_scene_xray/shape_edit_helper.py +++ b/io_scene_xray/shape_edit_helper.py @@ -154,6 +154,8 @@ def maxabs(*args): xsh.cyl_dir = vr.to_tuple() else: raise AssertionError('unsupported shape type: ' + xsh.type) + from io_scene_xray.xray_inject import XRayBoneProperties + xsh.version_data = XRayBoneProperties.ShapeProperties.CURVER_DATA for obj in bpy.data.objects: if obj.data == bone.id_data: bpy.context.scene.objects.active = obj diff --git a/io_scene_xray/xray_inject.py b/io_scene_xray/xray_inject.py index eec768cd..a0488cea 100644 --- a/io_scene_xray/xray_inject.py +++ b/io_scene_xray/xray_inject.py @@ -168,9 +168,12 @@ class XRayMaterialProperties(bpy.types.PropertyGroup): class XRayArmatureProperties(bpy.types.PropertyGroup): b_type = bpy.types.Armature - version = bpy.props.IntProperty() display_bone_shapes = bpy.props.BoolProperty(name='Display Bone Shapes', default=False) + def check_different_version_bones(self): + from functools import reduce + return reduce(lambda x,y: x|y, [b.xray.shape.check_version_different() for b in self.id_data.bones], 0) + class XRayBoneProperties(bpy.types.PropertyGroup): class BreakProperties(bpy.types.PropertyGroup): @@ -178,6 +181,31 @@ class BreakProperties(bpy.types.PropertyGroup): torque = bpy.props.FloatProperty() class ShapeProperties(bpy.types.PropertyGroup): + CURVER_DATA = 1 + + def check_version_different(self): + def iszero(vec): + return not any(v for v in vec) + + if self.version_data == self.CURVER_DATA: + return 0 + if self.type == '0': # none + return 0 + elif self.type == '1': # box + if iszero(self.box_trn) and iszero(self.box_rot) and iszero(self.box_hsz): + return 0 # default shape + elif self.type == '2': # sphere + if iszero(self.sph_pos) and not self.sph_rad: + return 0 # default shape + elif self.type == '3': # cylinder + if iszero(self.cyl_pos) and iszero(self.cyl_dir) and not self.cyl_rad and not self.cyl_hgh: + return 0 # default shape + return 1 if self.version_data < XRayBoneProperties.ShapeProperties.CURVER_DATA else 2 + + @staticmethod + def fmt_version_different(r): + return 'obsolete' if r == 1 else ('newest' if r == 2 else 'different') + def update_shape_type(self, context): if not self.edit_mode: return @@ -212,6 +240,7 @@ def update_shape_type(self, context): cyl_dir = bpy.props.FloatVectorProperty() cyl_hgh = bpy.props.FloatProperty() cyl_rad = bpy.props.FloatProperty() + version_data = bpy.props.IntProperty() class IKJointProperties(bpy.types.PropertyGroup): type = bpy.props.EnumProperty(items=( diff --git a/io_scene_xray/xray_inject_ui.py b/io_scene_xray/xray_inject_ui.py index d579ebad..df32451a 100644 --- a/io_scene_xray/xray_inject_ui.py +++ b/io_scene_xray/xray_inject_ui.py @@ -264,9 +264,12 @@ def poll(cls, context): def draw(self, context): layout = self.layout data = context.active_object.data.xray + v = data.check_different_version_bones() + if v != 0: + from io_scene_xray.xray_inject import XRayBoneProperties + layout.label('Found bones, edited with ' + XRayBoneProperties.ShapeProperties.fmt_version_different( + v) + ' version of this plugin', icon='ERROR') layout.prop(data, 'display_bone_shapes') - if data.version < 4: - layout.label('This armature was imported with obsolete version of this plugin', icon='ERROR') class XRayBonePanel(XRayPanel): @@ -288,6 +291,10 @@ def draw(self, context): _gen_xr_selector(layout, data, 'gamemtl', 'gamemtl') box = layout.box() box.prop(data.shape, 'type', 'shape type') + v = data.shape.check_version_different() + if v != 0: + box.label('shape edited with ' + data.shape.fmt_version_different(v) + ' version of this plugin', + icon='ERROR') seh.draw(box.column(align=True), bone) row = box.row(align=True) diff --git a/tests/external b/tests/external index 1ef14e2f..28a726a8 160000 --- a/tests/external +++ b/tests/external @@ -1 +1 @@ -Subproject commit 1ef14e2f88438f9019aa409fccdfee91a83ca818 +Subproject commit 28a726a83e004f558382d195be1d3f6d22d62443 diff --git a/tests/utils.py b/tests/utils.py index 3458b1a8..f6a01502 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -58,13 +58,13 @@ def _findReport(self, type=None, re_message=None): continue m = re_message.match(r[1]) if m is not None: - return m.group(1) + return m def assertReportsContains(self, type=None, re_message=None): r = self._findReport(type, re_message) if r is not None: return r - raise self.fail('Cannot find report with: type={}, message={}'.format(type, re_message)) + raise self.fail('Cannot find report with: type={}, message={} in reports: {}'.format(type, re_message, self._reports)) def assertReportsNotContains(self, type=None, re_message=None): r = self._findReport(type, re_message)