diff --git a/CHANGELOG.md b/CHANGELOG.md index 86683da..c93a0a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,20 +8,21 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) ### Changed ### Fixed -## [1.4.2] +## [1.4.2] 2020-07-06 ### Added +- Added carinfo.cca import, carinfo.txt export for managing positions and mesh list - Added p3d model info print into python console on export - Added option to export model with modifiers applied(Enabled by default) - Added option to use EdgeSplit modifier when importing model - Auto exit edit mode when exporting - Set correct smoothing based on material when importing - Automatically add .tga to material names on export if not present -- Replace unsupported characters on export with '_' - Empty 'floor_level' object in the scene now defines in-game floor level +- Replace unsupported characters in materials on export with '_' ### Changed ### Fixed - Fixed unnecessary info printing on export -- If object have no materials colwhite.tga will be used by default +- If object have no materials, colwhite.tga will be used by default ## [1.4.1] - 2020-07-04 ### Added diff --git a/io_scene_cdp3d/__init__.py b/io_scene_cdp3d/__init__.py index 4db9ba3..04d6d3d 100644 --- a/io_scene_cdp3d/__init__.py +++ b/io_scene_cdp3d/__init__.py @@ -21,7 +21,7 @@ "author": "Wurunduk", "blender": (2, 83, 0), "location": "File > Import-Export", - "version": (1, 4, 1), + "version": (1, 4, 2), "support": 'COMMUNITY', "category": "Import-Export"} @@ -45,7 +45,20 @@ ExportHelper, ) +class ImportCDCCA(bpy.types.Operator, ImportHelper): + bl_idname = "import_scene.crashday_cca" + bl_label = 'Import CCA' + bl_options = {'UNDO'} + + filename_ext = ".cca" + filter_glob: StringProperty(default="*.cca", options={'HIDDEN'}) + def execute(self, context): + from . import import_cdp3d + keywords = self.as_keywords(ignore=("filter_glob", + )) + + return import_cdp3d.load_cca(self, context, **keywords) class ImportCDP3D(bpy.types.Operator, ImportHelper): bl_idname = "import_scene.crashday_p3d" @@ -87,6 +100,24 @@ def execute(self, context): return import_cdp3d.load(self, context, **keywords) +class ExportCDCCA(bpy.types.Operator, ExportHelper): + bl_idname = "export_scene.crashday_cca" + bl_label = 'Export CCA' + + filename_ext = ".txt" + filter_glob:StringProperty( + default="*.txt", + options={'HIDDEN'}, + ) + + def execute(self, context): + from . import export_cdp3d + + keywords = self.as_keywords(ignore=("filter_glob", + "check_existing", + )) + + return export_cdp3d.save_cca(self, context, **keywords) class ExportCDP3D(bpy.types.Operator, ExportHelper): bl_idname = "export_scene.crashday_p3d" @@ -146,7 +177,7 @@ class ExportCDP3D(bpy.types.Operator, ExportHelper): export_log: BoolProperty( name = "Export Log", description = "Create a log file of export process with useful data", - default=True, + default=False, ) def execute(self, context): @@ -161,16 +192,20 @@ def execute(self, context): # Add to a menu def menu_func_export(self, context): - self.layout.operator(ExportCDP3D.bl_idname, text="Crashday model(.p3d)") + self.layout.operator(ExportCDP3D.bl_idname, text="Crashday Model(.p3d)") + self.layout.operator(ExportCDCCA.bl_idname, text="Crashday Carinfo Pos(.txt)") def menu_func_import(self, context): - self.layout.operator(ImportCDP3D.bl_idname, text="Crashday model(.p3d)") + self.layout.operator(ImportCDP3D.bl_idname, text="Crashday Model(.p3d)") + self.layout.operator(ImportCDCCA.bl_idname, text="Crashday Carinfo(.cca)") def register(): bpy.utils.register_class(ExportCDP3D) + bpy.utils.register_class(ExportCDCCA) bpy.utils.register_class(ImportCDP3D) + bpy.utils.register_class(ImportCDCCA) bpy.types.TOPBAR_MT_file_import.append(menu_func_import) bpy.types.TOPBAR_MT_file_export.append(menu_func_export) @@ -178,7 +213,9 @@ def register(): def unregister(): bpy.utils.unregister_class(ExportCDP3D) + bpy.utils.unregister_class(ExportCDCCA) bpy.utils.unregister_class(ImportCDP3D) + bpy.utils.unregister_class(ImportCDCCA) bpy.types.TOPBAR_MT_file_import.remove(menu_func_import) bpy.types.TOPBAR_MT_file_export.remove(menu_func_export) diff --git a/io_scene_cdp3d/export_cdp3d.py b/io_scene_cdp3d/export_cdp3d.py index 312e546..5f0f97a 100644 --- a/io_scene_cdp3d/export_cdp3d.py +++ b/io_scene_cdp3d/export_cdp3d.py @@ -366,3 +366,66 @@ def save(operator, log_file.close() return {'FINISHED'} + +def save_pos(f, col, name): + obj = col.objects.get(name) + pos = (0.0,0.0,0.0) + if obj is not None: + p = obj.location + pos = (p[0], p[2], p[1]) + + f.write('{:.4g} {:.4g} {:.4g} \t\t\t # {}{}\n'.format(pos[0], pos[1], pos[2], '!!!NOT FOUND ON EXPORT ' if obj is None else '', name)) + +def save_pos2(f, col, name): + obj = col.objects.get(name) + print(obj) + pos = (0.0,0.0,0.0) + if obj is not None: + p = obj.location + pos = (p[0], p[2], p[1]) + + f.write('{:.4g} \t\t\t # {}{}\n'.format(pos[2], '!!!NOT FOUND ON EXPORT ' if obj is None else '', name)) + +def save_cca(operator, + context, filepath=''): + + f = open(filepath, 'w') + col = bpy.context.scene + + exported_meshes_string = '' + + for ob in col.collection.all_objects: + if ob.type == 'MESH': + exported_meshes_string += ob.name + ' ' + + f.write('Meshes: {}\n\n'.format(exported_meshes_string)) + + save_pos(f, col, 'center_of_gravity_pos') + f.write('\n') + save_pos(f, col, 'left_upper_wheel_pos') + save_pos(f, col, 'right_lower_wheel_pos') + save_pos(f, col, 'minigun_pos') + f.write('0.0\t\t\t # Angle of minigun (negative values for downpointing)\n') + save_pos(f, col, 'mines_pos') + save_pos(f, col, 'missiles_pos') + save_pos(f, col, 'driver_pos') + save_pos(f, col, 'exhaust_pos') + save_pos(f, col, 'exhaust2_pos') + save_pos(f, col, 'flag_pos') + save_pos(f, col, 'bomb_pos') + save_pos(f, col, 'cockpit_cam_pos') + save_pos(f, col, 'roof_cam_pos') + save_pos(f, col, 'hood_cam_pos') + save_pos(f, col, 'bumper_cam_pos') + save_pos(f, col, 'rear_view_cam_pos') + save_pos(f, col, 'left_side_cam_pos') + save_pos(f, col, 'right_side_cam_pos') + save_pos(f, col, 'driver1_cam_pos') + save_pos(f, col, 'driver2_cam_pos') + save_pos(f, col, 'driver3_cam_pos') + save_pos(f, col, 'steering_wheel_pos') + save_pos(f, col, 'car_cover_pos') + save_pos2(f, col, 'engine_pos') + + f.close() + return {'FINISHED'} \ No newline at end of file diff --git a/io_scene_cdp3d/import_cdp3d.py b/io_scene_cdp3d/import_cdp3d.py index df56c07..b605b21 100644 --- a/io_scene_cdp3d/import_cdp3d.py +++ b/io_scene_cdp3d/import_cdp3d.py @@ -179,6 +179,13 @@ def create_lights(p3d_model, col): col.objects.link(light_object) +def create_pos(col, pos, name): + obj = bpy.data.objects.new(name, None) + col.objects.link(obj) + + obj.location = pos + obj.empty_display_type = 'PLAIN_AXES' + def load(operator, context, use_edge_split_modifier=True, @@ -217,10 +224,71 @@ def load(operator, create_lights(p, col) create_meshes(p, col) - floor_level = bpy.data.objects.new('floor_level', None) - col.objects.link(floor_level) + create_pos(col, (0.0, 0.0, - p.height/2.0), 'floor_level') + + return {'FINISHED'} + +def add_position(line, col, name): + line = line.split('#')[0] + line = line.strip() + pos = [float(i) for i in line.split(' ')] + + if len(pos) != 3: + return + + temp = pos[1] + pos[1] = pos[2] + pos[2] = temp + + create_pos(col, pos, name) - floor_level.location = (0.0,0.0, - p.height/2.0) - floor_level.empty_display_type = 'PLAIN_AXES' +# thanks CD for storing a position as one float yes +def add_position2(line, col, name): + line = line.split('#')[0] + line = line.strip() + pos = float(line) + + create_pos(col, (0.0, pos, 0.0), name) + + +def load_cca(operator, context, filepath=''): + file = open(filepath, 'r') + content = file.readlines() + + col = bpy.data.collections.new('Positions') + bpy.context.scene.collection.children.link(col) + + add_position(content[6], col, 'center_of_gravity_pos') + + p = content.index('--- Positions ---\n') + + add_position(content[p+2], col, 'left_upper_wheel_pos') + add_position(content[p+3], col, 'right_lower_wheel_pos') + add_position(content[p+4], col, 'minigun_pos') + add_position(content[p+6], col, 'mines_pos') + add_position(content[p+7], col, 'missiles_pos') + add_position(content[p+8], col, 'driver_pos') + add_position(content[p+9], col, 'exhaust_pos') + add_position(content[p+10], col, 'exhaust2_pos') + add_position(content[p+11], col, 'flag_pos') + add_position(content[p+12], col, 'bomb_pos') + add_position(content[p+13], col, 'cockpit_cam_pos') + add_position(content[p+14], col, 'roof_cam_pos') + add_position(content[p+15], col, 'hood_cam_pos') + add_position(content[p+16], col, 'bumper_cam_pos') + add_position(content[p+17], col, 'rear_view_cam_pos') + add_position(content[p+18], col, 'left_side_cam_pos') + add_position(content[p+19], col, 'right_side_cam_pos') + add_position(content[p+20], col, 'driver1_cam_pos') + add_position(content[p+21], col, 'driver2_cam_pos') + add_position(content[p+22], col, 'driver3_cam_pos') + add_position(content[p+23], col, 'steering_wheel_pos') + add_position(content[p+24], col, 'car_cover_pos') + add_position2(content[p+25], col, 'engine_pos') + + file.close() return {'FINISHED'} + + +