diff options
author | Daniel Stokes <kupomail@gmail.com> | 2013-12-18 02:42:47 +0400 |
---|---|---|
committer | kupoman <kupomail@gmail.com> | 2013-12-18 05:03:27 +0400 |
commit | e9e08a1d12594eab0e341049fc252ff8578e9333 (patch) | |
tree | ac7c15959b03398babb68058f3824c2a4dbff5b7 /release | |
parent | 173f7a3d30db8cba95656bf03dc842b9300c2436 (diff) |
Game Engine: Level of detail support and tools
Levels of detail can be added and modified in the object panel. The object
panel also contains new tools for generating levels of detail, setting up
levels of detail based on object names (useful for importing), and
clearing an object's level of detail settings. This is meant as a game
engine feature, though the level of details settings can be previewed in
the viewport.
Reviewed By: moguri, nexyon, brecht
Differential Revision: http://developer.blender.org/D109
Diffstat (limited to 'release')
-rw-r--r-- | release/scripts/startup/bl_operators/object.py | 151 | ||||
-rw-r--r-- | release/scripts/startup/bl_ui/properties_object.py | 45 |
2 files changed, 195 insertions, 1 deletions
diff --git a/release/scripts/startup/bl_operators/object.py b/release/scripts/startup/bl_operators/object.py index e5e53d6a4dc..3218af06cc7 100644 --- a/release/scripts/startup/bl_operators/object.py +++ b/release/scripts/startup/bl_operators/object.py @@ -775,3 +775,154 @@ class DupliOffsetFromCursor(Operator): ob.users_group[group].dupli_offset = scene.cursor_location return {'FINISHED'} + + +class LodByName(Operator): + """Add levels of detail to this object based on object names""" + bl_idname = "object.lod_by_name" + bl_label = "Setup Levels of Detail By Name" + bl_options = {'REGISTER', 'UNDO'} + + @classmethod + def poll(cls, context): + return (context.active_object is not None) + + def execute(self, context): + scene = context.scene + ob = context.active_object + + prefix = "" + suffix = "" + name = "" + if ob.name.lower().startswith("lod0"): + prefix = ob.name[:4] + name = ob.name[4:] + elif ob.name.lower().endswith("lod0"): + name = ob.name[:-4] + suffix = ob.name[-4:] + else: + return {'CANCELLED'} + + level = 0 + while True: + level += 1 + + if prefix: + prefix = prefix[:3] + str(level) + if suffix: + suffix = suffix[:3] + str(level) + + lod = None + try: + lod = bpy.data.objects[prefix + name + suffix] + except KeyError: + break + + try: + ob.lod_levels[level] + except IndexError: + bpy.ops.object.lod_add() + + ob.lod_levels[level].object = lod + + return {'FINISHED'} + + +class LodClearAll(Operator): + """Remove all levels of detail from this object""" + bl_idname = "object.lod_clear_all" + bl_label = "Clear All Levels of Detail" + bl_options = {'REGISTER', 'UNDO'} + + @classmethod + def poll(cls, context): + return (context.active_object is not None) + + def execute(self, context): + scene = context.scene + ob = context.active_object + + if ob.lod_levels: + while 'CANCELLED' not in bpy.ops.object.lod_remove(): + pass + + return {'FINISHED'} + + +class LodGenerate(Operator): + """Generates levels of detail using the decimate modifier""" + bl_idname = "object.lod_generate" + bl_label = "Generate Levels of Detail" + bl_options = {'REGISTER', 'UNDO'} + + count = bpy.props.IntProperty(name="Count", default=3) + target = bpy.props.FloatProperty(name="Target Size", default=0.1, + min=0.0, max=1.0) + package = bpy.props.BoolProperty(name="Package into Group", default=False) + + @classmethod + def poll(cls, context): + return (context.active_object is not None) + + def execute(self, context): + scene = bpy.context.scene + ob = scene.objects.active + + lod_name = ob.name + lod_suffix = "lod" + lod_prefix = "" + if lod_name.lower().endswith("lod0"): + lod_suffix = lod_name[-3:-1] + lod_name = lod_name[:-3] + elif lod_name.lower().startswith("lod0"): + lod_suffix = "" + lod_prefix = lod_name[:3] + lod_name = lod_name[4:] + + group_name = lod_name.strip(' ._') + if self.package: + try: + bpy.ops.object.group_link(group=group_name) + except TypeError: + bpy.ops.group.create(name=group_name) + + step = (1.0 - self.target) / (self.count - 1) + for i in range(1, self.count): + scene.objects.active = ob + bpy.ops.object.duplicate() + lod = bpy.context.selected_objects[0] + + scene.objects.active = ob + bpy.ops.object.lod_add() + scene.objects.active = lod + + if lod_prefix: + lod.name = lod_prefix + str(i) + lod_name + else: + lod.name = lod_name + lod_suffix + str(i) + + lod.location.y = ob.location.y + 3.0 * i + + if i == 1: + modifier = lod.modifiers.new("lod_decimate", "DECIMATE") + else: + modifier = lod.modifiers[-1] + + modifier.ratio = 1.0 - step*(i) + + ob.lod_levels[i].object = lod + + if self.package: + bpy.ops.object.group_link(group=group_name) + lod.parent = ob + + if self.package: + for level in ob.lod_levels[1:]: + level.object.hide = level.object.hide_render = True + + lod.select = False + ob.select = True + scene.objects.active = ob + + return {'FINISHED'} + diff --git a/release/scripts/startup/bl_ui/properties_object.py b/release/scripts/startup/bl_ui/properties_object.py index cbebdafbf2e..dcd32b17cbd 100644 --- a/release/scripts/startup/bl_ui/properties_object.py +++ b/release/scripts/startup/bl_ui/properties_object.py @@ -18,7 +18,7 @@ # <pep8 compliant> import bpy -from bpy.types import Panel +from bpy.types import Menu, Panel from rna_prop_ui import PropertyPanel @@ -125,6 +125,49 @@ class OBJECT_PT_transform_locks(ObjectButtonsPanel, Panel): sub.prop(ob, "lock_rotation_w", text="W") +class OBJECT_MT_lod_tools(Menu): + bl_label = "Level Of Detail Tools" + + def draw(self, context): + layout = self.layout + + layout.operator("object.lod_by_name", text="Set By Name") + layout.operator("object.lod_generate", text="Generate") + layout.operator("object.lod_clear_all", text="Clear All", icon='PANEL_CLOSE') + + +class OBJECT_PT_levels_of_detail(ObjectButtonsPanel, Panel): + bl_label = "Levels of Detail" + COMPAT_ENGINES = {'BLENDER_GAME'} + + @classmethod + def poll(cls, context): + return context.scene.render.engine in cls.COMPAT_ENGINES + + def draw(self, context): + layout = self.layout + ob = context.object + + col = layout.column() + + for i, level in enumerate(ob.lod_levels): + if i == 0: continue + box = col.box() + row = box.row() + row.prop(level, "object", text="") + row.operator("object.lod_remove", text="", icon='PANEL_CLOSE').index = i + + row = box.row() + row.prop(level, "distance") + row = row.row(align=True) + row.prop(level, "use_mesh", text="") + row.prop(level, "use_material", text="") + + row = col.row(align=True) + row.operator("object.lod_add", text="Add", icon='ZOOMIN') + row.menu("OBJECT_MT_lod_tools", text="", icon='TRIA_DOWN') + + class OBJECT_PT_relations(ObjectButtonsPanel, Panel): bl_label = "Relations" |