3 дек. 2013 г.

Dynamic Visible - Final

Ну вот и всё.
Дружно тестим и исправляем баги, если найдутся.


Сам addon можно получить тут или тут

Ну или копируйте ниже:



# ##### 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####

bl_info = {
    "name": "Dynamic Visible",
    "author": "Maxim Seliverstoff",
    "version": (0, 0, 1),
    "blender": (2, 68, 0),
    "location": "Camera > Dynamic Visible",
    "description": "Controls the visibility of objects through a picture frame camera",
    "warning": "",
    "wiki_url": "",
    "tracker_url": "",
    "category": "Object"}

import bpy, bl_ui
from bpy.types import Operator
from bpy.types import Panel, Menu
from rna_prop_ui import PropertyPanel
from bpy_extras.object_utils import world_to_camera_view

from bpy.app.handlers import persistent


@persistent
def update_handler(self):
    cam_obj = bpy.data.cameras[self.camera.name]
    cam = self.camera
    dv = cam_obj.dynamic_visible
    if dv.update:
        FindVisible(cam, cam_obj, dv)

bpy.app.handlers.frame_change_post.append(update_handler)

CameraButtonsPanel = bl_ui.properties_data_camera.CameraButtonsPanel

def updateDynamicVisible(self, context):
    cam_obj = bpy.data.objects[context.object.name]
    cam = context.camera
    dv = cam.dynamic_visible
    if dv.update:
        FindVisible(cam_obj, cam, dv)

class DynamicVisibleSettings(bpy.types.PropertyGroup):
    use = bpy.props.BoolProperty(
                        name        = "Use Properties",
                        description = "Use Properties Description",
                        default     = False
                        )

    raise_frame = bpy.props.FloatProperty(
                        name        = "Raise Frame",
                        description = "Increases the frame, the larger the value, \
                                       the more objects will be visible",
                        default     = 0.0,
                        min         = 0.0,
                        max         = 10.0,
                        soft_min    = 0.001,
                        soft_max    = 10.0,
                        step        = 5,
                        precision   = 3,
                        update      = updateDynamicVisible
                        )
                                             
    mode_type = bpy.props.EnumProperty(
                        items = [('LAYER',
                                  'Move to Layers',
                                  'Objects will be moved to another layer, each new frame'),
                               
                                 ('HIDE',
                                  'Hide Render',
                                  'Objects will be disconnected from the rendering')],
                             
                        name        = "Mode Type",
                        description = "The method by which objects are hidden",
                        default     = "LAYER"
                        )                                

    update = bpy.props.BoolProperty(
                        name        = "Auto Update",
                        description = "Select if you want to automatically hide objects",
                        default     = False
                        )
                     
    hide_view = bpy.props.BoolProperty(
                        name        = "Hide View",
                        description = "Hide objects in View",
                        default     = True
                        )
                     
    hide_render = bpy.props.BoolProperty(
                        name        = "Hide Render",
                        description = "Hide objects in Render",
                        default     = True
                        )
                     
    use_animation = bpy.props.BoolProperty(
                        name        = "Animation",
                        description = "Hide objects in Render",
                        default     = True
                        )
                     
    animated = bpy.props.BoolProperty(
                        name = "anim yes",
                        default     = False
    )                      
                     
    out_layer = bpy.props.BoolVectorProperty(
                        name    = 'Layer Out',
                subtype = 'LAYER',
                size    = 20
)

    include_group = bpy.props.StringProperty(
                        name="Include Group",
                        description="Use only group"
    )
 
    exclude_group = bpy.props.StringProperty(
                        name="Exclude Group",
                        description="Use only group"
    )
 

bpy.utils.register_class(DynamicVisibleSettings)
bpy.types.Camera.dynamic_visible = bpy.props.PointerProperty(type=DynamicVisibleSettings)


