forked from bartvdbraak/blender
20a2100a36
This is used to force snap on and off when needed. Also, when transform is not run modal, it will use default values for PET and snap properties (False) instead of scene settings. No need to force them off when calling transform with Exec.
419 lines
13 KiB
Python
419 lines
13 KiB
Python
# ##### 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
#
|
|
# ##### END GPL LICENSE BLOCK #####
|
|
|
|
# <pep8-80 compliant>
|
|
|
|
import bpy
|
|
import os
|
|
|
|
from bpy.props import *
|
|
|
|
class MESH_OT_delete_edgeloop(bpy.types.Operator):
|
|
'''Export a single object as a stanford PLY with normals,
|
|
colours and texture coordinates.'''
|
|
bl_idname = "mesh.delete_edgeloop"
|
|
bl_label = "Delete Edge Loop"
|
|
|
|
def execute(self, context):
|
|
bpy.ops.tfm.edge_slide(value=1.0)
|
|
bpy.ops.mesh.select_more()
|
|
bpy.ops.mesh.remove_doubles()
|
|
|
|
return ('FINISHED',)
|
|
|
|
rna_path_prop = StringProperty(name="Context Attributes",
|
|
description="rna context string", maxlen=1024, default="")
|
|
|
|
rna_reverse_prop = BoolProperty(name="Reverse",
|
|
description="Cycle backwards", default=False)
|
|
|
|
class NullPathMember:
|
|
pass
|
|
|
|
|
|
def context_path_validate(context, path):
|
|
import sys
|
|
try:
|
|
value = eval("context.%s" % path)
|
|
except AttributeError:
|
|
if "'NoneType'" in str(sys.exc_info()[1]):
|
|
# One of the items in the rna path is None, just ignore this
|
|
value = NullPathMember
|
|
else:
|
|
# We have a real error in the rna path, dont ignore that
|
|
raise
|
|
|
|
return value
|
|
|
|
|
|
def execute_context_assign(self, context):
|
|
if context_path_validate(context, self.properties.path) == NullPathMember:
|
|
return ('PASS_THROUGH',)
|
|
exec("context.%s=self.properties.value" % self.properties.path)
|
|
return ('FINISHED',)
|
|
|
|
|
|
class WM_OT_context_set_boolean(bpy.types.Operator):
|
|
'''Set a context value.'''
|
|
bl_idname = "wm.context_set_boolean"
|
|
bl_label = "Context Set"
|
|
|
|
path = rna_path_prop
|
|
value = BoolProperty(name="Value",
|
|
description="Assignment value", default=True)
|
|
|
|
execute = execute_context_assign
|
|
|
|
|
|
class WM_OT_context_set_int(bpy.types.Operator): # same as enum
|
|
'''Set a context value.'''
|
|
bl_idname = "wm.context_set_int"
|
|
bl_label = "Context Set"
|
|
|
|
path = rna_path_prop
|
|
value = IntProperty(name="Value", description="Assign value", default=0)
|
|
|
|
execute = execute_context_assign
|
|
|
|
|
|
class WM_OT_context_set_float(bpy.types.Operator): # same as enum
|
|
'''Set a context value.'''
|
|
bl_idname = "wm.context_set_float"
|
|
bl_label = "Context Set"
|
|
|
|
path = rna_path_prop
|
|
value = FloatProperty(name="Value",
|
|
description="Assignment value", default=0.0)
|
|
|
|
execute = execute_context_assign
|
|
|
|
|
|
class WM_OT_context_set_string(bpy.types.Operator): # same as enum
|
|
'''Set a context value.'''
|
|
bl_idname = "wm.context_set_string"
|
|
bl_label = "Context Set"
|
|
|
|
path = rna_path_prop
|
|
value = StringProperty(name="Value",
|
|
description="Assign value", maxlen=1024, default="")
|
|
|
|
execute = execute_context_assign
|
|
|
|
|
|
class WM_OT_context_set_enum(bpy.types.Operator):
|
|
'''Set a context value.'''
|
|
bl_idname = "wm.context_set_enum"
|
|
bl_label = "Context Set"
|
|
|
|
path = rna_path_prop
|
|
value = StringProperty(name="Value",
|
|
description="Assignment value (as a string)",
|
|
maxlen=1024, default="")
|
|
|
|
execute = execute_context_assign
|
|
|
|
|
|
class WM_OT_context_toggle(bpy.types.Operator):
|
|
'''Toggle a context value.'''
|
|
bl_idname = "wm.context_toggle"
|
|
bl_label = "Context Toggle"
|
|
path = rna_path_prop
|
|
|
|
def execute(self, context):
|
|
|
|
if context_path_validate(context, self.properties.path) == NullPathMember:
|
|
return ('PASS_THROUGH',)
|
|
|
|
exec("context.%s=not (context.%s)" % (self.properties.path, self.properties.path))
|
|
return ('FINISHED',)
|
|
|
|
|
|
class WM_OT_context_toggle_enum(bpy.types.Operator):
|
|
'''Toggle a context value.'''
|
|
bl_idname = "wm.context_toggle_enum"
|
|
bl_label = "Context Toggle Values"
|
|
|
|
path = rna_path_prop
|
|
value_1 = StringProperty(name="Value", \
|
|
description="Toggle enum", maxlen=1024, default="")
|
|
|
|
value_2 = StringProperty(name="Value", \
|
|
description="Toggle enum", maxlen=1024, default="")
|
|
|
|
def execute(self, context):
|
|
|
|
if context_path_validate(context, self.properties.path) == NullPathMember:
|
|
return ('PASS_THROUGH',)
|
|
|
|
exec("context.%s = ['%s', '%s'][context.%s!='%s']" % \
|
|
(self.properties.path, self.properties.value_1, self.properties.value_2, self.properties.path, self.properties.value_2))
|
|
|
|
return ('FINISHED',)
|
|
|
|
|
|
class WM_OT_context_cycle_int(bpy.types.Operator):
|
|
'''Set a context value. Useful for cycling active material,
|
|
vertex keys, groups' etc.'''
|
|
bl_idname = "wm.context_cycle_int"
|
|
bl_label = "Context Int Cycle"
|
|
path = rna_path_prop
|
|
reverse = rna_reverse_prop
|
|
|
|
def execute(self, context):
|
|
|
|
value = context_path_validate(context, self.properties.path)
|
|
if value == NullPathMember:
|
|
return ('PASS_THROUGH',)
|
|
|
|
self.properties.value = value
|
|
if self.properties.reverse:
|
|
self.properties.value -= 1
|
|
else:
|
|
self.properties.value += 1
|
|
execute_context_assign(self, context)
|
|
|
|
if self.properties.value != eval("context.%s" % self.properties.path):
|
|
# relies on rna clamping int's out of the range
|
|
if self.properties.reverse:
|
|
self.properties.value = (1 << 32)
|
|
else:
|
|
self.properties.value = - (1 << 32)
|
|
execute_context_assign(self, context)
|
|
|
|
return ('FINISHED',)
|
|
|
|
|
|
class WM_OT_context_cycle_enum(bpy.types.Operator):
|
|
'''Toggle a context value.'''
|
|
bl_idname = "wm.context_cycle_enum"
|
|
bl_label = "Context Enum Cycle"
|
|
|
|
path = rna_path_prop
|
|
reverse = rna_reverse_prop
|
|
|
|
def execute(self, context):
|
|
|
|
value = context_path_validate(context, self.properties.path)
|
|
if value == NullPathMember:
|
|
return ('PASS_THROUGH',)
|
|
|
|
orig_value = value
|
|
|
|
# Have to get rna enum values
|
|
rna_struct_str, rna_prop_str = self.properties.path.rsplit('.', 1)
|
|
i = rna_prop_str.find('[')
|
|
|
|
# just incse we get "context.foo.bar[0]"
|
|
if i != -1:
|
|
rna_prop_str = rna_prop_str[0:i]
|
|
|
|
rna_struct = eval("context.%s.rna_type" % rna_struct_str)
|
|
|
|
rna_prop = rna_struct.properties[rna_prop_str]
|
|
|
|
if type(rna_prop) != bpy.types.EnumProperty:
|
|
raise Exception("expected an enum property")
|
|
|
|
enums = rna_struct.properties[rna_prop_str].items.keys()
|
|
orig_index = enums.index(orig_value)
|
|
|
|
# Have the info we need, advance to the next item
|
|
if self.properties.reverse:
|
|
if orig_index == 0:
|
|
advance_enum = enums[-1]
|
|
else:
|
|
advance_enum = enums[orig_index-1]
|
|
else:
|
|
if orig_index == len(enums) - 1:
|
|
advance_enum = enums[0]
|
|
else:
|
|
advance_enum = enums[orig_index + 1]
|
|
|
|
# set the new value
|
|
exec("context.%s=advance_enum" % self.properties.path)
|
|
return ('FINISHED',)
|
|
|
|
doc_id = StringProperty(name="Doc ID",
|
|
description="", maxlen=1024, default="", hidden=True)
|
|
|
|
doc_new = StringProperty(name="Edit Description",
|
|
description="", maxlen=1024, default="")
|
|
|
|
|
|
class WM_OT_doc_view(bpy.types.Operator):
|
|
'''Load online reference docs'''
|
|
bl_idname = "wm.doc_view"
|
|
bl_label = "View Documentation"
|
|
|
|
doc_id = doc_id
|
|
_prefix = 'http://www.blender.org/documentation/250PythonDoc'
|
|
|
|
def _nested_class_string(self, class_string):
|
|
ls = []
|
|
class_obj = getattr(bpy.types, class_string, None).bl_rna
|
|
while class_obj:
|
|
ls.insert(0, class_obj)
|
|
class_obj = class_obj.nested
|
|
return '.'.join([class_obj.identifier for class_obj in ls])
|
|
|
|
def execute(self, context):
|
|
id_split = self.properties.doc_id.split('.')
|
|
if len(id_split) == 1: # rna, class
|
|
url = '%s/bpy.types.%s-class.html' % (self._prefix, id_split[0])
|
|
elif len(id_split) == 2: # rna, class.prop
|
|
class_name, class_prop = id_split
|
|
|
|
if hasattr(bpy.types, class_name.upper() + '_OT_' + class_prop):
|
|
url = '%s/bpy.ops.%s-module.html#%s' % \
|
|
(self._prefix, class_name, class_prop)
|
|
else:
|
|
# It so happens that epydoc nests these
|
|
class_name_full = self._nested_class_string(class_name)
|
|
url = '%s/bpy.types.%s-class.html#%s' % \
|
|
(self._prefix, class_name_full, class_prop)
|
|
|
|
else:
|
|
return ('PASS_THROUGH',)
|
|
|
|
import webbrowser
|
|
webbrowser.open(url)
|
|
|
|
return ('FINISHED',)
|
|
|
|
|
|
class WM_OT_doc_edit(bpy.types.Operator):
|
|
'''Load online reference docs'''
|
|
bl_idname = "wm.doc_edit"
|
|
bl_label = "Edit Documentation"
|
|
|
|
doc_id = doc_id
|
|
doc_new = doc_new
|
|
|
|
_url = "http://www.mindrones.com/blender/svn/xmlrpc.php"
|
|
|
|
def _send_xmlrpc(self, data_dict):
|
|
print("sending data:", data_dict)
|
|
|
|
import xmlrpc.client
|
|
user = 'blenderuser'
|
|
pwd = 'blender>user'
|
|
|
|
docblog = xmlrpc.client.ServerProxy(self._url)
|
|
docblog.metaWeblog.newPost(1, user, pwd, data_dict, 1)
|
|
|
|
def execute(self, context):
|
|
|
|
class_name, class_prop = self.properties.doc_id.split('.')
|
|
|
|
if not self.properties.doc_new:
|
|
return ('RUNNING_MODAL',)
|
|
|
|
# check if this is an operator
|
|
op_name = class_name.upper() + '_OT_' + class_prop
|
|
op_class = getattr(bpy.types, op_name, None)
|
|
|
|
# Upload this to the web server
|
|
upload = {}
|
|
|
|
if op_class:
|
|
rna = op_class.bl_rna
|
|
doc_orig = rna.description
|
|
if doc_orig == self.properties.doc_new:
|
|
return ('RUNNING_MODAL',)
|
|
|
|
print("op - old:'%s' -> new:'%s'" % (doc_orig, self.properties.doc_new))
|
|
upload["title"] = 'OPERATOR %s:%s' % (self.properties.doc_id, doc_orig)
|
|
upload["description"] = self.properties.doc_new
|
|
|
|
self._send_xmlrpc(upload)
|
|
|
|
else:
|
|
rna = getattr(bpy.types, class_name).bl_rna
|
|
doc_orig = rna.properties[class_prop].description
|
|
if doc_orig == self.properties.doc_new:
|
|
return ('RUNNING_MODAL',)
|
|
|
|
print("rna - old:'%s' -> new:'%s'" % (doc_orig, self.properties.doc_new))
|
|
upload["title"] = 'RNA %s:%s' % (self.properties.doc_id, doc_orig)
|
|
|
|
upload["description"] = self.properties.doc_new
|
|
|
|
self._send_xmlrpc(upload)
|
|
|
|
return ('FINISHED',)
|
|
|
|
def invoke(self, context, event):
|
|
wm = context.manager
|
|
wm.invoke_props_popup(self, event)
|
|
return ('RUNNING_MODAL',)
|
|
|
|
|
|
class WM_OT_reload_scripts(bpy.types.Operator):
|
|
'''Load online reference docs'''
|
|
bl_idname = "wm.reload_scripts"
|
|
bl_label = "Reload Scripts"
|
|
|
|
def execute(self, context):
|
|
MOD = type(bpy)
|
|
import sys
|
|
bpy.load_scripts(True)
|
|
'''
|
|
prefix = bpy.base_path
|
|
items = list(sys.modules.items())
|
|
items.sort()
|
|
items.reverse()
|
|
for mod_name, mod in items:
|
|
mod_file = getattr(mod, "__file__", "")
|
|
if mod_file.startswith(prefix) and "__init__" not in mod_file:
|
|
print(mod_file)
|
|
reload(mod)
|
|
"""
|
|
for submod_name in dir(mod):
|
|
submod = getattr(mod, submod_name)
|
|
if isinstance(submod, MOD):
|
|
reload(submod)
|
|
"""
|
|
else:
|
|
print("Ignoring:", mod, mod_file)
|
|
'''
|
|
return ('FINISHED',)
|
|
|
|
|
|
bpy.ops.add(MESH_OT_delete_edgeloop)
|
|
|
|
bpy.ops.add(WM_OT_context_set_boolean)
|
|
bpy.ops.add(WM_OT_context_set_int)
|
|
bpy.ops.add(WM_OT_context_set_float)
|
|
bpy.ops.add(WM_OT_context_set_string)
|
|
bpy.ops.add(WM_OT_context_set_enum)
|
|
bpy.ops.add(WM_OT_context_toggle)
|
|
bpy.ops.add(WM_OT_context_toggle_enum)
|
|
bpy.ops.add(WM_OT_context_cycle_enum)
|
|
bpy.ops.add(WM_OT_context_cycle_int)
|
|
|
|
bpy.ops.add(WM_OT_doc_view)
|
|
bpy.ops.add(WM_OT_doc_edit)
|
|
|
|
bpy.ops.add(WM_OT_reload_scripts)
|
|
|
|
# experemental!
|
|
import rna_prop_ui
|
|
bpy.ops.add(rna_prop_ui.WM_OT_properties_edit)
|
|
bpy.ops.add(rna_prop_ui.WM_OT_properties_add)
|
|
bpy.ops.add(rna_prop_ui.WM_OT_properties_remove)
|