diff --git a/.gitignore b/.gitignore index 1f30155..3b81a77 100644 --- a/.gitignore +++ b/.gitignore @@ -4,5 +4,6 @@ __pycache__ *.VC.* .vs /old.txt -/Test Install.bat +/Install to Blender Scripts Folder.bat /UpgradeLog.htm +/UpgradeLog2.htm diff --git a/io_scene_valvesource/__init__.py b/io_scene_valvesource/__init__.py index 778e5b6..3363270 100644 --- a/io_scene_valvesource/__init__.py +++ b/io_scene_valvesource/__init__.py @@ -19,15 +19,15 @@ # ##### END GPL LICENSE BLOCK ##### bl_info = { - "name": "Blender Source Tools (BST-Fix-279)", + "name": "Blender Source Tools (BST-Fix+ for 2.79)", "author": "Tom Edwards (translators: Grigory Revzin), modified by TF", - "version": (2, 10, 2, 999, 1), + "version": (2, 10, 2, 999, 2), "blender": (2, 74, 0), "category": "Import-Export", "location": "File > Import/Export, Scene properties", "wiki_url": "http://steamcommunity.com/groups/BlenderSourceTools", "tracker_url": "http://steamcommunity.com/groups/BlenderSourceTools/discussions/0/", - "description": "Importer and exporter for Valve Software's Source Engine. Supports SMD\VTA, DMX and QC." + "description": "Importer and exporter for Valve Software's Source Engine. Supports SMD\VTA, DMX and QC. Fork of the last official 2.79 release with some improvements." } import bpy, os diff --git a/io_scene_valvesource/import_smd.py b/io_scene_valvesource/import_smd.py index 84731d8..3b2f7f1 100644 --- a/io_scene_valvesource/import_smd.py +++ b/io_scene_valvesource/import_smd.py @@ -54,6 +54,8 @@ class SmdImporter(bpy.types.Operator, Logger): rotMode = EnumProperty(name=get_id("importer_rotmode"),items=rotModes,default='XYZ',description=get_id("importer_rotmode_tip")) boneMode = EnumProperty(name=get_id("importer_bonemode"),items=(('NONE','Default',''),('ARROWS','Arrows',''),('SPHERE','Sphere','')),default='SPHERE',description=get_id("importer_bonemode_tip")) + createEyeballBones = BoolProperty(name=get_id("importert_doeyebones"), description=get_id("importert_doeyebones_tooltip"), default=False) + def execute(self, context): pre_obs = set(bpy.context.scene.objects) pre_eem = context.user_preferences.edit.use_enter_edit_mode @@ -66,7 +68,7 @@ def execute(self, context): for filepath in [os.path.join(self.directory,file.name) for file in self.files] if self.files else [self.filepath]: filepath_lc = filepath.lower() if filepath_lc.endswith('.qc') or filepath_lc.endswith('.qci'): - self.num_files_imported = self.readQC(filepath, False, self.properties.doAnim, self.properties.makeCamera, self.properties.rotMode, outer_qc=True) + self.num_files_imported = self.readQC(filepath, False, self.properties.doAnim, self.properties.makeCamera, self.properties.rotMode, self.properties.createEyeballBones, outer_qc=True) bpy.context.scene.objects.active = self.qc.a elif filepath_lc.endswith('.smd'): self.num_files_imported = self.readSMD(filepath, self.properties.upAxis, self.properties.rotMode) @@ -442,7 +444,9 @@ def applyFrames(self,keyframes,num_frames, fps = None): ops.pose.armature_apply() bone_vis = None if self.properties.boneMode == 'NONE' else bpy.data.objects.get("smd_bone_vis") - + if self.qc: + self.qc.bone_vis = bone_vis + if self.properties.boneMode == 'SPHERE' and (not bone_vis or bone_vis.type != 'MESH'): ops.mesh.primitive_ico_sphere_add(subdivisions=3,size=2) bone_vis = bpy.context.active_object @@ -972,7 +976,7 @@ def vec_round(v): print("- Imported",num_shapes,"flex shapes") # Parses a QC file - def readQC(self, filepath, newscene, doAnim, makeCamera, rotMode, outer_qc = False): + def readQC(self, filepath, newscene, doAnim, makeCamera, rotMode, createEyeballBones, outer_qc = False): filename = os.path.basename(filepath) filedir = os.path.dirname(filepath) @@ -1150,7 +1154,22 @@ def import_file(word_index,default_ext,type,append='APPEND',layer=0,in_file_recu if line[0] in ["$collisionmodel","$collisionjoints"]: import_file(1,"smd",PHYS,'VALIDATE',layer=10) # FIXME: what if there are >10 LODs? continue + + # define bones from qc eyeball commands + if createEyeballBones: + if line[0] == "eyeball": + eyeballName = line[1] + parentBoneName = line[2] + positionX = line[3] + positionY = line[4] + positionZ = line[5] + print("QC defined eyeball bone \"" + eyeballName + "\" on parent bone \"" + parentBoneName + "\" at pos X: " + positionX + " Y: " + positionY + " Z: " + positionZ) + + if not hasattr(qc, "queued_eyebones"): + qc.queued_eyebones = [] + qc.queued_eyebones.append([eyeballName, parentBoneName, float(positionX), float(positionY), float(positionZ)]) + # origin; this is where viewmodel editors should put their camera, and is in general something to be aware of if line[0] == "$origin": if qc.makeCamera: @@ -1203,6 +1222,38 @@ def import_file(word_index,default_ext,type,append='APPEND',layer=0,in_file_recu file.close() + + # Create queued eyeball bones + if hasattr(qc, "queued_eyebones"): + # Make actual edit_bones + if not qc.a: qc.a = self.findArmature() + bpy.context.scene.objects.active = qc.a + ops.object.mode_set(mode='EDIT') + + createdBones = [] + + for bonedef in qc.queued_eyebones: + parentBone = None + for eb in qc.a.data.edit_bones: # Bone names used in the eyeball qc command are case insensitive + print("eb.name", eb.name) + if (eb.name.lower() == bonedef[1].lower()): + parentBone = eb + break + + eyeballBone = qc.a.data.edit_bones.new(bonedef[0]) + eyeballBone.head = (bonedef[2], bonedef[3], bonedef[4]) + eyeballBone.tail = (bonedef[2], bonedef[3] - 0.25, bonedef[4]) + eyeballBone.parent = parentBone + + createdBones.append(bonedef[0]) + + # Set visual bone model + ops.object.mode_set(mode='OBJECT') + + for bonedef in qc.queued_eyebones: + qc.a.pose.bones[bonedef[0]].custom_shape = qc.bone_vis + + if qc.origin: qc.origin.parent = qc.a if qc.ref_mesh: @@ -1214,6 +1265,7 @@ def import_file(word_index,default_ext,type,append='APPEND',layer=0,in_file_recu if outer_qc: printTimeMessage(qc.startTime,filename,"import","QC") + return self.num_files_imported def initSMD(self, filepath,smd_type,upAxis,rotMode,target_layer): diff --git a/io_scene_valvesource/translations.py b/io_scene_valvesource/translations.py index 3bdd644..c6390e5 100644 --- a/io_scene_valvesource/translations.py +++ b/io_scene_valvesource/translations.py @@ -577,6 +577,12 @@ 'en': "Bone shapes", 'ru': "Отображение костей", }, +'importert_doeyebones': { + 'en': "Create eyeball bones", +}, +'importert_doeyebones_tooltip': { + 'en': "Create bones for each QC eyeball command. Useful for adapting Source's 2D eyes system with different engines.", +}, 'importer_err_nofile': { 'ja': "選択ファイルはありません", 'en': "No file selected",