diff --git a/tools/io_qfmap/entity.py b/tools/io_qfmap/entity.py index 0886f9703..02232fdc3 100644 --- a/tools/io_qfmap/entity.py +++ b/tools/io_qfmap/entity.py @@ -21,18 +21,32 @@ import bpy from bpy.props import BoolProperty, FloatProperty, StringProperty, EnumProperty -from bpy.props import BoolVectorProperty, PointerProperty +from bpy.props import BoolVectorProperty, CollectionProperty, PointerProperty +from bpy.props import FloatVectorProperty, IntProperty + +from .entityclass import EntityClass def qfentity_items(self, context): qfmap = context.scene.qfmap entclasses = qfmap.entity_classes.entity_classes eclist = list(entclasses.keys()) eclist.sort() - return tuple(map(lambda ec: (ec, ec, entclasses[ec].comment), eclist)) + enum = (('', '--', 'No class. Will be exported as part of the world entity.'),) + enum += tuple(map(lambda ec: (ec, ec, entclasses[ec].comment), eclist)) + return enum + +class QFEntityProp(bpy.types.PropertyGroup): + name = StringProperty() + float = FloatProperty() + vector = FloatVectorProperty() + string = StringProperty() + list_control = StringProperty(default="string", options={'HIDDEN'}) class QFEntity(bpy.types.PropertyGroup): classname = EnumProperty(items = qfentity_items, name = "Entity Class") flags = BoolVectorProperty(size=12) + fields = CollectionProperty(type=QFEntityProp) + field_idx = IntProperty() class EntityPanel(bpy.types.Panel): bl_space_type = 'PROPERTIES' @@ -48,7 +62,10 @@ class EntityPanel(bpy.types.Panel): layout = self.layout obj = context.active_object qfmap = context.scene.qfmap - ec = qfmap.entity_classes.entity_classes[obj.qfentity.classname] + if obj.qfentity.classname: + ec = qfmap.entity_classes.entity_classes[obj.qfentity.classname] + else: + ec = EntityClass.null() flags = ec.flagnames + ("",) * (8 - len(ec.flagnames)) flags += ("!easy", "!medium", "!hard", "!dm") layout.prop(obj.qfentity, "classname") @@ -58,7 +75,9 @@ class EntityPanel(bpy.types.Panel): sub = col.column(align=True) for r in range(4): idx = c * 4 + r - sub.prop(obj.qfentity, "flags", text = flags[idx], index = idx) + sub.prop(obj.qfentity, "flags", text=flags[idx], index=idx) + layout.template_list(obj.qfentity, "fields", obj.qfentity, "field_idx", + prop_list="list_control") def default_brush_entity(entityclass): name = entityclass.name @@ -102,6 +121,21 @@ def entity_box(entityclass): mesh.materials.append(mat) return mesh +def set_entity_props(obj, ent): + qfe = obj.qfentity + if "classname" in ent.d: + qfe.classname = ent.d["classname"] + if "spawnflags" in ent.d: + flags = int(float(ent.d["spawnflags"])) + for i in range(12): + qfe.flags[i] = (flags & (1 << i)) and True or False + for key in ent.d.keys(): + if key in {"classname", "spawnflags", "origin"}: + continue + item = qfe.fields.add() + item.name = key + item.string = ent.d[key] + def add_entity(self, context, entclass): entity_class = context.scene.qfmap.entity_classes.entity_classes[entclass] context.user_preferences.edit.use_global_undo = False diff --git a/tools/io_qfmap/entityclass.py b/tools/io_qfmap/entityclass.py index 03f456f4d..c45294e74 100644 --- a/tools/io_qfmap/entityclass.py +++ b/tools/io_qfmap/entityclass.py @@ -14,6 +14,9 @@ class EntityClass: self.flagnames = flagnames self.comment = comment @classmethod + def null(cls): + return cls('', (1, 1, 1), None, (), "") + @classmethod def from_quaked(cls, text, filename, line = 0): script = Script(filename, text) if line: diff --git a/tools/io_qfmap/import_map.py b/tools/io_qfmap/import_map.py index ba6a0f4b0..14e9e6a30 100644 --- a/tools/io_qfmap/import_map.py +++ b/tools/io_qfmap/import_map.py @@ -24,11 +24,12 @@ import os import bpy from bpy_extras.object_utils import object_data_add from mathutils import Vector,Matrix +from math import pi from .map import parse_map, MapError from .quakepal import palette from .wad import WadFile -from .entity import entity_box +from .entity import entity_box, set_entity_props def parse_vector(vstr): v = vstr.split() @@ -109,10 +110,6 @@ def process_entity(ent, wads): light.distance = 300.0 light.falloff_type = 'CUSTOM_CURVE' obj = bpy.data.objects.new(name, light) - obj.location = parse_vector (ent.d["origin"]) - bpy.context.scene.objects.link(obj) - bpy.context.scene.objects.active=obj - obj.select = True elif ent.b: verts = [] faces = [] @@ -156,9 +153,6 @@ def process_entity(ent, wads): uvloop.data[k].uv = uv[j] mesh.update() obj = bpy.data.objects.new(name, mesh) - bpy.context.scene.objects.link(obj) - bpy.context.scene.objects.active=obj - obj.select = True else: if entityclass.size: mesh = entity_box(entityclass) @@ -168,10 +162,24 @@ def process_entity(ent, wads): obj.empty_draw_type = 'CUBE' obj.empty_draw_size = 8 obj.show_name = True + if "origin" in ent.d: obj.location = parse_vector (ent.d["origin"]) - bpy.context.scene.objects.link(obj) - bpy.context.scene.objects.active=obj - obj.select = True + angles = Vector() + if not ent.b: + #brush entities doen't normally support rotation + if "angle" in ent.d: + angles = Vector((0, 0, float(ent.d["angle"]))) + del ent.d["angle"] + elif "angles" in ent.d: + angles = parse_vector(ent.d["angles"]) + angles = angles.xzy + del ent.d["angles"] + obj.rotation_mode = 'XZY' + obj.rotation_euler = angles * pi / 180 + bpy.context.scene.objects.link(obj) + bpy.context.scene.objects.active=obj + obj.select = True + set_entity_props(obj, ent) def import_map(operator, context, filepath): bpy.context.user_preferences.edit.use_global_undo = False