class DATA_PT_camera_dynamic_visible(CameraButtonsPanel, Panel):
    COMPAT_ENGINES = {'BLENDER_RENDER', 'VRAY_RENDER', 'CYCLES'}
    bl_label = "Dynamic Visible Setting"
    bl_options = {'DEFAULT_CLOSED'}
 
    def button_event(evt, val):
        print(evt.type)
 
    def draw_header(self, context):
        self.layout.prop(context.camera.dynamic_visible, "use", text="")  
     
    def draw(self, context):
        layout = self.layout
     
        cam = context.camera.dynamic_visible
        layout.active = cam.use
             
        split = layout.split()
        split.prop(cam, "update")      
     

        if cam.update == False:
            split = layout.split()
            split.operator("camera.update_visible", icon="FILE_REFRESH")  


        split = layout.split()
        split.prop(cam, "raise_frame")

        layout.separator()
     
        split = layout.split()
        split.prop(cam, "mode_type", text="")
     
        if cam.mode_type == 'HIDE':
            col= split.column()
            col.prop(cam, "hide_view")
            col.prop(cam, "hide_render")
         
        if cam.mode_type == 'LAYER':
            col= split.column()
            col.prop(cam, "out_layer", text="")

        layout.separator()
        layout.label(text="Include\Exclude objects:")
     
        split = layout.split()
        split.prop_search(cam, 'include_group',
bpy.data,       'groups', text="Include")

        split = layout.split()
        split.prop_search(cam, 'exclude_group',
bpy.data,       'groups', text="Exclude")

        if cam.mode_type == 'HIDE':
     
            layout.separator()
            split = layout.split()
            split.prop(cam, "use_animation")

     
            if cam.use_animation:
                split = layout.split()
                split.active = not cam.animated
                split.operator("camera.create_animation_visible", icon="ANIM_DATA")
         
                split = layout.split()
                split.active = cam.animated
                split.operator("camera.clean_animation_visible", icon="CANCEL")


class ManualUpdate(bpy.types.Operator):
    bl_idname = "camera.update_visible"
    bl_label = "Update Current Frame"

    def execute(self, context):
        cam_obj = bpy.data.objects[context.object.name]
        cam = context.camera
        dv = cam.dynamic_visible
        FindVisible(cam_obj, cam, dv)
        return {'FINISHED'}

bpy.utils.register_class(ManualUpdate)


class CreateAnimation(bpy.types.Operator):
    bl_idname = "camera.create_animation_visible"
    bl_label = "Bake all frame to Animation"
 
    def __init__(self):
        bpy.context.window_manager.progress_begin(0,99)
        scene = bpy.context.scene
        self.start = scene.frame_start + 1
        self.end = scene.frame_end + 1
        self.step = scene.frame_step
        self.i = 0
        self._timer = None


    def __del__(self):
        bpy.context.window_manager.progress_end()

    def execute(self, context):
        self._timer = context.window_manager.event_timer_add(0.1, context.window)
        self.i += 1
        progress_step = self.end-self.start/100
        bpy.context.window_manager.progress_update(self.i/progress_step)
        cam_obj = bpy.data.objects[context.object.name]
        cam = context.camera
        dv = cam.dynamic_visible
     
        bpy.context.scene.frame_set(self.i)
        FindVisible(cam_obj, cam, dv, anim=True)
     
     
    def modal(self, context, event):
        cam = context.camera
        dv = cam.dynamic_visible
     
        if dv.animated:
            return {'FINISHED'}
     
        if self.i > self.end-self.start:
            dv.animated = True
            return {'FINISHED'}
     
        if event.type in ('RIGHTMOUSE', 'ESC'):
             return self.cancel(context)

        self.execute(context)

        return {'RUNNING_MODAL'}
 
    def cancel(self, context):
        context.window_manager.event_timer_remove(self._timer)
        bpy.context.window_manager.progress_end()
        return {'CANCELLED'}

    def invoke(self, context, event):
        context.window_manager.modal_handler_add(self)
        return {'RUNNING_MODAL'}


bpy.utils.register_class(CreateAnimation)

class CleanAnimation(bpy.types.Operator):
    bl_idname = "camera.clean_animation_visible"
    bl_label = "Clean Animation"

    def execute(self, context):
        ng = bpy.data.groups["DynamicVisibleObjects"]
        cam = context.camera
        dv = cam.dynamic_visible
        dv.animated = False
        for obj in ng.objects:
            anim_data = obj.animation_data

            for fcurve in anim_data.action.fcurves:
                if fcurve.data_path in ['hide', 'hide_render']:
                    anim_data.action.fcurves.remove(fcurve)
     
        return {'FINISHED'}

