From c620b3b66604ecd84c0447b9093217685cbfbfd9 Mon Sep 17 00:00:00 2001 From: Joseph Davies Date: Mon, 7 Aug 2017 19:43:14 -0700 Subject: [PATCH 1/6] Add plAvLadderMod. Adds modifier panel and export for Uru-style ladders. --- korman/properties/modifiers/avatar.py | 62 +++++++++++++++++++++++++++ korman/ui/modifiers/avatar.py | 9 ++++ 2 files changed, 71 insertions(+) diff --git a/korman/properties/modifiers/avatar.py b/korman/properties/modifiers/avatar.py index 81c0457..1803393 100644 --- a/korman/properties/modifiers/avatar.py +++ b/korman/properties/modifiers/avatar.py @@ -15,6 +15,7 @@ import bpy from bpy.props import * +import mathutils from PyHSPlasma import * from .base import PlasmaModifierProperties, PlasmaModifierLogicWiz @@ -22,6 +23,67 @@ from ...exporter.explosions import ExportError from ...helpers import find_modifier from ... import idprops + +class PlasmaLadderModifier(PlasmaModifierProperties): + pl_id = "laddermod" + + bl_category = "Avatar" + bl_label = "Ladder" + bl_description = "Climbable Ladder" + bl_icon = "COLLAPSEMENU" + + is_enabled = BoolProperty(name="Enabled", + description="Ladder enabled by default at Age start", + default=True) + direction = EnumProperty(name="Direction", + description="Direction of climb", + items=[("UP", "Up", "The avatar will mount the ladder and climb upward"), + ("DOWN", "Down", "The avatar will mount the ladder and climb downward"),], + default="DOWN") + num_loops = IntProperty(name="Loops", + description="How many full animation loops after the first to play before dismounting", + min=0, default=4) + facing_object = PointerProperty(name="Facing Object", + description="Target object the avatar must be facing through this region to trigger climb (optional)", + type=bpy.types.Object, + poll=idprops.poll_mesh_objects) + + def export(self, exporter, bo, so): + # Create the ladder modifier + mod = exporter.mgr.find_create_object(plAvLadderMod, so=so, name=self.key_name) + mod.type = plAvLadderMod.kBig + mod.loops = self.num_loops + mod.enabled = self.is_enabled + mod.goingUp = self.direction == "UP" + + # Create vector pointing from the Facing Object to the Detector. + # Animation only activates if the avatar is facing it within + # engine-defined (45 degree) tolerance + if self.facing_object is not None: + # Use object if one has been selected + ladderVec = self.facing_object.matrix_world.translation - bo.matrix_world.translation + else: + # Make our own artificial target -1.0 units back on the local Y axis. + world = bo.matrix_world.copy() + world.invert() + target = bo.location - (mathutils.Vector((0.0, 1.0, 0.0)) * world) + ladderVec = target - bo.matrix_local.translation + mod.ladderView = hsVector3(ladderVec.x, ladderVec.y, 0.0) + mod.ladderView.normalize() + + # Generate the detector's physical bounds + det_name = "{}_LadderDetector".format(self.id_data.name) + bounds = bo.plasma_modifiers.collision.bounds + simIface, physical = exporter.physics.generate_physical(bo, so, bounds, det_name) + physical.memberGroup = plSimDefs.kGroupDetector + physical.reportGroup |= 1 << plSimDefs.kGroupAvatar + physical.boundsType = plSimDefs.kHullBounds + + @property + def requires_actor(self): + return True + + sitting_approach_flags = [("kApproachFront", "Front", "Approach from the font"), ("kApproachLeft", "Left", "Approach from the left"), ("kApproachRight", "Right", "Approach from the right"), diff --git a/korman/ui/modifiers/avatar.py b/korman/ui/modifiers/avatar.py index 31cc508..11db188 100644 --- a/korman/ui/modifiers/avatar.py +++ b/korman/ui/modifiers/avatar.py @@ -17,6 +17,15 @@ import bpy from ...helpers import find_modifier +def laddermod(modifier, layout, context): + layout.label(text="Avatar climbs facing negative Y.") + + layout.prop(modifier, "is_enabled") + layout.prop(modifier, "num_loops") + layout.prop(modifier, "direction") + + layout.prop(modifier, "facing_object", icon="MESH_DATA") + def sittingmod(modifier, layout, context): layout.row().prop(modifier, "approach") From 64171882858b26035d35e6b8b9d1b362e26c3275 Mon Sep 17 00:00:00 2001 From: Joseph Davies Date: Wed, 16 Aug 2017 02:54:02 -0700 Subject: [PATCH 2/6] Create Plasma 'Add' menu and premade ladder. --- korman/__init__.py | 2 + korman/operators/__init__.py | 1 + korman/operators/op_mesh.py | 366 +++++++++++++++++++++++++++++++++++ korman/ui/__init__.py | 8 + korman/ui/ui_menus.py | 45 +++++ 5 files changed, 422 insertions(+) create mode 100644 korman/operators/op_mesh.py create mode 100644 korman/ui/ui_menus.py diff --git a/korman/__init__.py b/korman/__init__.py index 093df40..f7b0df8 100644 --- a/korman/__init__.py +++ b/korman/__init__.py @@ -41,6 +41,7 @@ def register(): nodes.register() operators.register() properties.register() + ui.register() def unregister(): @@ -48,6 +49,7 @@ def unregister(): bpy.utils.unregister_module(__name__) nodes.unregister() operators.unregister() + ui.unregister() if __name__ == "__main__": diff --git a/korman/operators/__init__.py b/korman/operators/__init__.py index ef4e5c4..94b352f 100644 --- a/korman/operators/__init__.py +++ b/korman/operators/__init__.py @@ -15,6 +15,7 @@ from . import op_export as exporter from . import op_lightmap as lightmap +from . import op_mesh as mesh from . import op_modifier as modifier from . import op_nodes as nodes from . import op_sound as sound diff --git a/korman/operators/op_mesh.py b/korman/operators/op_mesh.py new file mode 100644 index 0000000..408f3ba --- /dev/null +++ b/korman/operators/op_mesh.py @@ -0,0 +1,366 @@ +# This file is part of Korman. +# +# Korman 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 3 of the License, or +# (at your option) any later version. +# +# Korman 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 Korman. If not, see . + +import bpy +import bmesh +import math +import mathutils + +class PlasmaMeshOperator: + @classmethod + def poll(cls, context): + return context.scene.render.engine == "PLASMA_GAME" + + +class PlasmaAddLadderMeshOperator(PlasmaMeshOperator, bpy.types.Operator): + bl_idname = "mesh.plasma_ladder_add" + bl_label = "Ladder" + bl_category = "Plasma" + bl_description = "Adds a new Plasma Ladder" + bl_options = {"REGISTER", "UNDO"} + + # Basic stats + ladder_height = bpy.props.FloatProperty(name="Height", + description="Height of ladder in feet", + min=6, max=1000, step=200, precision=0, default=6, + unit="LENGTH", subtype="DISTANCE") + ladder_width = bpy.props.FloatProperty(name="Width", + description="Width of ladder in inches", + min=30, max=42, step=100, precision=0, default=30) + rung_height = bpy.props.FloatProperty(name="Rung height", + description="Height of rungs in inches", + min=1, max=6, step=100, precision=0, default=6) + # Template generation + gen_back_guide = bpy.props.BoolProperty(name="Ladder", + description="Generates helper object where ladder back should be placed", + default=True) + gen_ground_guides = bpy.props.BoolProperty(name="Ground", + description="Generates helper objects where ground should be placed", + default=True) + gen_rung_guides = bpy.props.BoolProperty(name="Rungs", + description="Generates helper objects where rungs should be placed", + default=True) + rung_width_type = bpy.props.EnumProperty(name="Rung Width", + description="Type of rungs to generate", + items=[("FULL", "Full Width Rungs", "The rungs cross the entire width of the ladder"), + ("HALF", "Half Width Rungs", "The rungs only cross half the ladder's width, on the side where the avatar will contact them"),], + default="FULL") + # Game options + has_upper_entry = bpy.props.BoolProperty(name="Has Upper Entry Point", + description="Specifies whether the ladder has an upper entry", + default=True) + upper_entry_enabled = bpy.props.BoolProperty(name="Upper Entry Enabled", + description="Specifies whether the ladder's upper entry is enabled by default at Age start", + default=True) + has_lower_entry = bpy.props.BoolProperty(name="Has Lower Entry Point", + description="Specifies whether the ladder has a lower entry", + default=True) + lower_entry_enabled = bpy.props.BoolProperty(name="Lower Entry Enabled", + description="Specifies whether the ladder's lower entry is enabled by default at Age start", + default=True) + + def draw(self, context): + layout = self.layout + space = bpy.context.space_data + if (not space.local_view): + box = layout.box() + box.label("Geometry:") + + row = box.row() + row.alert = self.ladder_height % 2 != 0 + row.prop(self, "ladder_height") + row = box.row() + row.prop(self, "ladder_width") + row = box.row() + row.prop(self, "rung_height") + + box = layout.box() + box.label("Template Guides:") + col = box.column() + col.prop(self, "gen_back_guide") + col.prop(self, "gen_ground_guides") + col.prop(self, "gen_rung_guides") + if self.gen_rung_guides: + col.separator() + col.prop(self, "rung_width_type", text="") + + box = layout.box() + row = box.row() + col = row.column() + col.label("Upper Entry:") + col.row().prop(self, "has_upper_entry", text="Create") + row = col.row() + row.enabled = self.has_upper_entry + row.prop(self, "upper_entry_enabled", text="Enabled") + col.separator() + col.label("Lower Entry:") + col.row().prop(self, "has_lower_entry", text="Create") + row = col.row() + row.enabled = self.has_lower_entry + row.prop(self, "lower_entry_enabled", text="Enabled") + + else: + row = layout.row() + row.label("Warning: Operator does not work in local view mode", icon="ERROR") + + def execute(self, context): + if bpy.context.mode == "OBJECT": + self.create_ladder_objects() + return {"FINISHED"} + else: + self.report({"WARNING"}, "Ladder creation only valid in Object mode") + return {"CANCELLED"} + + + def create_guide_rungs(self): + bpyscene = bpy.context.scene + cursor_shift = mathutils.Matrix.Translation(bpy.context.scene.cursor_location) + + rung_height_ft = self.rung_height / 12 + rung_width_ft = self.ladder_width / 12 + + if self.rung_width_type == "FULL": + rung_width = rung_width_ft + rung_yoffset = 0.0 + else: + rung_width = rung_width_ft / 2 + rung_yoffset = rung_width_ft / 4 + + rungs_scale = mathutils.Matrix( + ((0.5, 0.0, 0.0), + (0.0, rung_width, 0.0), + (0.0, 0.0, rung_height_ft))) + + for rung_num in range(0, int(self.ladder_height)): + side = "L" if (rung_num % 2) == 0 else "R" + + mesh = bpy.data.meshes.new("LadderRung_{}_{}".format(side, rung_num)) + rungs = bpy.data.objects.new("LadderRung_{}_{}".format(side, rung_num), mesh) + rungs.hide_render = True + rungs.draw_type = "BOUNDS" + + bpyscene.objects.link(rungs) + bpyscene.objects.active = rungs + rungs.select = True + + bm = bmesh.new() + bmesh.ops.create_cube(bm, size=(1.0), matrix=rungs_scale) + + # Move each rung up, based on: + # its place in the array, aligned to the top of the rung position, shifted up to start at the ladder's base + if (rung_num % 2) == 0: + rung_pos = mathutils.Matrix.Translation((0.5, -rung_yoffset, rung_num + (1.0 - rung_height_ft) + (rung_height_ft / 2))) + else: + rung_pos = mathutils.Matrix.Translation((0.5, rung_yoffset, rung_num + (1.0 - rung_height_ft) + (rung_height_ft / 2))) + bmesh.ops.transform(bm, matrix=cursor_shift, space=rungs.matrix_world, verts=bm.verts) + bmesh.ops.transform(bm, matrix=rung_pos, space=rungs.matrix_world, verts=bm.verts) + bm.to_mesh(mesh) + bm.free() + + def create_guide_back(self): + bpyscene = bpy.context.scene + cursor_shift = mathutils.Matrix.Translation(bpy.context.scene.cursor_location) + + # Create an empty mesh and the object. + mesh = bpy.data.meshes.new("LadderBack") + back = bpy.data.objects.new("LadderBack", mesh) + back.hide_render = True + back.draw_type = "BOUNDS" + + # Add the object into the scene. + bpyscene.objects.link(back) + bpyscene.objects.active = back + back.select = True + + # Construct the bmesh and assign it to the blender mesh. + bm = bmesh.new() + ladder_scale = mathutils.Matrix( + ((0.5, 0.0, 0.0), + (0.0, self.ladder_width / 12, 0.0), + (0.0, 0.0, self.ladder_height))) + bmesh.ops.create_cube(bm, size=(1.0), matrix=ladder_scale) + + # Shift the ladder up so that its base is at the 3D cursor + back_pos = mathutils.Matrix.Translation((0.0, 0.0, self.ladder_height / 2)) + bmesh.ops.transform(bm, matrix=cursor_shift, space=back.matrix_world, verts=bm.verts) + bmesh.ops.transform(bm, matrix=back_pos, space=back.matrix_world, verts=bm.verts) + bm.to_mesh(mesh) + bm.free() + + def create_guide_ground(self): + bpyscene = bpy.context.scene + cursor_shift = mathutils.Matrix.Translation(bpy.context.scene.cursor_location) + + for pos in ("Upper", "Lower"): + # Create an empty mesh and the object. + mesh = bpy.data.meshes.new("LadderGround_{}".format(pos)) + ground = bpy.data.objects.new("LadderGround_{}".format(pos), mesh) + ground.hide_render = True + ground.draw_type = "BOUNDS" + + # Add the object into the scene. + bpyscene.objects.link(ground) + bpyscene.objects.active = ground + ground.select = True + + # Construct the bmesh and assign it to the blender mesh. + bm = bmesh.new() + ground_depth = 3.0 + ground_scale = mathutils.Matrix( + ((ground_depth, 0.0, 0.0), + (0.0, self.ladder_width / 12, 0.0), + (0.0, 0.0, 0.5))) + bmesh.ops.create_cube(bm, size=(1.0), matrix=ground_scale) + + if pos == "Upper": + ground_pos = mathutils.Matrix.Translation((-(ground_depth / 2) + 0.25, 0.0, self.ladder_height + 0.25)) + else: + ground_pos = mathutils.Matrix.Translation(((ground_depth / 2) + 0.25, 0.0, 0.25)) + bmesh.ops.transform(bm, matrix=cursor_shift, space=ground.matrix_world, verts=bm.verts) + bmesh.ops.transform(bm, matrix=ground_pos, space=ground.matrix_world, verts=bm.verts) + bm.to_mesh(mesh) + bm.free() + + def create_upper_entry(self): + bpyscene = bpy.context.scene + cursor_shift = mathutils.Matrix.Translation(bpy.context.scene.cursor_location) + + # Create an empty mesh and the object. + mesh = bpy.data.meshes.new("LadderEntry_Upper") + upper_rgn = bpy.data.objects.new("LadderEntry_Upper", mesh) + upper_rgn.hide_render = True + upper_rgn.draw_type = "WIRE" + + # Add the object into the scene. + bpyscene.objects.link(upper_rgn) + bpyscene.objects.active = upper_rgn + upper_rgn.select = True + upper_rgn.plasma_object.enabled = True + + # Construct the bmesh and assign it to the blender mesh. + bm = bmesh.new() + rgn_scale = mathutils.Matrix( + ((self.ladder_width / 12, 0.0, 0.0), + (0.0, 2.5, 0.0), + (0.0, 0.0, 2.0))) + bmesh.ops.create_cube(bm, size=(1.0), matrix=rgn_scale) + + rgn_pos = mathutils.Matrix.Translation((-1.80, 0.0, 1.5 + self.ladder_height)) + bmesh.ops.transform(bm, matrix=cursor_shift, space=upper_rgn.matrix_world, verts=bm.verts) + bmesh.ops.transform(bm, matrix=rgn_pos, space=upper_rgn.matrix_world, verts=bm.verts) + + bm.to_mesh(mesh) + bm.free() + + origin_to_bottom(upper_rgn) + upper_rgn.rotation_euler[2] = math.radians(90.0) + + bpy.ops.object.plasma_modifier_add(types="laddermod") + laddermod = upper_rgn.plasma_modifiers.laddermod + laddermod.is_enabled = self.lower_entry_enabled + laddermod.num_loops = (self.ladder_height - 6) / 2 + laddermod.direction = "DOWN" + + def create_lower_entry(self): + bpyscene = bpy.context.scene + cursor_shift = mathutils.Matrix.Translation(bpy.context.scene.cursor_location) + + # Create an empty mesh and the object. + mesh = bpy.data.meshes.new("LadderEntry_Lower") + lower_rgn = bpy.data.objects.new("LadderEntry_Lower", mesh) + lower_rgn.hide_render = True + lower_rgn.draw_type = "WIRE" + + # Add the object into the scene. + bpyscene.objects.link(lower_rgn) + bpyscene.objects.active = lower_rgn + lower_rgn.select = True + lower_rgn.plasma_object.enabled = True + + # Construct the bmesh and assign it to the blender mesh. + bm = bmesh.new() + rgn_scale = mathutils.Matrix( + ((self.ladder_width / 12, 0.0, 0.0), + (0.0, 2.5, 0.0), + (0.0, 0.0, 2.0))) + bmesh.ops.create_cube(bm, size=(1.0), matrix=rgn_scale) + + rgn_pos = mathutils.Matrix.Translation((2.70, 0.0, 1.5)) + bmesh.ops.transform(bm, matrix=cursor_shift, space=lower_rgn.matrix_world, verts=bm.verts) + bmesh.ops.transform(bm, matrix=rgn_pos, space=lower_rgn.matrix_world, verts=bm.verts) + + bm.to_mesh(mesh) + bm.free() + + origin_to_bottom(lower_rgn) + lower_rgn.rotation_euler[2] = math.radians(-90.0) + + bpy.ops.object.plasma_modifier_add(types="laddermod") + laddermod = lower_rgn.plasma_modifiers.laddermod + laddermod.is_enabled = self.lower_entry_enabled + laddermod.num_loops = (self.ladder_height - 6) / 2 + laddermod.direction = "UP" + + def create_ladder_objects(self): + for obj in bpy.data.objects: + obj.select = False + + if self.gen_rung_guides: + self.create_guide_rungs() + if self.gen_back_guide: + self.create_guide_back() + if self.gen_ground_guides: + self.create_guide_ground() + + bpy.ops.object.origin_set(type="ORIGIN_CENTER_OF_MASS") + + if self.has_upper_entry: + self.create_upper_entry() + if self.has_lower_entry: + self.create_lower_entry() + + bpy.ops.group.create(name="LadderGroup") + bpy.ops.group.objects_add_active() + + +def origin_to_bottom(obj): + # Modified from https://blender.stackexchange.com/a/42110/3055 + mw = obj.matrix_world + local_verts = [mathutils.Vector(v[:]) for v in obj.bound_box] + x, y, z = 0, 0, 0 + + l = len(local_verts) + y = sum((v.y for v in local_verts)) / l + x = sum((v.x for v in local_verts)) / l + z = min((v.z for v in local_verts)) + + local_origin = mathutils.Vector((x, y, z)) + global_origin = mw * local_origin + + bm = bmesh.new() + bm.from_mesh(obj.data) + + for v in bm.verts: + v.co = v.co - local_origin + + bm.to_mesh(obj.data) + mw.translation = global_origin + + +def register(): + bpy.utils.register_module(__name__) + +def unregister(): + bpy.utils.unregister_module(__name__) diff --git a/korman/ui/__init__.py b/korman/ui/__init__.py index 3a865c4..c334f8a 100644 --- a/korman/ui/__init__.py +++ b/korman/ui/__init__.py @@ -14,8 +14,16 @@ # along with Korman. If not, see . from .ui_lamp import * +from .ui_menus import * from .ui_modifiers import * from .ui_object import * from .ui_texture import * from .ui_toolbox import * from .ui_world import * + + +def register(): + ui_menus.register() + +def unregister(): + ui_menus.unregister() diff --git a/korman/ui/ui_menus.py b/korman/ui/ui_menus.py new file mode 100644 index 0000000..1f51912 --- /dev/null +++ b/korman/ui/ui_menus.py @@ -0,0 +1,45 @@ +# This file is part of Korman. +# +# Korman 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 3 of the License, or +# (at your option) any later version. +# +# Korman 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 Korman. If not, see . + +from ..operators.op_mesh import * + +class PlasmaMenu: + @classmethod + def poll(cls, context): + return context.scene.render.engine == "PLASMA_GAME" + + +class PlasmaAddMenu(PlasmaMenu, bpy.types.Menu): + bl_idname = "menu.plasma_add" + bl_label = "Plasma" + bl_description = "Add a Plasma premade" + + def draw(self, context): + layout = self.layout + + layout.operator("mesh.plasma_ladder_add", text="Ladder", icon="COLLAPSEMENU") + + +def build_plasma_menu(self, context): + if context.scene.render.engine != "PLASMA_GAME": + return + self.layout.separator() + self.layout.menu("menu.plasma_add", icon="URL") + +def register(): + bpy.types.INFO_MT_add.append(build_plasma_menu) + +def unregister(): + bpy.types.INFO_MT_add.remove(build_plasma_menu) From f3b2cd59e73905cfb2293dd93251fafe741e04e8 Mon Sep 17 00:00:00 2001 From: Joseph Davies Date: Sun, 29 Oct 2017 11:04:25 -0700 Subject: [PATCH 3/6] Use existing collision bounds type for ladder region if one is set. --- korman/properties/modifiers/avatar.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/korman/properties/modifiers/avatar.py b/korman/properties/modifiers/avatar.py index 1803393..e854ebf 100644 --- a/korman/properties/modifiers/avatar.py +++ b/korman/properties/modifiers/avatar.py @@ -73,11 +73,10 @@ class PlasmaLadderModifier(PlasmaModifierProperties): # Generate the detector's physical bounds det_name = "{}_LadderDetector".format(self.id_data.name) - bounds = bo.plasma_modifiers.collision.bounds + bounds = "hull" if not bo.plasma_modifiers.collision.enabled else bo.plasma_modifiers.collision.bounds simIface, physical = exporter.physics.generate_physical(bo, so, bounds, det_name) physical.memberGroup = plSimDefs.kGroupDetector physical.reportGroup |= 1 << plSimDefs.kGroupAvatar - physical.boundsType = plSimDefs.kHullBounds @property def requires_actor(self): From b3474effc63f97b851c4c9bd3f50043ab8b5be24 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Wed, 20 Dec 2017 20:28:37 -0500 Subject: [PATCH 4/6] Allow custom names for ladder stems --- korman/operators/op_mesh.py | 47 +++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/korman/operators/op_mesh.py b/korman/operators/op_mesh.py index 408f3ba..51534e3 100644 --- a/korman/operators/op_mesh.py +++ b/korman/operators/op_mesh.py @@ -31,6 +31,11 @@ class PlasmaAddLadderMeshOperator(PlasmaMeshOperator, bpy.types.Operator): bl_description = "Adds a new Plasma Ladder" bl_options = {"REGISTER", "UNDO"} + # Allows user to specify their own name stem + ladder_name = bpy.props.StringProperty(name="Name", + description="Ladder name stem", + default="Ladder") + # Basic stats ladder_height = bpy.props.FloatProperty(name="Height", description="Height of ladder in feet", @@ -74,10 +79,16 @@ class PlasmaAddLadderMeshOperator(PlasmaMeshOperator, bpy.types.Operator): def draw(self, context): layout = self.layout space = bpy.context.space_data - if (not space.local_view): + + if not space.local_view: box = layout.box() - box.label("Geometry:") + box.label("Ladder Name:") + row = box.row() + row.alert = not self.ladder_name + row.prop(self, "ladder_name", text="") + box = layout.box() + box.label("Geometry:") row = box.row() row.alert = self.ladder_height % 2 != 0 row.prop(self, "ladder_height") @@ -116,13 +127,12 @@ class PlasmaAddLadderMeshOperator(PlasmaMeshOperator, bpy.types.Operator): row.label("Warning: Operator does not work in local view mode", icon="ERROR") def execute(self, context): - if bpy.context.mode == "OBJECT": + if context.mode == "OBJECT": self.create_ladder_objects() - return {"FINISHED"} else: self.report({"WARNING"}, "Ladder creation only valid in Object mode") return {"CANCELLED"} - + return {"FINISHED"} def create_guide_rungs(self): bpyscene = bpy.context.scene @@ -146,8 +156,8 @@ class PlasmaAddLadderMeshOperator(PlasmaMeshOperator, bpy.types.Operator): for rung_num in range(0, int(self.ladder_height)): side = "L" if (rung_num % 2) == 0 else "R" - mesh = bpy.data.meshes.new("LadderRung_{}_{}".format(side, rung_num)) - rungs = bpy.data.objects.new("LadderRung_{}_{}".format(side, rung_num), mesh) + mesh = bpy.data.meshes.new("{}_Rung_{}_{}".format(self.name_stem, side, rung_num)) + rungs = bpy.data.objects.new("{}_Rung_{}_{}".format(self.name_stem, side, rung_num), mesh) rungs.hide_render = True rungs.draw_type = "BOUNDS" @@ -174,8 +184,9 @@ class PlasmaAddLadderMeshOperator(PlasmaMeshOperator, bpy.types.Operator): cursor_shift = mathutils.Matrix.Translation(bpy.context.scene.cursor_location) # Create an empty mesh and the object. - mesh = bpy.data.meshes.new("LadderBack") - back = bpy.data.objects.new("LadderBack", mesh) + name = "{}_Back".format(self.name_stem) + mesh = bpy.data.meshes.new(name) + back = bpy.data.objects.new(name, mesh) back.hide_render = True back.draw_type = "BOUNDS" @@ -205,8 +216,9 @@ class PlasmaAddLadderMeshOperator(PlasmaMeshOperator, bpy.types.Operator): for pos in ("Upper", "Lower"): # Create an empty mesh and the object. - mesh = bpy.data.meshes.new("LadderGround_{}".format(pos)) - ground = bpy.data.objects.new("LadderGround_{}".format(pos), mesh) + name = "{}_Ground_{}".format(self.name_stem, pos) + mesh = bpy.data.meshes.new(name) + ground = bpy.data.objects.new(name, mesh) ground.hide_render = True ground.draw_type = "BOUNDS" @@ -238,8 +250,9 @@ class PlasmaAddLadderMeshOperator(PlasmaMeshOperator, bpy.types.Operator): cursor_shift = mathutils.Matrix.Translation(bpy.context.scene.cursor_location) # Create an empty mesh and the object. - mesh = bpy.data.meshes.new("LadderEntry_Upper") - upper_rgn = bpy.data.objects.new("LadderEntry_Upper", mesh) + name = "{}_Entry_Upper".format(self.name_stem) + mesh = bpy.data.meshes.new(name) + upper_rgn = bpy.data.objects.new(name, mesh) upper_rgn.hide_render = True upper_rgn.draw_type = "WIRE" @@ -278,8 +291,9 @@ class PlasmaAddLadderMeshOperator(PlasmaMeshOperator, bpy.types.Operator): cursor_shift = mathutils.Matrix.Translation(bpy.context.scene.cursor_location) # Create an empty mesh and the object. - mesh = bpy.data.meshes.new("LadderEntry_Lower") - lower_rgn = bpy.data.objects.new("LadderEntry_Lower", mesh) + name = "{}_Entry_Lower".format(self.name_stem) + mesh = bpy.data.meshes.new(name) + lower_rgn = bpy.data.objects.new(name, mesh) lower_rgn.hide_render = True lower_rgn.draw_type = "WIRE" @@ -334,6 +348,9 @@ class PlasmaAddLadderMeshOperator(PlasmaMeshOperator, bpy.types.Operator): bpy.ops.group.create(name="LadderGroup") bpy.ops.group.objects_add_active() + @property + def name_stem(self): + return self.ladder_name if self.ladder_name else "Ladder" def origin_to_bottom(obj): # Modified from https://blender.stackexchange.com/a/42110/3055 From 91f38b519bca1dbdf334c117565244e46132dddb Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Wed, 20 Dec 2017 20:50:49 -0500 Subject: [PATCH 5/6] Thou shalt not animate mine operator... --- korman/operators/op_mesh.py | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/korman/operators/op_mesh.py b/korman/operators/op_mesh.py index 51534e3..6ab93d0 100644 --- a/korman/operators/op_mesh.py +++ b/korman/operators/op_mesh.py @@ -34,47 +34,58 @@ class PlasmaAddLadderMeshOperator(PlasmaMeshOperator, bpy.types.Operator): # Allows user to specify their own name stem ladder_name = bpy.props.StringProperty(name="Name", description="Ladder name stem", - default="Ladder") - + default="Ladder", + options=set()) # Basic stats ladder_height = bpy.props.FloatProperty(name="Height", description="Height of ladder in feet", min=6, max=1000, step=200, precision=0, default=6, - unit="LENGTH", subtype="DISTANCE") + unit="LENGTH", subtype="DISTANCE", + options=set()) ladder_width = bpy.props.FloatProperty(name="Width", description="Width of ladder in inches", - min=30, max=42, step=100, precision=0, default=30) + min=30, max=42, step=100, precision=0, default=30, + options=set()) rung_height = bpy.props.FloatProperty(name="Rung height", description="Height of rungs in inches", - min=1, max=6, step=100, precision=0, default=6) + min=1, max=6, step=100, precision=0, default=6, + options=set()) # Template generation gen_back_guide = bpy.props.BoolProperty(name="Ladder", description="Generates helper object where ladder back should be placed", - default=True) + default=True, + options=set()) gen_ground_guides = bpy.props.BoolProperty(name="Ground", description="Generates helper objects where ground should be placed", - default=True) + default=True, + options=set()) gen_rung_guides = bpy.props.BoolProperty(name="Rungs", description="Generates helper objects where rungs should be placed", - default=True) + default=True, + options=set()) rung_width_type = bpy.props.EnumProperty(name="Rung Width", description="Type of rungs to generate", items=[("FULL", "Full Width Rungs", "The rungs cross the entire width of the ladder"), ("HALF", "Half Width Rungs", "The rungs only cross half the ladder's width, on the side where the avatar will contact them"),], - default="FULL") + default="FULL", + options=set()) # Game options has_upper_entry = bpy.props.BoolProperty(name="Has Upper Entry Point", description="Specifies whether the ladder has an upper entry", - default=True) + default=True, + options=set()) upper_entry_enabled = bpy.props.BoolProperty(name="Upper Entry Enabled", description="Specifies whether the ladder's upper entry is enabled by default at Age start", - default=True) + default=True, + options=set()) has_lower_entry = bpy.props.BoolProperty(name="Has Lower Entry Point", description="Specifies whether the ladder has a lower entry", - default=True) + default=True, + options=set()) lower_entry_enabled = bpy.props.BoolProperty(name="Lower Entry Enabled", description="Specifies whether the ladder's lower entry is enabled by default at Age start", - default=True) + default=True, + options=set()) def draw(self, context): layout = self.layout From bfee3eec829993ad54459eee3048abb51e2b6c16 Mon Sep 17 00:00:00 2001 From: Joseph Davies Date: Tue, 26 Dec 2017 19:39:37 -0800 Subject: [PATCH 6/6] Reword Add Ladder operator label for consistency. --- korman/operators/op_mesh.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/korman/operators/op_mesh.py b/korman/operators/op_mesh.py index 6ab93d0..378eed6 100644 --- a/korman/operators/op_mesh.py +++ b/korman/operators/op_mesh.py @@ -26,7 +26,7 @@ class PlasmaMeshOperator: class PlasmaAddLadderMeshOperator(PlasmaMeshOperator, bpy.types.Operator): bl_idname = "mesh.plasma_ladder_add" - bl_label = "Ladder" + bl_label = "Add Ladder" bl_category = "Plasma" bl_description = "Adds a new Plasma Ladder" bl_options = {"REGISTER", "UNDO"}