Browse Source

Create Plasma 'Add' menu and premade ladder.

pull/64/head
Joseph Davies 7 years ago
parent
commit
6417188285
Signed by untrusted user: Deledrius
GPG Key ID: 28ACC6E8D2B24B8A
  1. 2
      korman/__init__.py
  2. 1
      korman/operators/__init__.py
  3. 366
      korman/operators/op_mesh.py
  4. 8
      korman/ui/__init__.py
  5. 45
      korman/ui/ui_menus.py

2
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__":

1
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

366
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 <http://www.gnu.org/licenses/>.
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__)

8
korman/ui/__init__.py

@ -14,8 +14,16 @@
# along with Korman. If not, see <http://www.gnu.org/licenses/>.
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()

45
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 <http://www.gnu.org/licenses/>.
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)
Loading…
Cancel
Save