bpy.utils.register_class(CleanAnimation)

def FindVisible(cam_obj, cam, dv, anim=False):
 
    non_trace = [
            "CAMERA",
            "LAMP",
            "CURVE",
            "EMPTY",
            "LATTICE"]
 
    scene = bpy.context.scene
    fr = scene.frame_current
 
    if len(dv.include_group) > 0:
        obj_list = bpy.data.groups[dv.include_group].objects
    else:
        obj_list = bpy.data.objects
 
    if len(dv.exclude_group) > 0:
        obj_exclude = bpy.data.groups[dv.exclude_group].objects
    else:
        obj_exclude = []
 
    for ob in obj_list:
        if ob.type in non_trace or ob.name in obj_exclude:
            continue
        else:
            frame = world_to_camera_view(scene, cam_obj, ob.location)
            xy_min = 0 - dv.raise_frame
            xy_max = 1 + dv.raise_frame
            if frame[0] >=xy_min and frame[0]<=xy_max and frame[1]>=xy_min and frame[1]<=xy_max and frame[2]>0:
                if dv.mode_type == 'HIDE':
                    if dv.hide_view:
                        ob.hide = not dv.hide_view
                        if anim and check_key(ob, 'hide', fr, ob.hide):
                            add_anim_group(ob)
                            ob.keyframe_insert(data_path='hide', frame=fr)
                    if dv.hide_render:
                        ob.hide_render = not dv.hide_render
                        if anim  and check_key(ob, 'hide_render', fr, ob.hide_render):
                            add_anim_group(ob)
                            ob.keyframe_insert(data_path='hide_render', frame=fr)
                elif dv.mode_type == 'LAYER':
                    ob.layers = scene.layers
            else:
                if dv.mode_type == 'HIDE':
                    ob.hide = dv.hide_view
                    if anim and check_key(ob, 'hide', fr, ob.hide):
                        add_anim_group(ob)
                        ob.keyframe_insert(data_path='hide', frame=fr)
                    ob.hide_render = dv.hide_render
                    if anim and check_key(ob, 'hide_render', fr, ob.hide_render):
                        add_anim_group(ob)
                        ob.keyframe_insert(data_path='hide_render', frame=fr)
                elif dv.mode_type == 'LAYER':
                    ob.layers = dv.out_layer


def add_anim_group(obj):
    scene = bpy.context.scene
    if not "DynamicVisibleObjects" in bpy.data.groups:
            ng = bpy.data.groups.new("DynamicVisibleObjects")
    else:
        ng = bpy.data.groups["DynamicVisibleObjects"]
         
    if obj.name in ng.objects:
        return False
    else:
        ng.objects.link(obj)
        return True

def check_key(obj, path, fr, c_val, index=0):
 
    out = True
    if c_val:
        c_val = 1.0
    else:
        c_val = 0.0
     
    anim_data = obj.animation_data

    if anim_data.action:
        for fcurve in anim_data.action.fcurves:
            if fcurve.data_path == path:
                if fcurve.evaluate(fr-1) == c_val:
                    out = False
                else:
                    out = True
        return out
    else:
        return True  
     
def register():
    bpy.utils.register_class(DATA_PT_camera_dynamic_visible)

def unregister():
    bpy.utils.unregister_class(DATA_PT_camera_dynamic_visible)

if __name__ == "__main__":
    register()

2 комментария:

  1. А тестирование эффективности производилось? Сколько времени/памяти удаётся сэкономить?

    ОтветитьУдалить
    Ответы
    1. Пока был очень беглый тест, но он показал, что разница ощутима только на больших нагрузках.
      Ну вот в этой сцене примерно 15 сек. до и 13 после. А если увеличивать кол-во объектов, то разрыв растет в процентном отношении.
      Чуть позже сделаю табличку более подробную, самому интересно.

      Удалить