Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlijenstina <lijenstina@gmail.com>2017-05-12 02:59:08 +0300
committerlijenstina <lijenstina@gmail.com>2017-05-12 02:59:08 +0300
commit32b977d1b2f4abb9f09308636ba10c224c6a76f6 (patch)
tree993bc1cd3da72efac105bfc1ddfbfa9127ea3760 /stored_views
parentd9e259cd94194c74387ff445a1623119a48505e8 (diff)
Stored Views: cleanup, refactor, various fixes
Bumped version to 0.3.6 Pep 8 cleanup Remove the logger setup, uncomment the log calls in the sripts Replace deprecated imp call with importlib Add AddonPreferences settings importers, draw update Fix crash with New Camera To View if there is no object present Fix import, export BLSV crashes: No file was selected during import Pickle crashes during export with Vectors, Quaternions Crash with import if the scene wasn't initialized Finish the IO user interface switchable from the preferences Finish Import from an another scene - scene selection was missing making the feature not working Replace type comparisons with isinstance Fix the 3D view text alignment so it doesn't show bellow the properties area Fix the 3d view draw crash when opening the File Browser Fix crash with Material enum missing in DisplayData
Diffstat (limited to 'stored_views')
-rw-r--r--stored_views/__init__.py117
-rw-r--r--stored_views/core.py65
-rw-r--r--stored_views/io.py239
-rw-r--r--stored_views/operators.py86
-rw-r--r--stored_views/properties.py114
-rw-r--r--stored_views/ui.py110
6 files changed, 478 insertions, 253 deletions
diff --git a/stored_views/__init__.py b/stored_views/__init__.py
index cfc0beb0..8deca8f0 100644
--- a/stored_views/__init__.py
+++ b/stored_views/__init__.py
@@ -18,73 +18,113 @@
bl_info = {
"name": "Stored Views",
- "description": "Save and restore User defined views, pov, layers and display configs.",
+ "description": "Save and restore User defined views, pov, layers and display configs",
"author": "nfloyd, Francesco Siddi",
- "version": (0, 3, 4,),
+ "version": (0, 3, 6),
"blender": (2, 7, 8),
"location": "View3D > Properties > Stored Views",
- "warning": 'beta release, single view only',
- "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/Scripts/3D_interaction/stored_views",
- "tracker_url": "https://developer.blender.org/maniphest/task/edit/form/2/",
+ "warning": "",
+ "wiki_url": "https://wiki.blender.org/index.php/Extensions:2.5/"
+ "Py/Scripts/3D_interaction/stored_views",
"category": "3D View"}
-# ACKNOWLEDGMENT
-# ==============
-# import/export functionality is mostly based
-# on Bart Crouch's Theme Manager Addon
+"""
+ACKNOWLEDGMENT
+==============
+import/export functionality is mostly based
+on Bart Crouch's Theme Manager Addon
-# TODO: check against 2.63
-# TODO: quadview complete support : investigate. Where's the data?
-# TODO: lock_camera_and_layers. investigate usage
-# TODO: list reordering
+TODO: quadview complete support : investigate. Where's the data?
+TODO: lock_camera_and_layers. investigate usage
+TODO: list reordering
-# logging setup
-'''
-import logging
-
-logger = logging.getLogger(__name__)
-logger.setLevel(logging.DEBUG)
-hdlr = logging.StreamHandler()
-fmtr = logging.Formatter('%(asctime)s %(levelname)s %(name)s : %(funcName)s - %(message)s')
-hdlr.setFormatter(fmtr)
-logger.addHandler(hdlr)
-'''
+NOTE: logging setup has to be provided by the user in a separate config file
+ as Blender will not try to configure logging by default in an add-on
+ The Config File should be in the Blender Config folder > /scripts/startup/config_logging.py
+ For setting up /location of the config folder see:
+ https://docs.blender.org/manual/en/dev/getting_started/
+ installing/configuration/directories.html
+ For configuring logging itself in the file, general Python documentation should work
+ As the logging calls are not configured, they can be kept in the other modules of this add-on
+ and will not have output until the logging configuration is set up
+"""
if "bpy" in locals():
- import imp
- imp.reload(ui)
- imp.reload(properties)
- imp.reload(core)
- imp.reload(operators)
- imp.reload(io)
+ import importlib
+ importlib.reload(core)
+ importlib.reload(ui)
+ importlib.reload(properties)
+ importlib.reload(operators)
+ importlib.reload(io)
else:
- #from . import properties, core
- from . import ui, properties, core, operators, io
+ from . import core
+ from . import ui
+ from . import properties
+ from . import operators
+ from . import io
import bpy
-from bpy.props import PointerProperty
+from bpy.props import (
+ BoolProperty,
+ IntProperty,
+ PointerProperty,
+ )
+from bpy.types import (
+ AddonPreferences,
+ Operator,
+ )
-class VIEW3D_stored_views_initialize(bpy.types.Operator):
+class VIEW3D_stored_views_initialize(Operator):
bl_idname = "view3d.stored_views_initialize"
- bl_label = "Initilize"
+ bl_label = "Initialize"
@classmethod
def poll(cls, context):
return not hasattr(bpy.types.Scene, 'stored_views')
def execute(self, context):
- bpy.types.Scene.stored_views = PointerProperty(type=properties.StoredViewsData)
+ bpy.types.Scene.stored_views = PointerProperty(
+ type=properties.StoredViewsData
+ )
scenes = bpy.data.scenes
for scene in scenes:
core.DataStore.sanitize_data(scene)
return {'FINISHED'}
+# Addon Preferences
+
+class VIEW3D_stored_views_preferences(AddonPreferences):
+ bl_idname = __name__
+
+ show_exporters = BoolProperty(
+ name="Enable I/O Operators",
+ default=False,
+ description="Enable Import/Export Operations in the UI:\n"
+ "Import Stored Views preset,\n"
+ "Export Stored Views preset and \n"
+ "Import stored views from scene",
+ )
+ view_3d_update_rate = IntProperty(
+ name="3D view update",
+ description="Update rate of the 3D view redraw\n"
+ "Increse the value if the UI feels sluggish",
+ min=1, max=10,
+ default=1
+ )
+
+ def draw(self, context):
+ layout = self.layout
+
+ row = layout.row(align=True)
+ row.prop(self, "view_3d_update_rate", toggle=True)
+ row.prop(self, "show_exporters", toggle=True)
+
+
def register():
bpy.utils.register_module(__name__)
- # Context restricted, need to initialize different (button to be clicked by user)
- #initialize()
+
def unregister():
ui.VIEW3D_stored_views_draw.handle_remove(bpy.context)
@@ -92,5 +132,6 @@ def unregister():
if hasattr(bpy.types.Scene, "stored_views"):
del bpy.types.Scene.stored_views
+
if __name__ == "__main__":
register()
diff --git a/stored_views/core.py b/stored_views/core.py
index 21e49b31..34f57dfe 100644
--- a/stored_views/core.py
+++ b/stored_views/core.py
@@ -1,15 +1,25 @@
-'''
+# gpl authors: nfloyd, Francesco Siddi
+
+
import logging
module_logger = logging.getLogger(__name__)
-'''
-import hashlib
+import hashlib
import bpy
+# Utility function get preferences setting for exporters
+def get_preferences():
+ # replace the key if the add-on name changes
+ addon = bpy.context.user_preferences.addons["stored_views"]
+ show_warn = (addon.preferences.show_exporters if addon else False)
+
+ return show_warn
+
+
class StoredView():
def __init__(self, mode, index=None):
-# self.logger = logging.getLogger('%s.StoredView' % __name__)
+ self.logger = logging.getLogger('%s.StoredView' % __name__)
self.scene = bpy.context.scene
self.view3d = bpy.context.space_data
self.index = index
@@ -21,12 +31,12 @@ class StoredView():
else:
stored_view = self.data_store.get(self.index)
self.from_v3d(stored_view)
-# self.logger.debug('index: %s name: %s' % (self.data_store.current_index, stored_view.name))
+ self.logger.debug('index: %s name: %s' % (self.data_store.current_index, stored_view.name))
def set(self):
stored_view = self.data_store.get(self.index)
self.update_v3d(stored_view)
-# self.logger.debug('index: %s name: %s' % (self.data_store.current_index, stored_view.name))
+ self.logger.debug('index: %s name: %s' % (self.data_store.current_index, stored_view.name))
def from_v3d(self, stored_view):
raise NotImplementedError("Subclass must implement abstract method")
@@ -42,7 +52,7 @@ class StoredView():
class POV(StoredView):
def __init__(self, index=None):
super().__init__(mode='POV', index=index)
-# self.logger = logging.getLogger('%s.POV' % __name__)
+ self.logger = logging.getLogger('%s.POV' % __name__)
def from_v3d(self, stored_view):
view3d = self.view3d
@@ -61,7 +71,7 @@ class POV(StoredView):
stored_view.camera_type = view3d.camera.type # type : 'CAMERA' or 'MESH'
stored_view.camera_name = view3d.camera.name # store string instead of object
stored_view.camera_pointer = view3d.camera.as_pointer()
- if view3d.lock_object != None:
+ if view3d.lock_object is not None:
stored_view.lock_object_name = view3d.lock_object.name # idem
stored_view.lock_object_pointer = view3d.lock_object.as_pointer() # idem
@@ -79,7 +89,7 @@ class POV(StoredView):
view3d.clip_start = stored_view.clip_start
view3d.clip_end = stored_view.clip_end
view3d.lock_cursor = stored_view.lock_cursor
- if stored_view.lock_cursor == True:
+ if stored_view.lock_cursor is True:
# update cursor only if view is locked to cursor
view3d.cursor_location = stored_view.cursor_location
@@ -120,18 +130,19 @@ class POV(StoredView):
@staticmethod
def is_modified(context, stored_view):
- # TODO: check for others param, currently only perspectiveand perspective_matrix are checked
-# logger = logging.getLogger('%s.POV' % __name__)
+ # TODO: check for others param, currently only perspective
+ # and perspective_matrix are checked
+ POV.logger = logging.getLogger('%s.POV' % __name__)
view3d = context.space_data
region3d = view3d.region_3d
if region3d.view_perspective != stored_view.perspective:
-# logger.debug('view_perspective')
+ POV.logger.debug('view_perspective')
return True
md5 = POV._get_perspective_matrix_md5(region3d)
if (md5 != stored_view.perspective_matrix_md5 and
- region3d.view_perspective != "CAMERA"):
-# logger.debug('perspective_matrix')
+ region3d.view_perspective != "CAMERA"):
+ POV.logger.debug('perspective_matrix')
return True
return False
@@ -145,7 +156,7 @@ class POV(StoredView):
class Layers(StoredView):
def __init__(self, index=None):
super().__init__(mode='LAYERS', index=index)
-# self.logger = logging.getLogger('%s.Layers' % __name__)
+ self.logger = logging.getLogger('%s.Layers' % __name__)
def from_v3d(self, stored_view):
view3d = self.view3d
@@ -156,26 +167,25 @@ class Layers(StoredView):
def update_v3d(self, stored_view):
view3d = self.view3d
view3d.lock_camera_and_layers = stored_view.lock_camera_and_layers
- if stored_view.lock_camera_and_layers == True:
+ if stored_view.lock_camera_and_layers is True:
self.scene.layers = stored_view.scene_layers
else:
view3d.layers = stored_view.view_layers
@staticmethod
def is_modified(context, stored_view):
-# logger = logging.getLogger('%s.Layers' % __name__)
+ Layers.logger = logging.getLogger('%s.Layers' % __name__)
if stored_view.lock_camera_and_layers != context.space_data.lock_camera_and_layers:
-# logger.debug('lock_camera_and_layers')
+ Layers.logger.debug('lock_camera_and_layers')
return True
- if stored_view.lock_camera_and_layers == True:
+ if stored_view.lock_camera_and_layers is True:
for i in range(20):
if stored_view.scene_layers[i] != context.scene.layers[i]:
-# logger.debug('scene_layers[%s]' % (i, ))
+ Layers.logger.debug('scene_layers[%s]' % (i, ))
return True
else:
for i in range(20):
if stored_view.view_layers[i] != context.space_data.view3d.layers[i]:
-# logger.debug('view_layers[%s]' % (i ,))
return True
return False
@@ -183,7 +193,7 @@ class Layers(StoredView):
class Display(StoredView):
def __init__(self, index=None):
super().__init__(mode='DISPLAY', index=index)
-# self.logger = logging.getLogger('%s.Display' % __name__)
+ self.logger = logging.getLogger('%s.Display' % __name__)
def from_v3d(self, stored_view):
view3d = self.view3d
@@ -221,24 +231,23 @@ class Display(StoredView):
@staticmethod
def is_modified(context, stored_view):
- # logger = logging.getLogger('%s.Display' % __name__)
+ Display.logger = logging.getLogger('%s.Display' % __name__)
view3d = context.space_data
excludes = ["material_mode", "quad_view", "lock_rotation", "show_sync_view", "use_box_clip", "name"]
for k, v in stored_view.items():
if k not in excludes:
if getattr(view3d, k) != getattr(stored_view, k):
-# logger.debug('%s' % (k ,))
return True
if stored_view.material_mode != context.scene.game_settings.material_mode:
-# logger.debug('material_mode')
+ Display.logger.debug('material_mode')
return True
class View(StoredView):
def __init__(self, index=None):
super().__init__(mode='VIEW', index=index)
-# self.logger = logging.getLogger('%s.View' % __name__)
+ self.logger = logging.getLogger('%s.View' % __name__)
self.pov = POV()
self.layers = Layers()
self.display = Display()
@@ -264,12 +273,12 @@ class View(StoredView):
class DataStore():
def __init__(self, scene=None, mode=None):
- if scene == None:
+ if scene is None:
scene = bpy.context.scene
stored_views = scene.stored_views
self.mode = mode
- if mode == None:
+ if mode is None:
self.mode = stored_views.mode
if self.mode == 'VIEW':
diff --git a/stored_views/io.py b/stored_views/io.py
index 862b2f92..b6aec4dd 100644
--- a/stored_views/io.py
+++ b/stored_views/io.py
@@ -1,19 +1,28 @@
+# gpl authors: nfloyd, Francesco Siddi
+
import gzip
import os
import pickle
import shutil
import bpy
-from bpy.props import (BoolProperty,
- StringProperty)
-
-from bpy_extras.io_utils import ExportHelper, ImportHelper
-
+from bpy.types import Operator
+from bpy.props import (
+ BoolProperty,
+ StringProperty
+ )
+from bpy_extras.io_utils import (
+ ExportHelper,
+ ImportHelper,
+ )
from . import bl_info
-from . operators import DataStore
+from .core import get_preferences
+from .operators import DataStore
+
# TODO: reinstate filters?
class IO_Utils():
+
@staticmethod
def get_preset_path():
# locate stored_views preset folder
@@ -21,7 +30,7 @@ class IO_Utils():
if not paths:
# stored_views preset folder doesn't exist, so create it
paths = [os.path.join(bpy.utils.user_resource('SCRIPTS'), "presets",
- "stored_views")]
+ "stored_views")]
if not os.path.exists(paths[0]):
os.makedirs(paths[0])
@@ -30,28 +39,39 @@ class IO_Utils():
@staticmethod
def stored_views_apply_from_scene(scene_name, replace=True):
scene = bpy.context.scene
- sv = bpy.context.scene.stored_views
-# io_filters = sv.settings.io_filters
-
- structs = [sv.view_list, sv.pov_list, sv.layers_list, sv.display_list]
- if replace == True:
- for st in structs: # clear swap and list
- while len(st) > 0:
- st.remove(0)
-
- f_sv = bpy.data.scenes[scene_name].stored_views
- f_structs = [f_sv.view_list, f_sv.pov_list, f_sv.layers_list, f_sv.display_list]
-# is_filtered = [io_filters.views, io_filters.point_of_views, io_filters.layers, io_filters.displays]
-
- for i in range(len(f_structs)):
-# if is_filtered[i] == False:
-# continue
- for j in f_structs[i]:
- item = structs[i].add()
- #stored_views_copy_item(j, item)
- for k, v in j.items():
- item[k] = v
- DataStore.sanitize_data(scene)
+ scene_exists = True if scene_name in bpy.data.scenes.keys() else False
+
+ if scene_exists:
+ sv = bpy.context.scene.stored_views
+ # io_filters = sv.settings.io_filters
+
+ structs = [sv.view_list, sv.pov_list, sv.layers_list, sv.display_list]
+ if replace is True:
+ for st in structs: # clear swap and list
+ while len(st) > 0:
+ st.remove(0)
+
+ f_sv = bpy.data.scenes[scene_name].stored_views
+ # f_sv = bpy.data.scenes[scene_name].stored_views
+ f_structs = [f_sv.view_list, f_sv.pov_list, f_sv.layers_list, f_sv.display_list]
+ """
+ is_filtered = [io_filters.views, io_filters.point_of_views,
+ io_filters.layers, io_filters.displays]
+ """
+ for i in range(len(f_structs)):
+ """
+ if is_filtered[i] is False:
+ continue
+ """
+ for j in f_structs[i]:
+ item = structs[i].add()
+ # stored_views_copy_item(j, item)
+ for k, v in j.items():
+ item[k] = v
+ DataStore.sanitize_data(scene)
+ return True
+ else:
+ return False
@staticmethod
def stored_views_export_to_blsv(filepath, name='Custom Preset'):
@@ -60,7 +80,6 @@ class IO_Utils():
dump["info"]["script"] = bl_info['name']
dump["info"]["script_version"] = bl_info['version']
dump["info"]["version"] = bpy.app.version
-# dump["info"]["build_revision"] = bpy.app.build_revision
dump["info"]["preset_name"] = name
# get current stored views settings
@@ -90,32 +109,34 @@ class IO_Utils():
if prop.identifier == "rna_type":
# not a setting, so skip
continue
+
val = getattr(struct, prop.identifier)
- if str(type(val)) in ["<class 'bpy_prop_array'>",
- "<class 'mathutils.Quaternion'>",
- "<class 'mathutils.Vector'>"]:
+ if str(type(val)) in ["<class 'bpy_prop_array'>"]:
# array
- dict[prop.identifier] = [v \
- for v in val]
+ dict[prop.identifier] = [v for v in val]
+ # adress the pickle limitations of dealing with the Vector class
+ elif str(type(val)) in ["<class 'Vector'>",
+ "<class 'Quaternion'>"]:
+ dict[prop.identifier] = [v for v in val]
else:
# single value
dict[prop.identifier] = val
-# io_filters = sv.settings.io_filters
+ # io_filters = sv.settings.io_filters
dump["data"] = {"point_of_views": {},
"layers": {},
"displays": {},
"views": {}}
- others_data = [(dump["data"]["point_of_views"], sv.pov_list), # , io_filters.point_of_views),
- (dump["data"]["layers"], sv.layers_list), # , io_filters.layers),
- (dump["data"]["displays"], sv.display_list)] # , io_filters.displays)]
+ others_data = [(dump["data"]["point_of_views"], sv.pov_list), # , io_filters.point_of_views),
+ (dump["data"]["layers"], sv.layers_list), # , io_filters.layers),
+ (dump["data"]["displays"], sv.display_list)] # , io_filters.displays)]
for list_data in others_data:
-# if list_data[2] == True:
+ # if list_data[2] is True:
dump_list(list_data[0], list_data[1])
views_data = (dump["data"]["views"], sv.view_list)
-# if io_filters.views == True:
+ # if io_filters.views is True:
dump_view_list(views_data[0], views_data[1])
# save to file
@@ -127,40 +148,49 @@ class IO_Utils():
@staticmethod
def stored_views_apply_preset(filepath, replace=True):
+ if not filepath:
+ return False
+
file = gzip.open(filepath, mode='rb')
dump = pickle.load(file)
file.close()
-
# apply preset
scene = bpy.context.scene
- sv = scene.stored_views
-# io_filters = sv.settings.io_filters
+ sv = getattr(scene, "stored_views", None)
+
+ if not sv:
+ return False
+
+ # io_filters = sv.settings.io_filters
sv_data = {"point_of_views": sv.pov_list,
"views": sv.view_list,
"layers": sv.layers_list,
"displays": sv.display_list}
for sv_struct, props in dump["data"].items():
-# is_filtered = getattr(io_filters, sv_struct)
-# if is_filtered == False:
-# continue
- sv_list = sv_data[sv_struct]#.list
- if replace == True: # clear swap and list
+ """
+ is_filtered = getattr(io_filters, sv_struct)
+ if is_filtered is False:
+ continue
+ """
+ sv_list = sv_data[sv_struct] # .list
+ if replace is True: # clear swap and list
while len(sv_list) > 0:
sv_list.remove(0)
for key, prop_struct in props.items():
sv_item = sv_list.add()
+
for subprop, subval in prop_struct.items():
- if type(subval) == type({}): # views : pov, layers, displays
+ if isinstance(subval, dict): # views : pov, layers, displays
v_subprop = getattr(sv_item, subprop)
for v_subkey, v_subval in subval.items():
- if type(v_subval) == type([]): # array like of pov,...
+ if isinstance(v_subval, list): # array like of pov,...
v_array_like = getattr(v_subprop, v_subkey)
for i in range(len(v_array_like)):
v_array_like[i] = v_subval[i]
else:
setattr(v_subprop, v_subkey, v_subval) # others
- elif type(subval) == type([]):
+ elif isinstance(subval, list):
array_like = getattr(sv_item, subprop)
for i in range(len(array_like)):
array_like[i] = subval[i]
@@ -169,21 +199,45 @@ class IO_Utils():
DataStore.sanitize_data(scene)
+ return True
+
-class VIEW3D_stored_views_import(bpy.types.Operator, ImportHelper):
+class VIEW3D_stored_views_import(Operator, ImportHelper):
bl_idname = "stored_views.import"
bl_label = "Import Stored Views preset"
bl_description = "Import a .blsv preset file to the current Stored Views"
filename_ext = ".blsv"
- filter_glob = StringProperty(default="*.blsv", options={'HIDDEN'})
- replace = BoolProperty(name="Replace",
- default=True,
- description="Replace current stored views, otherwise append")
+ filter_glob = StringProperty(
+ default="*.blsv",
+ options={'HIDDEN'}
+ )
+ replace = BoolProperty(
+ name="Replace",
+ default=True,
+ description="Replace current stored views, otherwise append"
+ )
+
+ @classmethod
+ def poll(cls, context):
+ return get_preferences()
def execute(self, context):
+ # the usual way is to not select the file in the file browser
+ exists = os.path.isfile(self.filepath) if self.filepath else False
+ if not exists:
+ self.report({'WARNING'},
+ "No filepath specified, or file could not be found. Operation Cancelled")
+ return {'CANCELLED'}
+
# apply chosen preset
- IO_Utils.stored_views_apply_preset(filepath=self.filepath, replace=self.replace)
+ apply_preset = IO_Utils.stored_views_apply_preset(
+ filepath=self.filepath, replace=self.replace
+ )
+ if not apply_preset:
+ self.report({'WARNING'},
+ "Please Initialize Stored Views first (in the 3D View Properties Area)")
+ return {'CANCELLED'}
# copy preset to presets folder
filename = os.path.basename(self.filepath)
@@ -191,47 +245,82 @@ class VIEW3D_stored_views_import(bpy.types.Operator, ImportHelper):
shutil.copyfile(self.filepath,
os.path.join(IO_Utils.get_preset_path()[0], filename))
except:
- self.report({'WARNING'}, "Stored Views: preset applied, but installing failed (preset already exists?)")
+ self.report({'WARNING'},
+ "Stored Views: preset applied, but installing failed (preset already exists?)")
return{'CANCELLED'}
return{'FINISHED'}
-class VIEW3D_stored_views_import_from_scene(bpy.types.Operator):
+class VIEW3D_stored_views_import_from_scene(Operator):
bl_idname = "stored_views.import_from_scene"
bl_label = "Import stored views from scene"
- bl_description = "Import current stored views by those from another scene"
+ bl_description = "Import currently stored views from an another scene"
+
+ scene_name = StringProperty(
+ name="Scene Name",
+ description="A current blend scene",
+ default=""
+ )
+ replace = BoolProperty(
+ name="Replace",
+ default=True,
+ description="Replace current stored views, otherwise append"
+ )
+
+ @classmethod
+ def poll(cls, context):
+ return get_preferences()
+
+ def draw(self, context):
+ layout = self.layout
- scene_name = bpy.props.StringProperty(name="Scene Name",
- description="A current blend scene",
- default="")
+ layout.prop_search(self, "scene_name", bpy.data, "scenes")
+ layout.prop(self, "replace")
- replace = BoolProperty(name="Replace",
- default=True,
- description="Replace current stored views, otherwise append")
+ def invoke(self, context, event):
+ return context.window_manager.invoke_props_dialog(self)
def execute(self, context):
# filepath should always be given
if not self.scene_name:
- self.report("ERROR", "Could not find scene")
+ self.report({"WARNING"},
+ "No scene name was given. Operation Cancelled")
return{'CANCELLED'}
- IO_Utils.stored_views_apply_from_scene(self.scene_name, replace=self.replace)
+ is_finished = IO_Utils.stored_views_apply_from_scene(
+ self.scene_name, replace=self.replace
+ )
+ if not is_finished:
+ self.report({"WARNING"},
+ "Could not find the specified scene. Operation Cancelled")
+ return {"CANCELLED"}
return{'FINISHED'}
-class VIEW3D_stored_views_export(bpy.types.Operator, ExportHelper):
+class VIEW3D_stored_views_export(Operator, ExportHelper):
bl_idname = "stored_views.export"
bl_label = "Export Stored Views preset"
bl_description = "Export the current Stored Views to a .blsv preset file"
filename_ext = ".blsv"
- filepath = StringProperty(default=os.path.join(IO_Utils.get_preset_path()[0], "untitled"))
- filter_glob = StringProperty(default="*.blsv", options={'HIDDEN'})
- preset_name = StringProperty(name="Preset name",
- default="",
- description="Name of the stored views preset")
+ filepath = StringProperty(
+ default=os.path.join(IO_Utils.get_preset_path()[0], "untitled")
+ )
+ filter_glob = StringProperty(
+ default="*.blsv",
+ options={'HIDDEN'}
+ )
+ preset_name = StringProperty(
+ name="Preset name",
+ default="",
+ description="Name of the stored views preset"
+ )
+
+ @classmethod
+ def poll(cls, context):
+ return get_preferences()
def execute(self, context):
IO_Utils.stored_views_export_to_blsv(self.filepath, self.preset_name)
diff --git a/stored_views/operators.py b/stored_views/operators.py
index d4500502..1ec3026b 100644
--- a/stored_views/operators.py
+++ b/stored_views/operators.py
@@ -1,12 +1,19 @@
-import bpy
-
-from bpy.props import (FloatProperty, BoolProperty, IntProperty,
- FloatVectorProperty, StringProperty, EnumProperty)
-from . core import stored_view_factory, DataStore
-from . ui import init_draw
+# gpl authors: nfloyd, Francesco Siddi
-
-class VIEW3D_stored_views_save(bpy.types.Operator):
+import bpy
+from bpy.props import (
+ IntProperty,
+ StringProperty,
+ )
+from bpy.types import Operator
+from .core import (
+ stored_view_factory,
+ DataStore,
+ )
+from .ui import init_draw
+
+
+class VIEW3D_stored_views_save(Operator):
bl_idname = "stored_views.save"
bl_label = "Save Current"
bl_description = "Save the view 3d current state"
@@ -23,7 +30,7 @@ class VIEW3D_stored_views_save(bpy.types.Operator):
return {'FINISHED'}
-class VIEW3D_stored_views_set(bpy.types.Operator):
+class VIEW3D_stored_views_set(Operator):
bl_idname = "stored_views.set"
bl_label = "Set"
bl_description = "Update the view 3D according to this view"
@@ -40,12 +47,12 @@ class VIEW3D_stored_views_set(bpy.types.Operator):
return {'FINISHED'}
-class VIEW3D_stored_views_delete(bpy.types.Operator):
+class VIEW3D_stored_views_delete(Operator):
bl_idname = "stored_views.delete"
bl_label = "Delete"
bl_description = "Delete this view"
- index = bpy.props.IntProperty()
+ index = IntProperty()
def execute(self, context):
data = DataStore()
@@ -53,36 +60,43 @@ class VIEW3D_stored_views_delete(bpy.types.Operator):
return {'FINISHED'}
-class VIEW3D_New_Camera_to_View(bpy.types.Operator):
+
+class VIEW3D_New_Camera_to_View(Operator):
bl_idname = "stored_views.newcamera"
bl_label = "New Camera To View"
- bl_description = "Add a new Casmera Active & Aligned to this view"
+ bl_description = "Add a new Active Camera and align it to this view"
def execute(self, context):
- bpy.ops.object.mode_set(mode='OBJECT')
-
- bpy.ops.object.camera_add(
- view_align=True)
- cam = bpy.context.active_object
- bpy.ops.view3d.object_as_camera()
- bpy.ops.view3d.camera_to_view()
-
-
- # this will name the Camera Object
- if 'View_Camera' not in context.scene.objects:
- cam.name = "View_Camera"
- else:
- cam.name = "View_Camera.000"
+ try:
+ # check for operator's poll (there is no active object, for instance)
+ if bpy.ops.object.mode_set.poll():
+ bpy.ops.object.mode_set(mode='OBJECT')
+
+ bpy.ops.object.camera_add(view_align=True)
+ cam = bpy.context.active_object
+ bpy.ops.view3d.object_as_camera()
+ bpy.ops.view3d.camera_to_view()
+
+ # this will name the Camera Object
+ if 'View_Camera' not in context.scene.objects:
+ cam.name = "View_Camera"
+ else:
+ cam.name = "View_Camera.000"
+
+ return {'FINISHED'}
+ except:
+ self.report({'WARNING'},
+ "Operation Cancelled. New Camera to View failed to add a new camera")
+ return {'CANCELLED'}
- return {'FINISHED'}
-### Camera marker & switcher by Fsiddi
-class SetSceneCamera(bpy.types.Operator):
+# Camera marker & switcher by Fsiddi
+class SetSceneCamera(Operator):
bl_idname = "cameraselector.set_scene_camera"
bl_label = "Set Scene Camera"
- bl_description = "Set chosen camera as the scene's active camera."
+ bl_description = "Set chosen camera as the scene's active camera"
- chosen_camera = bpy.props.StringProperty()
+ chosen_camera = StringProperty()
select_chosen = False
def execute(self, context):
@@ -113,18 +127,18 @@ class SetSceneCamera(bpy.types.Operator):
return self.execute(context)
-class AddCameraMarker(bpy.types.Operator):
+class AddCameraMarker(Operator):
bl_idname = "cameraselector.add_camera_marker"
bl_label = "Add Camera Marker"
- bl_description = "Add a timeline marker bound to chosen camera."
+ bl_description = "Add a timeline marker bound to chosen camera"
- chosen_camera = bpy.props.StringProperty()
+ chosen_camera = StringProperty()
def execute(self, context):
chosen_camera = bpy.data.objects.get(self.chosen_camera, None)
scene = context.scene
if not chosen_camera:
- self.report({'ERROR'}, "Camera %s not found.")
+ self.report({'WARNING'}, "Camera %s not found. Operation Cancelled")
return {'CANCELLED'}
current_frame = scene.frame_current
diff --git a/stored_views/properties.py b/stored_views/properties.py
index f011ce68..6dffc3d0 100644
--- a/stored_views/properties.py
+++ b/stored_views/properties.py
@@ -1,25 +1,35 @@
+# gpl authors: nfloyd, Francesco Siddi
+
from bpy.types import PropertyGroup
-from bpy.props import (BoolProperty,
- BoolVectorProperty,
- CollectionProperty,
- FloatProperty,
- FloatVectorProperty,
- EnumProperty,
- IntProperty,
- IntVectorProperty,
- PointerProperty,
- StringProperty)
+from bpy.props import (
+ BoolProperty,
+ BoolVectorProperty,
+ CollectionProperty,
+ FloatProperty,
+ FloatVectorProperty,
+ EnumProperty,
+ IntProperty,
+ IntVectorProperty,
+ PointerProperty,
+ StringProperty,
+ )
class POVData(PropertyGroup):
distance = FloatProperty()
- location = FloatVectorProperty(subtype='TRANSLATION')
- rotation = FloatVectorProperty(subtype='QUATERNION',
- size=4)
+ location = FloatVectorProperty(
+ subtype='TRANSLATION'
+ )
+ rotation = FloatVectorProperty(
+ subtype='QUATERNION',
+ size=4
+ )
name = StringProperty()
- perspective = EnumProperty(items=[('PERSP', '', ''),
- ('ORTHO', '', ''),
- ('CAMERA', '', '')])
+ perspective = EnumProperty(
+ items=[('PERSP', '', ''),
+ ('ORTHO', '', ''),
+ ('CAMERA', '', '')]
+ )
lens = FloatProperty()
clip_start = FloatProperty()
clip_end = FloatProperty()
@@ -42,11 +52,14 @@ class LayersData(PropertyGroup):
class DisplayData(PropertyGroup):
name = StringProperty()
- viewport_shade = EnumProperty(items=[('BOUNDBOX', 'BOUNDBOX', 'BOUNDBOX'),
- ('WIREFRAME', 'WIREFRAME', 'WIREFRAME'),
- ('SOLID', 'SOLID', 'SOLID'),
- ('TEXTURED', 'TEXTURED', 'TEXTURED'),
- ('RENDERED', 'RENDERED', 'RENDERED')])
+ viewport_shade = EnumProperty(
+ items=[('BOUNDBOX', 'BOUNDBOX', 'BOUNDBOX'),
+ ('WIREFRAME', 'WIREFRAME', 'WIREFRAME'),
+ ('SOLID', 'SOLID', 'SOLID'),
+ ('TEXTURED', 'TEXTURED', 'TEXTURED'),
+ ('MATERIAL', 'MATERIAL', 'MATERIAL'),
+ ('RENDERED', 'RENDERED', 'RENDERED')]
+ )
show_only_render = BoolProperty()
show_outline_selected = BoolProperty()
show_all_objects_origin = BoolProperty()
@@ -58,9 +71,11 @@ class DisplayData(PropertyGroup):
grid_lines = IntProperty()
grid_scale = FloatProperty()
grid_subdivisions = IntProperty()
- material_mode = EnumProperty(items=[('TEXTURE_FACE', '', ''),
- ('MULTITEXTURE', '', ''),
- ('GLSL', '', '')])
+ material_mode = EnumProperty(
+ items=[('TEXTURE_FACE', '', ''),
+ ('MULTITEXTURE', '', ''),
+ ('GLSL', '', '')]
+ )
show_textured_solid = BoolProperty()
quad_view = BoolProperty()
lock_rotation = BoolProperty()
@@ -69,22 +84,43 @@ class DisplayData(PropertyGroup):
class ViewData(PropertyGroup):
- pov = PointerProperty(type=POVData)
- layers = PointerProperty(type=LayersData)
- display = PointerProperty(type=DisplayData)
+ pov = PointerProperty(
+ type=POVData
+ )
+ layers = PointerProperty(
+ type=LayersData
+ )
+ display = PointerProperty(
+ type=DisplayData
+ )
name = StringProperty()
class StoredViewsData(PropertyGroup):
- pov_list = CollectionProperty(type=POVData)
- layers_list = CollectionProperty(type=LayersData)
- display_list = CollectionProperty(type=DisplayData)
- view_list = CollectionProperty(type=ViewData)
- mode = EnumProperty(name="Mode",
- items=[('VIEW', 'View', ''),
- ('POV', 'POV', ''),
- ('LAYERS', 'Layers', ''),
- ('DISPLAY', 'Display', '')],
- default='VIEW')
- current_indices = IntVectorProperty(size=4, default=[-1, -1, -1, -1])
- view_modified = BoolProperty(default=False)
+ pov_list = CollectionProperty(
+ type=POVData
+ )
+ layers_list = CollectionProperty(
+ type=LayersData
+ )
+ display_list = CollectionProperty(
+ type=DisplayData
+ )
+ view_list = CollectionProperty(
+ type=ViewData
+ )
+ mode = EnumProperty(
+ name="Mode",
+ items=[('VIEW', "View", "3D View settings"),
+ ('POV', "POV", "POV settings"),
+ ('LAYERS', "Layers", "Layers settings"),
+ ('DISPLAY', "Display", "Display settings")],
+ default='VIEW'
+ )
+ current_indices = IntVectorProperty(
+ size=4,
+ default=[-1, -1, -1, -1]
+ )
+ view_modified = BoolProperty(
+ default=False
+ )
diff --git a/stored_views/ui.py b/stored_views/ui.py
index f1d7df12..09f0b15c 100644
--- a/stored_views/ui.py
+++ b/stored_views/ui.py
@@ -1,49 +1,72 @@
-'''
+# gpl authors: nfloyd, Francesco Siddi
+
import logging
module_logger = logging.getLogger(__name__)
-'''
import bpy
import blf
-
from . import core
+from bpy.types import (
+ Operator,
+ Panel,
+ )
+
+"""
+ If view name display is enabled,
+ it will check periodically if the view has been modified
+ since last set.
+ get_preferences_timer() is the time in seconds between these checks.
+ It can be increased, if the view become sluggish
+ It is set in the add-on preferences
+"""
+
-# If view name display is enabled,
-# it will check periodically if the view has been modified
-# since last set.
-# VIEW_MODIFIED_TIMER is the time in seconds between these checks.
-# It can be increased, if the view become sluggish
-VIEW_MODIFIED_TIMER = 1
-# TODO: expose refresh rate to ui???
-# TODO: ui for import/export
+# Utility function get_preferences_timer for update of 3d view draw
+def get_preferences_timer():
+ # replace the key if the add-on name changes
+ # TODO: expose refresh rate to ui???
+ addon = bpy.context.user_preferences.addons["stored_views"]
+ timer_update = (addon.preferences.view_3d_update_rate if addon else False)
+
+ return timer_update
def init_draw(context=None):
- if context == None:
+ if context is None:
context = bpy.context
+
if "stored_views_osd" not in context.window_manager:
context.window_manager["stored_views_osd"] = False
+
if not context.window_manager["stored_views_osd"]:
context.window_manager["stored_views_osd"] = True
bpy.ops.stored_views.draw()
def _draw_callback_px(self, context):
+ if context.area and context.area.type == 'VIEW_3D':
+ r_width = text_location = context.region.width
+ r_height = context.region.height
+ font_id = 0 # TODO: need to find out how best to get font_id
- r_width = context.region.width
- r_height = context.region.height
- font_id = 0 # TODO: need to find out how best to get font_id
+ blf.size(font_id, 11, context.user_preferences.system.dpi)
+ text_size = blf.dimensions(0, self.view_name)
- blf.size(font_id, 11, 72)
- text_size = blf.dimensions(0, self.view_name)
+ # compute the text location
+ text_location = 0
+ overlap = context.user_preferences.system.use_region_overlap
+ if overlap:
+ for region in context.area.regions:
+ if region.type == "UI":
+ text_location = r_width - region.width
- text_x = r_width - text_size[0] - 10
- text_y = r_height - text_size[1] - 8
- blf.position(font_id, text_x, text_y, 0)
- blf.draw(font_id, self.view_name)
+ text_x = text_location - text_size[0] - 10
+ text_y = r_height - text_size[1] - 8
+ blf.position(font_id, text_x, text_y, 0)
+ blf.draw(font_id, self.view_name)
-class VIEW3D_stored_views_draw(bpy.types.Operator):
+class VIEW3D_stored_views_draw(Operator):
bl_idname = "stored_views.draw"
bl_label = "Show current"
bl_description = "Toggle the display current view name in the view 3D"
@@ -56,7 +79,7 @@ class VIEW3D_stored_views_draw(bpy.types.Operator):
VIEW3D_stored_views_draw._handle = bpy.types.SpaceView3D.draw_handler_add(
_draw_callback_px, (self, context), 'WINDOW', 'POST_PIXEL')
VIEW3D_stored_views_draw._timer = \
- context.window_manager.event_timer_add(VIEW_MODIFIED_TIMER, context.window)
+ context.window_manager.event_timer_add(get_preferences_timer(), context.window)
@staticmethod
def handle_remove(context):
@@ -69,22 +92,22 @@ class VIEW3D_stored_views_draw(bpy.types.Operator):
@classmethod
def poll(cls, context):
- #return context.mode=='OBJECT'
+ # return context.mode == 'OBJECT'
return True
def modal(self, context, event):
if context.area:
context.area.tag_redraw()
- if not context.area.type or context.area.type != "VIEW_3D":
+ if not context.area or context.area.type != "VIEW_3D":
return {"PASS_THROUGH"}
data = core.DataStore()
stored_views = context.scene.stored_views
if len(data.list) > 0 and \
- data.current_index >= 0 and \
- not stored_views.view_modified:
+ data.current_index >= 0 and \
+ not stored_views.view_modified:
if not stored_views.view_modified:
sv = data.list[data.current_index]
@@ -100,15 +123,18 @@ class VIEW3D_stored_views_draw(bpy.types.Operator):
elif data.mode == 'DISPLAY':
is_modified = core.Display.is_modified(context, sv)
if is_modified:
-# module_logger.debug('view modified - index: %s name: %s' % (data.current_index, sv.name))
+ module_logger.debug(
+ 'view modified - index: %s name: %s' % (data.current_index, sv.name)
+ )
self.view_name = ""
stored_views.view_modified = is_modified
- return {"PASS_THROUGH"}
+ return {"PASS_THROUGH"}
else:
-# module_logger.debug('exit')
+ module_logger.debug('exit')
context.window_manager["stored_views_osd"] = False
VIEW3D_stored_views_draw.handle_remove(context)
+
return {'FINISHED'}
def execute(self, context):
@@ -116,20 +142,21 @@ class VIEW3D_stored_views_draw(bpy.types.Operator):
self.view_name = ""
VIEW3D_stored_views_draw.handle_add(self, context)
context.window_manager.modal_handler_add(self)
- return {"RUNNING_MODAL"}
+ return {"RUNNING_MODAL"}
else:
- self.report({"WARNING"}, "View3D not found, can't run operator")
+ self.report({"WARNING"}, "View3D not found. Operation Cancelled")
+
return {"CANCELLED"}
-class VIEW3D_PT_properties_stored_views(bpy.types.Panel):
+class VIEW3D_PT_properties_stored_views(Panel):
bl_label = "Stored Views"
bl_space_type = "VIEW_3D"
bl_region_type = "UI"
def draw(self, context):
-# logger = logging.getLogger('%s Properties panel' % __name__)
+ self.logger = logging.getLogger('%s Properties panel' % __name__)
layout = self.layout
if bpy.ops.view3d.stored_views_initialize.poll():
@@ -141,7 +168,7 @@ class VIEW3D_PT_properties_stored_views(bpy.types.Panel):
# UI : mode
col = layout.column(align=True)
col.prop_enum(stored_views, "mode", 'VIEW')
- row = layout.row()
+ row = layout.row(align=True)
row.operator("view3d.camera_to_view", text="Camera To view")
row.operator("stored_views.newcamera", text="New Camera To view")
@@ -154,6 +181,13 @@ class VIEW3D_PT_properties_stored_views(bpy.types.Panel):
row = layout.row()
row.operator("stored_views.save").index = -1
+ # IO Operators
+ if core.get_preferences():
+ row = layout.row(align=True)
+ row.operator("stored_views.import_from_scene", text="Import from Scene")
+ row.operator("stored_views.import", text="", icon="IMPORT")
+ row.operator("stored_views.export", text="", icon="EXPORT")
+
data_store = core.DataStore()
list = data_store.list
# UI : items list
@@ -178,7 +212,7 @@ class VIEW3D_PT_properties_stored_views(bpy.types.Panel):
else:
icon_string = "OUTLINER_DATA_CAMERA"
if mode == 'LAYERS':
- if list[i].lock_camera_and_layers == True:
+ if list[i].lock_camera_and_layers is True:
icon_string = 'SCENE_DATA'
else:
icon_string = 'RENDERLAYERS'
@@ -186,6 +220,8 @@ class VIEW3D_PT_properties_stored_views(bpy.types.Panel):
shade = list[i].viewport_shade
if shade == 'TEXTURED':
icon_string = 'TEXTURE_SHADED'
+ if shade == 'MATERIAL':
+ icon_string = 'MATERIAL_DATA'
elif shade == 'SOLID':
icon_string = 'SOLID'
elif shade == 'WIREFRAME':
@@ -197,7 +233,7 @@ class VIEW3D_PT_properties_stored_views(bpy.types.Panel):
# stored view row
subrow = box.row(align=True)
# current view indicator
- if data_store.current_index == i and context.scene.stored_views.view_modified == False:
+ if data_store.current_index == i and context.scene.stored_views.view_modified is False:
subrow.label(text="", icon='SMALL_TRI_RIGHT_VEC')
subrow.operator("stored_views.set",
text="", icon=icon_string).index = i