diff options
Diffstat (limited to 'drafts')
-rwxr-xr-x | drafts/init-v0.1-from-3DS-io-addon.py | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/drafts/init-v0.1-from-3DS-io-addon.py b/drafts/init-v0.1-from-3DS-io-addon.py new file mode 100755 index 0000000..32d0ad0 --- /dev/null +++ b/drafts/init-v0.1-from-3DS-io-addon.py @@ -0,0 +1,214 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + +bl_info = { + "name": "Export Half-Life 1 Tools Format(.map)", + "author": "Ludovic Pouzenc", + "version": (0, 1, 0), + "blender": (2, 79, 0), + "location": "File > Export > Half-Life 1 tools (.map)", + "description": "Export mesh to Half-Life 1 tools (.map)", + "warning": "", + #"wiki_url": "http://to.do", + "category": "Import-Export"} + +""" +Related links: +https://developer.valvesoftware.com/wiki/MAP_file_format + +Usage Notes: +Map file could be opened in Valve Hammer 3.4 editor (prefered bit windows only) +or passed to orignal's or ZLHT's compiler tools (use wine to run them on linux) + +MAP format defines solids (brushes) as a set of intersecting planes. +Planes a defined by 3 points in space (could be different from face's vertices) + +This is (very) unusual. This cannot reprents things such as : +* Concave meshes +* Non-planar faces +Existing tools that use this .map format probably don't cope with : +* ngons with n > 32 + +For now this script do : +* For each mesh in current scene +** Simplify it (remove doubles in vertices, fill holes, connect vertices to not have concave faces nor non planar faces) +** Recalc face normals to have them pointing to this outside of the mesh +* For each object in current scene that is type 'MESH' +** Take the mesh and local to world matrix +** Make a .map brush for each mesh's blender face (world coords, scaled by blender_to_map_scale_factor) +** Put AAATRIGGER texture stupidly +** Output it as part of worldspawn entity in .map + +""" + +if "bpy" in locals(): + import importlib +# if "import_3ds" in locals(): +# importlib.reload(import_hl1map) + if "export_hl1map" in locals(): + importlib.reload(export_hl1map) + +import bpy +from bpy.props import ( + BoolProperty, + CollectionProperty, + FloatProperty, + StringProperty, + ) +from bpy_extras.io_utils import ( +# ImportHelper, + ExportHelper, + ) + +#class ImportHL1MAP(bpy.types.Operator, ImportHelper): +# """Import Half-Life 1 Tools Format(.map)""" +# bl_idname = "import_scene.hl1_map" +# bl_label = 'Half-Life 1 tools (.map)' +# bl_options = {'UNDO'} + +# filename_ext = ".map" +# filter_glob = StringProperty(default="*.map", options={'HIDDEN'}) + +# constrain_size = FloatProperty( +# name="Size Constraint", +# description="Scale the model by 10 until it reaches the " +# "size constraint (0 to disable)", +# min=0.0, max=1000.0, +# soft_min=0.0, soft_max=1000.0, +# default=10.0, +# ) +# use_image_search = BoolProperty( +# name="Image Search", +# description="Search subdirectories for any associated images " +# "(Warning, may be slow)", +# default=True, +# ) +# use_apply_transform = BoolProperty( +# name="Apply Transform", +# description="Workaround for object transformations " +# "importing incorrectly", +# default=True, +# ) + +# def execute(self, context): +# from . import import_3ds + +# keywords = self.as_keywords(ignore=("axis_forward", +# "axis_up", +# "filter_glob", +# )) + +# global_matrix = axis_conversion(from_forward=self.axis_forward, +# from_up=self.axis_up, +# ).to_4x4() +# keywords["global_matrix"] = global_matrix + +# return import_3ds.load(self, context, **keywords) + +class WorldSpawnEntityProp(bpy.types.PropertyGroup): + value = bpy.props.StringProperty(name='') + +class ExportHL1MAP(bpy.types.Operator, ExportHelper): + """Export Half-Life 1 Tools Format(.map)""" + bl_idname = 'export_scene.hl1_map' + bl_label = 'Export HL1 .map' + + filename_ext = '.map' + + filter_glob = StringProperty(default='*'+filename_ext, options={'HIDDEN'}) + + use_selection = BoolProperty( + name='Selection Only', + description='Export selected objects only', + default=False, + ) + + blender_to_map_scale_factor = FloatProperty( + name='Upscaling factor', + description='Scale from blender world coordinates to map brush coordinates', + default=100, + ) + # self.attrs is a list of objects representing application specific and dynamically set attributes + attrs = [] + # https://developer.valvesoftware.com/wiki/MAP_file_format + collection = CollectionProperty( + name='Worldspawn entity properties', + description='All non-entity brushes in .map belongs to a Worldspawn entity that have mandatory properties to be ran in-game', + type=WorldSpawnEntityProp, + ) + + worldspawn_props = { + 'classname': 'worldspawn', + 'sounds': 1, + 'MaxRange': 4096, + 'mapversion': 220, + 'wad': '\\half-life\\valve\\xeno.wad;\\half-life\\valve\\decals.wad;\\half-life\\valve\\halflife.wad;\\half-life\\valve\\liquids.wad' + } + def invoke(self, context, event): + self.collection.clear() + for attr in self.attrs: + # create a new item in self.collection + collectionItem = self.collection.add() + collectionItem.name = attr.name + collectionItem.value = attr.value + attr.collectionItem = collectionItem + return super(ExportHL1MAP, self).invoke(context, event) + # FIXME https://blenderartists.org/t/how-to-set-a-property-for-an-operator-dynamically/615897/6 + # def draw(self, context): + # layout = self.layout + # for attr in self.attrs: + # attrName = attr[0] + # row = self.layout.split() + # # it's not possible to set the name for an item in self.collection, + # # however it's possible to set a label dynamically + # row.label(attr.name) + # # the following property refers to the attribute <value> of the item in self.collection + # # remember the attribute <value> was defined in the class CustomFloatProperty + # row.prop(attr.collectionItem, "value") + # return super(ExportHL1MAP, self).draw(context) + + def execute(self, context): + from . import export_hl1map + keywords = self.as_keywords(ignore=('filter_glob','check_existing')) + keywords['worldspawn_props'] = self.worldspawn_props + print('export_hl1map.save(self, context, ', keywords, ')') + return export_hl1map.save(self, context, **keywords) + + + +# Add to a menu +def menu_func_export(self, context): + self.layout.operator(ExportHL1MAP.bl_idname, text="Half-Life 1 tools (.map)") + +#def menu_func_import(self, context): +# self.layout.operator(ImportHL1MAP.bl_idname, text="Half-Life 1 tools (.map)") + + +def register(): + bpy.utils.register_module(__name__) +# bpy.types.INFO_MT_file_import.append(menu_func_import) + bpy.types.INFO_MT_file_export.append(menu_func_export) + + +def unregister(): + bpy.utils.unregister_module(__name__) +# bpy.types.INFO_MT_file_import.remove(menu_func_import) + bpy.types.INFO_MT_file_export.remove(menu_func_export) + +if __name__ == "__main__": + register() |