# ##### 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 LICENCE BLOCK #####


bl_info = {
    "name": "My Big Button",
    "author": "Hokuss",
    "version": (0, 2, 5),
    "blender": (2, 80, 0),
    "location": "PROPERTIES WINDOW > Render & 3D View > UI > Render Tab & 3D View header",
    "description": "Render Button & Camera Manager for Blender 2.80",
    "warning": "",
    "wiki_url": "https://blenderartists.org/t/big-render-button-for-blender-2-80/1159414",
    "category": "Render",
    }

import bpy
import os
from bl_ui.utils import PresetPanel
import time, datetime
from bpy.utils import register_class, unregister_class

from bpy.types import (
    Operator,
    Panel,Scene, PropertyGroup,Object,Menu, Panel, UIList
)
from bpy.props import (IntProperty,
                       FloatProperty,
                       StringProperty,
                       EnumProperty,
                       PointerProperty,
                       )
#////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
#SETTINGS//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 

class MYBIGBUTTON_Settings(PropertyGroup):
    
    switchPropertiesRenderButton_prop : bpy.props.BoolProperty(
        name="QuickSettings",
        description="Toggle Quick Settings",
        default = False)
   
    switchStillAnim_prop : bpy.props.BoolProperty(
        name="Animation",
        description="Activate Animation Rendering",
        default = False)
        
    switchRenderRotation_prop : bpy.props.BoolProperty(
        name="Rotation",
        description="Toggle Landscape / Portrait",
        default = False)
        
#    switchCamOrtho_prop : bpy.props.BoolProperty(
#        name="Persp/Ortho",
#        description="Toggle Ortho",
#        default = False)
                
    switchQuickSettings_prop : bpy.props.BoolProperty(
        name="QuickSettings",
        description="Toggle Quick Settings",
        default = False)
        
    switchRenderSelection: bpy.props.BoolProperty(
        name="Cameras Selection ",
        description="Toglle to Cameras Selection for Batch Rendering",
        default = False)
        
    SwitchPropertiesBatch: bpy.props.BoolProperty(
        name="Batch Render Properties ",
        description="Toglle Batch Rendering box Properties",
        default = False)
        
    saveInBlendFolder: bpy.props.BoolProperty(
        name="Save in blend folder",
        description="Save Batch Render in blend folder",
        default = False)        
        
        
    storeRenderInSlots: bpy.props.BoolProperty(
        name="Store in Slots",
        description="Store Cameras Output in Render Slots",
        default = False)        
               

    Default_HRes_prop : bpy.props.IntProperty(
        name="DHres",
        description="Horizontal Default Dimension",
        default = 1920) 
        
    Default_VRes_prop : bpy.props.IntProperty(
        name="DHres",
        description="Vertical Default Dimension",
        default = 1080)  

    Default_HPixRes_prop : bpy.props.IntProperty(
        name="DHres",
        description="Horizontal Default Dimension",
        default = 1) 
        
    Default_VPixRes_prop : bpy.props.IntProperty(
        name="DHres",
        description="Vertical Default Dimension",
        default = 1) 


class MYBIGBUTTON_obj_Settings(PropertyGroup):
    
    Custom_Cam_prop : bpy.props.BoolProperty(
        name="Animation",
        description="Store Custom Resolution",
        default = False)
        
    Custom_Camtrack_prop : bpy.props.BoolProperty(
        name="Track",
        description="Track",
        default = False) 

    Custom_CamRes_prop : bpy.props.BoolProperty(
        name="Custom Resolution",
        description="Track",
        default = False) 

    Custom_CamRender_prop : bpy.props.BoolProperty(
        name="Add This Camera",
        description="Add in batch rendering list",
        default = False)
        
#    Custom_CamView_prop : bpy.props.BoolProperty(
#        name="Toggle view On/Off",
#        description="Toggle view On/Off",
#        default = False)        
        
        
    Custom_CamHRes_prop : bpy.props.IntProperty(
        name="Hres",
        description="Track",
        default = 1920) 
        
    Custom_CamVRes_prop : bpy.props.IntProperty(
        name="Vres",
        description="Track",
        default = 1080) 
   
    Custom_CamHPixRes_prop : bpy.props.IntProperty(
        name="Hres",
        description="Track",
        default = 1) 
        
    Custom_CamVPixRes_prop : bpy.props.IntProperty(
        name="Vres",
        description="Track",
        default = 1) 
    
#//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////        
#Function /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
   
def ShowMessageBox(message = "", title = "Message Box", icon = 'INFO'):
    def draw(self, context):
        self.layout.label(text=message)

    bpy.context.window_manager.popup_menu(draw, title = title, icon = icon)                  



#////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
#OPERATOR/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////   

# ADD CAMERA ##################################################################################
class SCENECAMERA_OT_Add(Operator):
    bl_idname      = "cameramanager.add_scene_camera"
    bl_label       = "add Camera"
    bl_description = "Add Camera"
    #bl_options = {'UNDO'}    

    hide_others = False  
    
    def execute(self, context): 
        
        scene = bpy.context.scene           
        rd    = scene.render
        
        #Store active collection before add Camera
        Active_Coll = bpy.context.view_layer.active_layer_collection 

        # Make Master Collection active before add camera
        context.view_layer.active_layer_collection = context.view_layer.layer_collection

        bpy.ops.object.camera_add() 
                
        bpy.context.object.data.show_name = True
        bpy.context.object.show_name = True   
        
        #Restore collection active before adding camera
        bpy.context.view_layer.active_layer_collection = Active_Coll  

    ###Align to view last camera added  
        chosen_camera = context.active_object
        scene = context.scene

        scene.camera = chosen_camera
        
        bpy.context.space_data.camera = bpy.data.objects[chosen_camera.name] 
        
        bpy.ops.object.select_all(action='DESELECT')
        chosen_camera.select_set(state = True)
        
        # trick to prevent error if align camera to view in camera view mode!
        bpy.ops.view3d.view_persportho()
        bpy.ops.view3d.view_persportho()        
        
        bpy.ops.view3d.camera_to_view()     
    
        return {'FINISHED'}


# ACTIV & PREVIEW CHOSEN CAMERA ##################################################################################
class SCENECAMERA_OT_ActivPreview(Operator):
    bl_idname      = "cameramanager.activpreview_scene_camera"
    bl_label       = "Preview Camera"
    bl_description = "Active & Preview Camera"
    #bl_options = {'UNDO'}    

    CamView : bpy.props.BoolProperty(default = False) 
    
    def execute(self, context):

        scene         = context.scene
        chosen_camera = context.active_object

        scene.camera  = chosen_camera
        render        = scene.render
        cs            = chosen_camera.RBTab_obj_Settings
        rs            = scene.RBTab_Settings        
        marker_list   = context.scene.timeline_markers 
               
        for marker in marker_list:
            if marker.camera == scene.camera:
                scene.frame_current = marker.frame
        
        if cs.Custom_CamRes_prop == True:                 
            render.resolution_x   = cs.Custom_CamHRes_prop       
            render.resolution_y   = cs.Custom_CamVRes_prop
            render.pixel_aspect_x = cs.Custom_CamHPixRes_prop
            render.pixel_aspect_y = cs.Custom_CamVPixRes_prop             
        else :
            render.resolution_x   = rs.Default_HRes_prop       
            render.resolution_y   = rs.Default_VRes_prop
            render.pixel_aspect_x = rs.Default_HPixRes_prop
            render.pixel_aspect_y = rs.Default_VPixRes_prop                    
        
        bpy.context.view_layer.objects.active = chosen_camera
                                       
    #ACTIV & PREVIEW CHOSEN CAMERA                             
        bpy.ops.object.select_all(action='DESELECT')
        chosen_camera.select_set(state = True)       
        bpy.context.space_data.camera = bpy.data.objects[chosen_camera.name]
        
        print(self.CamView)
               
        for area in bpy.context.screen.areas:
            if area.type == 'VIEW_3D':
                context.area.spaces[0].region_3d.view_perspective = 'CAMERA'
                break        
        return {'FINISHED'}

        
                
# ALIGN CHOSEN CAMERA TO ACTIV VIEW ##################################################################################
class SCENECAMERA_OT_AlignView(Operator):
    bl_idname      = "cameramanager.alignview_scene_camera"
    bl_label       = "Align Camera View to Activ View"
    #bl_options = {'UNDO'}
    bl_description = (" \u2022 In perpective View: Align to View \n"
                      " \u2022 In Camera View: Align to Cursor") 

    
    def execute(self, context):
        scene         = context.scene
        chosen_camera = context.active_object
        scene.camera  = chosen_camera
        render        = scene.render
        cs            = chosen_camera.RBTab_obj_Settings
        rs            = scene.RBTab_Settings                
        marker_list   = context.scene.timeline_markers 
               
        for marker in marker_list:
            if marker.camera == scene.camera:
                scene.frame_current = marker.frame
        
        if cs.Custom_CamRes_prop == True:
            render.resolution_x   = cs.Custom_CamHRes_prop       
            render.resolution_y   = cs.Custom_CamVRes_prop
            render.pixel_aspect_x = cs.Custom_CamHPixRes_prop
            render.pixel_aspect_y = cs.Custom_CamVPixRes_prop            
        else :
            render.resolution_x   = rs.Default_HRes_prop       
            render.resolution_y   = rs.Default_VRes_prop
            render.pixel_aspect_x = rs.Default_HPixRes_prop
            render.pixel_aspect_y = rs.Default_VPixRes_prop             
        
        object_to_track = bpy.context.selected_objects
        bpy.context.view_layer.objects.active = chosen_camera    
                                    
        area = next(area for area in bpy.context.screen.areas if area.type == 'VIEW_3D')
                
    #ALIGN CHOSEN CAMERA TO ACTIV VIEW        
                
        # Align to 3d Cursor IF in camera view       
        if area.spaces[0].region_3d.view_perspective == 'CAMERA':
            if len(chosen_camera.constraints) > 0:
                CamTarget = chosen_camera.constraints[0].target
                bpy.ops.object.select_all(action='DESELECT')
                bpy.data.objects[CamTarget.name].select_set(state = True)
                bpy.ops.view3d.snap_selected_to_cursor(use_offset=False)
                bpy.ops.object.select_all(action='DESELECT')
                chosen_camera.select_set(state = True)

            else:            
                Active_Coll = bpy.context.view_layer.active_layer_collection                 
                context.view_layer.active_layer_collection = context.view_layer.layer_collection
                
                bpy.ops.object.empty_add(type='PLAIN_AXES')
                                    
                bpy.context.view_layer.active_layer_collection = Active_Coll                 
                bpy.context.object.name = "target"
                object_to_track = bpy.context.selected_objects
                chosen_camera.select_set(state = True)
                scene.camera = chosen_camera 
                                                                                 
                bpy.context.view_layer.objects.active = bpy.data.objects[object_to_track[0].name]                        
                bpy.ops.object.track_set(type='TRACKTO')
                bpy.ops.object.track_clear(type='CLEAR_KEEP_TRANSFORM')
                bpy.ops.object.select_all(action='DESELECT')
                bpy.data.objects["target"].select_set(state = True)                
                bpy.ops.object.delete(use_global=False, confirm=False)
                bpy.ops.object.select_all(action='DESELECT')
                chosen_camera.select_set(state = True)

        # Align to activ View IF NOT in Camera View                
        else:                        
            bpy.ops.object.select_all(action='DESELECT')
            chosen_camera.select_set(state = True)
            bpy.ops.view3d.view_persportho()
            bpy.ops.view3d.view_persportho()            
            bpy.ops.view3d.camera_to_view()
                
        bpy.context.view_layer.objects.active = chosen_camera 
        bpy.context.space_data.camera = bpy.data.objects[chosen_camera.name]
               
        for area in bpy.context.screen.areas:
            if area.type == 'VIEW_3D':
                context.area.spaces[0].region_3d.view_perspective = 'CAMERA'
                break        
        return {'FINISHED'}


# ALIGN CHOSEN CAMERA TO SELECTED OBJECT ##################################################################################
class SCENECAMERA_OT_AlignObj(Operator):
    bl_idname      = "cameramanager.alignobj_scene_camera"
    bl_label       = "Align Camera View to Object(s)"
    #bl_options = {'UNDO'}    
    bl_description = (" \u2022 Object(s) Selected: Align to Object(s) \n"
                      " \u2022 No Object Selected: View All") 
    
    def execute(self, context):
        scene         = context.scene
        chosen_camera = context.active_object
        scene.camera  = chosen_camera        
        render        = scene.render
        cs            = chosen_camera.RBTab_obj_Settings
        rs            = scene.RBTab_Settings              
        marker_list   = context.scene.timeline_markers
                
        for marker in marker_list:
            if marker.camera == scene.camera:
                scene.frame_current = marker.frame        
          
        
        if cs.Custom_CamRes_prop == True:
            render.resolution_x   = cs.Custom_CamHRes_prop       
            render.resolution_y   = cs.Custom_CamVRes_prop
            render.pixel_aspect_x = cs.Custom_CamHPixRes_prop
            render.pixel_aspect_y = cs.Custom_CamVPixRes_prop            
            
        else :
            render.resolution_x   = rs.Default_HRes_prop       
            render.resolution_y   = rs.Default_VRes_prop
            render.pixel_aspect_x = rs.Default_HPixRes_prop
            render.pixel_aspect_y = rs.Default_VPixRes_prop            
            
            
        bpy.context.view_layer.objects.active = chosen_camera
        object_to_track = bpy.context.selected_objects
                         
    #ALIGN CHOSEN CAMERA TO SELECTED OBJECT
    
        # View All IF no object selected OR current camera selected    
        if len(object_to_track) == 0 or chosen_camera.name == object_to_track[0].name:
            bpy.ops.object.select_all(action='SELECT')
            bpy.ops.view3d.camera_to_view_selected() 

        # View Selected object(s)                 
        else:
            bpy.ops.view3d.camera_to_view_selected()                

        bpy.ops.object.select_all(action='DESELECT')
        chosen_camera.select_set(state = True)
        bpy.context.view_layer.objects.active = chosen_camera  
        bpy.context.space_data.camera = bpy.data.objects[chosen_camera.name]
               
        for area in bpy.context.screen.areas:
            if area.type == 'VIEW_3D':
                context.area.spaces[0].region_3d.view_perspective = 'CAMERA'
                break        
        return {'FINISHED'}
    

# TRACK TO SELECTED OBJECT ################################################################################
### ADD TRACK #############
class SCENECAMERA_OT_AddTrackTo(Operator):
    bl_idname      = "cameramanager.trackto_scene_camera"
    bl_label       = "Track to Object"
    #bl_options = {'UNDO'}    
    bl_description = (" \u2022 Object Selected: Track to Object Selected \n"
                      " \u2022 No Object Selected: Track to New Empty")

    def execute(self, context):

        scene         = context.scene
        chosen_camera = context.active_object
        scene.camera  = chosen_camera
        
        object_to_track = bpy.context.selected_objects
        bpy.context.view_layer.objects.active = chosen_camera
        
        targets = sorted([o for o in scene.objects if o.type == 'EMPTY'], key=lambda o: o.name)
      
    #TRACK TO SELECTED OBJECT 
      
        # IF object selected = none OR = current camera THEN add empty and track to                        
        if len(object_to_track) == 0 or chosen_camera.name == object_to_track[0].name:
            Active_Coll = bpy.context.view_layer.active_layer_collection                 
            context.view_layer.active_layer_collection = context.view_layer.layer_collection
                    
            bpy.ops.object.empty_add(type='PLAIN_AXES')
                    
            bpy.context.view_layer.active_layer_collection = Active_Coll 
            bpy.context.object.name = "t_{0}".format(chosen_camera.name)
                       
            bpy.context.object.show_name = True
            bpy.context.object.show_in_front = True
            object_to_track = bpy.context.selected_objects
                    
            chosen_camera.select_set(state = True)
            scene.camera = chosen_camera 
                                                                                 
            bpy.context.view_layer.objects.active = bpy.data.objects[object_to_track[0].name]                        
            bpy.ops.object.track_set(type='TRACKTO')
            
        #If object selected THEN track to        
        else :
            chosen_camera.select_set(state = True)
            scene.camera = chosen_camera 
                                                                                 
            bpy.context.view_layer.objects.active = bpy.data.objects[object_to_track[0].name]                        
            bpy.ops.object.track_set(type='TRACKTO')
                
        bpy.ops.object.select_all(action='DESELECT')
        chosen_camera.select_set(state = True)
        #print(chosen_camera.constraints[0].target.name)                         
        bpy.context.view_layer.objects.active = chosen_camera                
        bpy.context.space_data.camera = bpy.data.objects[chosen_camera.name]
           
        for area in bpy.context.screen.areas:
            if area.type == 'VIEW_3D':
                context.area.spaces[0].region_3d.view_perspective = 'CAMERA'
                break                        
        return {'FINISHED'} 

### REMOVE TRACK ############# 
class SCENECAMERA_OT_RemoveTrackTo(Operator):
    bl_idname      = "cameramanager.removetrackto_scene_camera"
    bl_label       = "Remove Track to Object"
    #bl_options = {'UNDO'}    
    bl_description = (" \u2022 Click: Clear Track \n"
                      " \u2022 Shift + Click: Clear and Keep Transformation")
    
    @classmethod
    def poll(cls, context):
        return context.active_object is not None

    def invoke(self, context, event):
        scene         = context.scene
        chosen_camera = context.active_object
        scene.camera  = chosen_camera
        
        object_to_track = bpy.context.selected_objects
        bpy.context.view_layer.objects.active = chosen_camera
        
        targets = sorted([o for o in scene.objects if o.type == 'EMPTY'], key=lambda o: o.name)
      
    #REMOVE TRACK TO SELECTED OBJECT   

        CamTarget = chosen_camera.constraints[0].target
        bpy.ops.object.select_all(action='DESELECT')
        chosen_camera.select_set(state = True)
         
        # Shift Click = Clear Keep    
        if event.shift:
            bpy.ops.object.track_clear(type='CLEAR_KEEP_TRANSFORM')
            
        # Click = Clear   
        else:
            bpy.ops.object.track_clear(type='CLEAR')
         
        # Remove Target after Clear Track IF Target Type = Empty and 
        # name starts with = t_
        _tname = CamTarget.name[0:2]        
        if CamTarget.type == 'EMPTY' and _tname == "t_":
            bpy.ops.object.select_all(action='DESELECT')
            bpy.data.objects[CamTarget.name].select_set(state = True)                
            bpy.ops.object.delete(use_global=False, confirm=False)
                    
        bpy.ops.object.select_all(action='DESELECT')
        chosen_camera.select_set(state = True)                         
        bpy.context.view_layer.objects.active = chosen_camera                
        bpy.context.space_data.camera = bpy.data.objects[chosen_camera.name]
           
        for area in bpy.context.screen.areas:
            if area.type == 'VIEW_3D':
                context.area.spaces[0].region_3d.view_perspective = 'CAMERA'
                break                        
        return {'FINISHED'} 
   


# BATCH RENDER All CAMERA ##################################################################################
class SCENECAMERA_OT_BatchRenderAll(Operator):
    bl_idname      = "cameramanager.render_all_camera"
    bl_label       = "Batch Render All Camera"
    bl_description = "Render All Cameras"
   
    _timer      = None
    cameras     = []
    _cameras    = None
    marker_list = None
    stop        = None
    rendering   = None
    path        = "//"
    
    tmarkers : bpy.props.BoolProperty(default = False)

    @classmethod
    def poll(cls, context):
        return context.active_object is not None or context.scene.camera is not None

    def pre(self, dummy):
        self.rendering = True

    def post(self, dummy):
        scene   = bpy.context.scene
        rs      = scene.RBTab_Settings
        img     = bpy.data.images['Render Result']
        
        if scene.frame_current == 0:
            marker_list = scene.timeline_markers
            for m in marker_list:
                if m.camera == scene.camera:
                    scene.timeline_markers.remove(m)  
                          
        if rs.storeRenderInSlots == True:
            img.render_slots.active_index += 1
                   
        self.cameras.pop(0)
        self.rendering = False
                
    def cancelled(self, dummy):
        scene = bpy.context.scene
        if scene.frame_current == 0:
            marker_list = scene.timeline_markers
            for m in marker_list:
                if m.camera == scene.camera:
                    scene.timeline_markers.remove(m)         
        
        self.stop = True

    def execute(self, context):

        self.stop = False
        self.rendering = False
        
        scene   = bpy.context.scene
        rs      = scene.RBTab_Settings
        img     = bpy.data.images['Render Result']
        
        self.marker_list   = context.scene.timeline_markers

        if rs.switchRenderSelection == True :
            if self.tmarkers == True:
                self.cameras = sorted([o.camera.name for o in self.marker_list])
                self.tmarkers = False            
            else:            
                for o in scene.objects:
                    cs = o.RBTab_obj_Settings
                    if o.type == 'CAMERA'and cs.Custom_CamRender_prop == True:
                        self.cameras += sorted([o.name])                    
        else:
            if self.tmarkers == True:
                self.cameras = sorted([o.camera.name for o in self.marker_list])
                self.tmarkers = False            
            else:
                self.cameras = sorted([o.name for o in scene.objects if o.type == 'CAMERA'])                    
                
        if rs.storeRenderInSlots == True:
            if len(img.render_slots) < len(self.cameras):
                _slotToAdd = len(self.cameras)-len(img.render_slots) #+1
                i = 0
                while i < _slotToAdd:
                    i+=1
                    img.render_slots.new()
                                                
        if rs.saveInBlendFolder == False: self.path = bpy.context.scene.render.filepath
        
        bpy.data.images['Render Result'].render_slots.active_index = 0
        
        bpy.app.handlers.render_pre.append(self.pre)
        bpy.app.handlers.render_post.append(self.post)
        bpy.app.handlers.render_cancel.append(self.cancelled)

        self._timer = context.window_manager.event_timer_add(0.5, window=context.window)
        context.window_manager.modal_handler_add(self)

        return {"RUNNING_MODAL"}

    def modal(self, context, event):
        sc = bpy.context.scene
        render = sc.render
        cs = sc.camera.RBTab_obj_Settings
        
        if event.type == 'TIMER': 
            KamRender = False
    
            #Test to avoid render display mode SCREEN. 
            #If is active during this batch render mode, you lose your workspace layout!
            if bpy.context.scene.render.display_mode not in ('AREA', 'NONE', 'WINDOW'):
                #Force AREA mode if chosen. 
                bpy.context.scene.render.display_mode ='AREA'

            if True in (not self.cameras, self.stop is True):                                
                bpy.app.handlers.render_pre.remove(self.pre)
                bpy.app.handlers.render_post.remove(self.post)
                bpy.app.handlers.render_cancel.remove(self.cancelled)
                context.window_manager.event_timer_remove(self._timer)
                sc.frame_current = 1
                sc.render.filepath = self.path

                return {"FINISHED"}

            elif self.rendering is False:                
                if len(self.marker_list) == 0:
                    sc.camera = bpy.data.objects[self.cameras[0]]
                    
                    cs = sc.camera.RBTab_obj_Settings
                    rs = sc.RBTab_Settings
                    
                    if cs.Custom_CamRes_prop == True:                 
                        render.resolution_x   = cs.Custom_CamHRes_prop       
                        render.resolution_y   = cs.Custom_CamVRes_prop
                        render.pixel_aspect_x = cs.Custom_CamHPixRes_prop
                        render.pixel_aspect_y = cs.Custom_CamVPixRes_prop             
                    else :
                        render.resolution_x   = rs.Default_HRes_prop       
                        render.resolution_y   = rs.Default_VRes_prop
                        render.pixel_aspect_x = rs.Default_HPixRes_prop
                        render.pixel_aspect_y = rs.Default_VPixRes_prop                  
                    
                    sc.render.filepath = self.path + self.cameras[0]
                    
                    bpy.ops.render.render("INVOKE_DEFAULT", write_still=True)
                    
                elif len(self.marker_list) >0:
                    for marker in self.marker_list:
                        if self.cameras[0] == marker.camera.name :
                            sc.camera = bpy.data.objects[self.cameras[0]]                            
                            sc.frame_current = marker.frame
                            
                            cs = sc.camera.RBTab_obj_Settings
                            rs = sc.RBTab_Settings
                            
                            if cs.Custom_CamRes_prop == True:                 
                                render.resolution_x   = cs.Custom_CamHRes_prop       
                                render.resolution_y   = cs.Custom_CamVRes_prop
                                render.pixel_aspect_x = cs.Custom_CamHPixRes_prop
                                render.pixel_aspect_y = cs.Custom_CamVPixRes_prop             
                            else :
                                render.resolution_x   = rs.Default_HRes_prop       
                                render.resolution_y   = rs.Default_VRes_prop
                                render.pixel_aspect_x = rs.Default_HPixRes_prop
                                render.pixel_aspect_y = rs.Default_VPixRes_prop                             
                                                        
                            sc.render.filepath = self.path + self.cameras[0]

                            bpy.ops.render.render("INVOKE_DEFAULT", write_still=True)                            
                            
                            KamRender = True
                            break
                        
                    if KamRender == False:
                            
                        sc.camera = bpy.data.objects[self.cameras[0]]
                        chosen_camera = sc.camera
                        
                        cs = sc.camera.RBTab_obj_Settings
                        rs = sc.RBTab_Settings
                        
                        if cs.Custom_CamRes_prop == True:                 
                            render.resolution_x   = cs.Custom_CamHRes_prop       
                            render.resolution_y   = cs.Custom_CamVRes_prop
                            render.pixel_aspect_x = cs.Custom_CamHPixRes_prop
                            render.pixel_aspect_y = cs.Custom_CamVPixRes_prop             
                        else :
                            render.resolution_x   = rs.Default_HRes_prop       
                            render.resolution_y   = rs.Default_VRes_prop
                            render.pixel_aspect_x = rs.Default_HPixRes_prop
                            render.pixel_aspect_y = rs.Default_VPixRes_prop  
                                                  
                        sc.render.filepath = self.path + self.cameras[0]
                        
                        marker = None
                        bpy.context.scene.frame_current = 0                        
                        current_frame = sc.frame_current                                
                        for m in reversed(sorted(filter(lambda m: m.frame <= current_frame,sc.timeline_markers),key=lambda m: m.frame)):
                            marker = m
                            break                        
                        marker_name = chosen_camera.name                        
                        if marker and (marker.frame == current_frame):
                            marker.name = marker_name
                        else:
                            marker = sc.timeline_markers.new(marker_name)                            
                        marker.frame = sc.frame_current
                        marker.camera = chosen_camera
                        marker.select = True
                        for other_marker in [m for m in sc.timeline_markers if m != marker]:
                            other_marker.select = False                      
                                                    
                        bpy.ops.render.render("INVOKE_DEFAULT", write_still=True)                                                

        return {"PASS_THROUGH"}
        
                
# RENDER CHOSEN CAMERA ##################################################################################
class SCENECAMERA_OT_Render(Operator):
    bl_idname      = "cameramanager.render_scene_camera"
    bl_label       = "Render Camera"
    bl_description = "Render this camera"

    KamCurrent = None
    renderFrom : bpy.props.StringProperty(default ='')   
        
    def renderComplete(self, context):
        print("render complete")
        scene = bpy.context.scene
            
        if scene.frame_current == 0:
            marker_list = scene.timeline_markers
            for m in marker_list:
                if m.camera == scene.camera:
                    scene.timeline_markers.remove(m)
                    return {'CANCELLED'}
        else:
           return {'CANCELLED'} 
            
    def renderCancel(self, context):
        print("render stop")
        scene = bpy.context.scene
        if scene.frame_current == 0:
            marker_list = scene.timeline_markers
            for m in marker_list:
                if m.camera == scene.camera:
                    scene.timeline_markers.remove(m)
                    return {'CANCELLED'}
        else:
           return {'CANCELLED'}         

    def execute(self, context):    
        scene         = context.scene        
        chosen_camera = context.active_object 
        print(scene.camera)
        
        render        = scene.render
        
        KamCurrent = None
        
        bpy.app.handlers.render_complete.clear()
        bpy.app.handlers.render_complete.append(self.renderComplete)
        bpy.app.handlers.render_cancel.clear()    
        bpy.app.handlers.render_cancel.append(self.renderCancel)
                                    
        bpy.context.view_layer.objects.active = chosen_camera

        marker_list = context.scene.timeline_markers 
        cameras     = sorted([o for o in scene.objects if o.type == 'CAMERA'],key=lambda o: o.name)
        
         
#|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| 
    
        
        if context.active_object is None:
            if len(cameras) == 0:
                ShowMessageBox("No camera found in this scene !", "Render Error", 'ERROR')
                return {"FINISHED"}    
                            
            elif len(cameras) > 0 and scene.camera is None:
                bpy.ops.object.select_all(action='DESELECT')
                chosen_camera = cameras[0]
                chosen_camera.select_set(state = True)
                scene.camera  = chosen_camera 
                
            elif len(cameras) == 1 :
                bpy.ops.object.select_all(action='DESELECT')
                chosen_camera = cameras[0]
                chosen_camera.select_set(state = True)
                scene.camera  = chosen_camera
                
            elif len(cameras) > 1:
                bpy.ops.object.select_all(action='DESELECT')
                chosen_camera = scene.camera
                chosen_camera.select_set(state = True)
                bpy.context.view_layer.objects.active = chosen_camera
         
        else:        
            if len(cameras) == 0:
                ShowMessageBox("No Camera in this scene !", "Render", 'ERROR')
                return {"FINISHED"}
            
            elif len(cameras) > 0 and scene.camera is None:
                bpy.ops.object.select_all(action='DESELECT')
                chosen_camera = cameras[0]
                chosen_camera.select_set(state = True)
                scene.camera  = chosen_camera 
            
            
            elif len(cameras) == 1 :
                if context.active_object.type != 'CAMERA':
                    print("no camera active")
                    bpy.ops.object.select_all(action='DESELECT')
                    chosen_camera = cameras[0]
                    chosen_camera.select_set(state = True)
                    scene.camera  = chosen_camera
                    
            elif len(cameras) > 1:
                if context.active_object.type != 'CAMERA' :
                    bpy.ops.object.select_all(action='DESELECT')
                    chosen_camera = scene.camera
                    chosen_camera.select_set(state = True)
                    bpy.context.view_layer.objects.active = chosen_camera
                    

#||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||                     
                
        if self.renderFrom == 'TAB':
            scene.camera  = bpy.context.space_data.camera 
            chosen_camera = bpy.context.space_data.camera
        elif self.renderFrom == 'PROPERTIES': scene.camera  = chosen_camera
        elif self.renderFrom == 'CAMANAGER':
            scene.camera  = chosen_camera
            print(scene.camera)
            #return {'FINISHED'} 
            
        
        x  = render.resolution_x
        y  = render.resolution_y 

        cs = chosen_camera.RBTab_obj_Settings
        rs = scene.RBTab_Settings
        
        if cs.Custom_CamRes_prop == True:                 
            render.resolution_x   = cs.Custom_CamHRes_prop       
            render.resolution_y   = cs.Custom_CamVRes_prop
            render.pixel_aspect_x = cs.Custom_CamHPixRes_prop
            render.pixel_aspect_y = cs.Custom_CamVPixRes_prop             
        else :
            render.resolution_x   = rs.Default_HRes_prop       
            render.resolution_y   = rs.Default_VRes_prop
            render.pixel_aspect_x = rs.Default_HPixRes_prop
            render.pixel_aspect_y = rs.Default_VPixRes_prop   
        
        
        if len(marker_list) > 0:
            bpy.ops.object.select_all(action='DESELECT')
            chosen_camera.select_set(state = True)
            bpy.context.view_layer.objects.active = scene.camera             
            
            if self.renderFrom == 'TAB':                
                bpy.context.space_data.camera = bpy.data.objects[scene.camera.name]                    
                for area in bpy.context.screen.areas:
                    if area.type == 'VIEW_3D':
                        context.area.spaces[0].region_3d.view_perspective = 'CAMERA'
                        break 
                                                         
            for marker in marker_list:
                if chosen_camera == marker.camera:
                    scene.camera  = marker.camera                    
                    scene.frame_current = marker.frame
                    bpy.ops.render.render('INVOKE_DEFAULT')
                    return {'FINISHED'} 
                 
            marker = None
            
            scene.frame_current = 0
            
            current_frame = scene.frame_current
                    
            for m in reversed(sorted(filter(lambda m: m.frame <= current_frame,scene.timeline_markers),key=lambda m: m.frame)):
                marker = m
                break
            
            marker_name = scene.camera.name
            
            if marker and (marker.frame == current_frame):
                marker.name = marker_name
            else:
                marker = scene.timeline_markers.new(marker_name)
                
            marker.frame  = scene.frame_current
            marker.camera = scene.camera
            marker.select = True

            for other_marker in [m for m in scene.timeline_markers if m != marker]:
                other_marker.select = False
                 
            bpy.ops.render.render('INVOKE_DEFAULT')

        elif len(marker_list) == 0 :
            print(self.renderFrom)                
            bpy.ops.object.select_all(action='DESELECT')
            chosen_camera.select_set(state = True)
            bpy.context.view_layer.objects.active = scene.camera 
           
            if self.renderFrom in ('TAB', 'CAMANAGER'):
                bpy.context.space_data.camera = bpy.data.objects[scene.camera.name]       
                for area in bpy.context.screen.areas:
                    if area.type == 'VIEW_3D':
                        context.area.spaces[0].region_3d.view_perspective = 'CAMERA'
                        break  
                                            
            bpy.ops.render.render('INVOKE_DEFAULT') 
                           
        return {'FINISHED'}    
                                       

# ADD CAMERA MARKER ##################################################################################
class SCENECAMERA_OT_AddMarker(Operator):
    bl_idname      = "cameramanager.add_camera_marker"
    bl_label       = "Add Camera Marker"
    bl_description = "Add a timeline marker bound to this camera"
    #bl_options = {'UNDO'}    

    def execute(self, context):
        chosen_camera = context.active_object
        scene         = context.scene
        current_frame = scene.frame_current
        marker        = None
        
        for m in reversed(sorted(filter(lambda m: m.frame <= current_frame,scene.timeline_markers),key=lambda m: m.frame)):
            marker = m
            break

        marker_name = chosen_camera.name
        
        if marker and (marker.frame == current_frame):
            marker.name = marker_name
        else:
            marker = scene.timeline_markers.new(marker_name)
            
        marker.frame  = scene.frame_current
        marker.camera = chosen_camera
        marker.select = True

        for other_marker in [m for m in scene.timeline_markers if m != marker]:
            other_marker.select = False
            
        return {'FINISHED'}


# REMOVE CAMERA MARKER ##################################################################################
class SCENECAMERA_OT_removeMarker(Operator):
    bl_idname = "cameramanager.remove_camera_marker"
    bl_label = "Remove Camera Marker"
    bl_description = "Remove timeline marker"
    #bl_options = {'UNDO'}    

    def execute(self, context):
        scene          = context.scene
        chosen_camera  = context.active_object
        scene.camera   = chosen_camera
        marker_list    = context.scene.timeline_markers
       
        for marker in marker_list:
            if marker.camera == scene.camera:
                scene.camera        = marker.camera
                scene.frame_current = marker.frame
                scene.timeline_markers.remove(marker)                
                
        bpy.ops.object.select_all(action='DESELECT')
        scene.camera.select_set(state = True)
        bpy.context.view_layer.objects.active = scene.camera  
        bpy.context.space_data.camera = bpy.data.objects[scene.camera.name]
               
        for area in bpy.context.screen.areas:
            if area.type == 'VIEW_3D':
                context.area.spaces[0].region_3d.view_perspective = 'CAMERA'
                break        
                
        return {'FINISHED'}

    
# REMOVE CAMERA ##################################################################################    
class SCENECAMERA_OT_Remove(Operator):
    bl_idname      = "cameramanager.del_scene_camera"
    bl_label       = "Remove Scene Camera"
    bl_description = "Remove this camera"
    #bl_options = {'UNDO'}    

    def execute(self, context):
        chosen_camera = context.active_object
        scene         = context.scene
        marker_list   = context.scene.timeline_markers
                
        scene.camera = chosen_camera
        
        if len(marker_list)>0:
            for marker in marker_list:
                if marker.camera == scene.camera:
                    scene.camera        = marker.camera
                    scene.frame_current = marker.frame
                    scene.timeline_markers.remove(marker) 
        
        if len(chosen_camera.constraints) >0:
            CamTarget = chosen_camera.constraints[0].target
            _tname = CamTarget.name[0:2]     
            if CamTarget.type == 'EMPTY' and _tname == "t_":
                bpy.ops.object.select_all(action='DESELECT')
                bpy.data.objects[CamTarget.name].select_set(state = True)                
                bpy.ops.object.delete(use_global=False, confirm=False)           
                                        
        scene.camera = chosen_camera
        bpy.ops.object.select_all(action='DESELECT')
        chosen_camera.select_set(state = True)
        bpy.ops.object.delete(use_global=False, confirm=False)        
        return {'FINISHED'}


# TOGGLE RENDER ORIENTATION ##################################################################################
class MYBIGBUTTONTAB_OT_toggle_orientation(Operator):
    bl_idname      = "render.toggle_orientation"
    bl_label       = "Toggle Orientation"
    bl_description = "Toggle Landscape / Portrait"
    #bl_options = {'UNDO'}    
    
    def execute(self, context):
        scene  = context.scene
        rs     = scene.RBTab_Settings
        render = scene.render
        
        if rs.switchRenderRotation_prop == False:            
            x    = render.resolution_x        
            y    = render.resolution_y
            pa_x = render.pixel_aspect_x
            pa_y = render.pixel_aspect_y
            
            render.resolution_x   = y
            render.resolution_y   = x
            render.pixel_aspect_x = pa_y
            render.pixel_aspect_y = pa_x
            
            rs.switchRenderRotation_prop = True
            
        elif rs.switchRenderRotation_prop == True:
            x    = render.resolution_y        
            y    = render.resolution_x
            pa_x = render.pixel_aspect_y
            pa_y = render.pixel_aspect_x
                        
            render.resolution_x   = x
            render.resolution_y   = y
            render.pixel_aspect_x = pa_x
            render.pixel_aspect_y = pa_y
            
            rs.switchRenderRotation_prop = False

        return {'FINISHED'}


# STORE DEFAULT DIMENSION ##################################################################################
class MYBIGBUTTONTAB_OT_store_defaultres(Operator):
    bl_idname      = "render.store_as_defaultres"
    bl_label       = "Set Current Resolution as Default"
    #bl_options = {'UNDO'}    
    bl_description = (" \u2022 Shift + Click: Recover Last")
            
    @classmethod
    def poll(cls, context):
        return context.active_object is not None

    def invoke(self, context, event):    
        scene = context.scene
        rs    = scene.RBTab_Settings
        rd    = scene.render
        
        if event.shift:
            rd.resolution_x   = rs.Default_HRes_prop   
            rd.resolution_y   = rs.Default_VRes_prop
            rd.pixel_aspect_x = rs.Default_HPixRes_prop
            rd.pixel_aspect_y = rs.Default_VPixRes_prop         

        else:                    
            rs.Default_HRes_prop    = rd.resolution_x     
            rs.Default_VRes_prop    = rd.resolution_y
            rs.Default_HPixRes_prop = rd.pixel_aspect_x
            rs.Default_VPixRes_prop = rd.pixel_aspect_y                       

        return {'FINISHED'}


# CUSTOM CAMERA RESOLUTION ##################################################################################
class SCENECAMERA_OT_CustomResolution(Operator):
    bl_idname = "cameramanager.custom_resolution"
    bl_label = "Custom Resolution"
    bl_description = "Set current resolution as custom camera resolution"
    #bl_options = {'UNDO'}    
    
    crrefresh : bpy.props.BoolProperty(default = False)
    crdel     : bpy.props.BoolProperty(default = False)
    
    def execute(self, context):
        scene  = context.scene
        render = scene.render        
        ob     = context.active_object
        rs     = scene.RBTab_Settings        
        cs     = ob.RBTab_obj_Settings
                
        x      = render.resolution_x        
        y      = render.resolution_y        
        pa_x   = render.pixel_aspect_x
        pa_y   = render.pixel_aspect_y
        
        if self.crdel == True:
            cs.Custom_CamRes_prop     = False
            
            cs.Custom_CamHRes_prop    = rs.Default_HRes_prop
            cs.Custom_CamVRes_prop    = rs.Default_VRes_prop
            cs.Custom_CamHPixRes_prop = rs.Default_HPixRes_prop
            cs.Custom_CamVPixRes_prop = rs.Default_VPixRes_prop
            
            render.resolution_x       = rs.Default_HRes_prop      
            render.resolution_y       = rs.Default_VRes_prop
            render.pixel_aspect_x     = rs.Default_HPixRes_prop
            render.pixel_aspect_y     = rs.Default_VPixRes_prop
             
            self.crdel                = False
            return {'FINISHED'}                
        
        if cs.Custom_CamRes_prop == False:
            cs.Custom_CamHRes_prop    = x
            cs.Custom_CamVRes_prop    = y
            cs.Custom_CamHPixRes_prop = pa_x
            cs.Custom_CamVPixRes_prop = pa_y 
            cs.Custom_CamRes_prop     = True
            return {'FINISHED'} 
                
        elif cs.Custom_CamRes_prop == True:
            if self.crrefresh == False:
               return {'FINISHED'} 
            
            elif self.crrefresh == True:
                cs.Custom_CamHRes_prop    = x
                cs.Custom_CamVRes_prop    = y
                cs.Custom_CamHPixRes_prop = pa_x
                cs.Custom_CamVPixRes_prop = pa_y
                self.crrefresh            = False
                return {'FINISHED'}


#////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
#UI-PANEL//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
# RENDER BUTTON PROPERTIES ######################################################################################
class MYBIGBUTTON_PT_MyBigButton(Panel):
    bl_space_type  = "PROPERTIES"
    bl_region_type = "WINDOW"
    bl_context     = "render"    
    bl_label       = "Render Button "
    bl_idname      = "MYBIGBUTTON_PT_MyBigButton"
    bl_options     = {'HIDE_HEADER'}    
    

    def draw(self, context):
        scene  = context.scene
        rd     = context.scene.render

        layout = self.layout        
        split  = layout.split()        

        layout.use_property_split    = True       
        layout.use_property_decorate = False
        
        row = layout.row(align=True)
        row.scale_y = 2.5
        
        if (context.active_object is not None) and (context.active_object.mode !='OBJECT'):
            row.enabled = False
              
        if (scene.RBTab_Settings.switchStillAnim_prop == True):                              
            row.operator("render.render", text="RENDER ANIMATION").animation = True
            
        else:        
            row.operator("cameramanager.render_scene_camera", text="RENDER FRAME").renderFrom = 'PROPERTIES'
            
        row.prop(scene.RBTab_Settings, "switchStillAnim_prop", text="",icon='RENDER_ANIMATION')
            
        if (scene.RBTab_Settings.switchStillAnim_prop == True):
            row = layout.row(align=True)
            
            if (context.active_object is not None) and (context.active_object.mode !='OBJECT'):
                row.enabled = False
                
            if scene.show_subframe:
                row.prop(scene, "frame_float", text="")
            else:
                row.prop(scene, "frame_current", text="")

            row.separator()
            
            row.prop(scene, "use_preview_range", text="", toggle=True)
            
            #row.separator()
            sub = row.row(align=True)
            sub.scale_x = 0.95
            
            if not scene.use_preview_range:
                sub.prop(scene, "frame_start", text="")
                sub.prop(scene, "frame_end", text="")
            else:
                sub.prop(scene, "frame_preview_start", text="")
                sub.prop(scene, "frame_preview_end", text="")
                
        layout.separator()                                      
        row = layout.row()  
        
        if (context.active_object is not None) and (context.active_object.mode == 'EDIT'):
            row.enabled = False       
        
        row.prop(rd, "display_mode")
        row.prop(rd, "use_lock_interface", text="", emboss=False, icon='DECORATE_UNLOCKED') 
        
        layout.separator()



# RENDER BUTTON TAB ######################################################################################
class MYBIGBUTTONTAB_PT_MyBigButton(Panel):
    bl_space_type  = "VIEW_3D"
    bl_region_type = "UI"
    bl_category    = "Render"
    bl_context     = "objectmode"        
    bl_label       = "Render Button"
    bl_idname      = "MYBIGBUTTONTAB_PT_MyBigButton"
 

    def draw_header_preset(self, context):
        layout = self.layout
        layout.emboss = 'NONE' 
        row = layout.row(align=True)
        row.operator("render.opengl", text="", icon='RENDER_STILL')        
        row.operator("render.opengl", text="", icon='RENDER_ANIMATION').animation = True
        row.operator("screen.screen_full_area", text ="", icon = 'FULLSCREEN_ENTER').use_hide_panels=False
        row.label(text=" ", icon = 'BLANK1')


    def draw(self, context):
        scene = context.scene
        rd    = scene.render
        
        layout = self.layout 
        split  = layout.split()

        layout.use_property_split    = True       
        layout.use_property_decorate = False
        
        row = layout.row(align=True)
        row.scale_y = 2.5
              
        if (scene.RBTab_Settings.switchStillAnim_prop == True):                              
            row.operator("render.render", text="RENDER ANIMATION").animation = True
            
        else:        
            row.operator("cameramanager.render_scene_camera", text="RENDER FRAME").renderFrom = 'TAB'
            
        row.prop(scene.RBTab_Settings, "switchStillAnim_prop", text="",icon='RENDER_ANIMATION')
            
        # Frame Range
        if (scene.RBTab_Settings.switchStillAnim_prop == True):
            row = layout.row(align=True)

            if scene.show_subframe:
                row.prop(scene, "frame_float", text="")
            else:
                row.prop(scene, "frame_current", text="")

            row.separator()
            
            row.prop(scene, "use_preview_range", text="", toggle=True)
            
            #row.separator()
            sub = row.row(align=True)
            sub.scale_x = 0.95
             
            if not scene.use_preview_range:
                sub.prop(scene, "frame_start", text="")
                sub.prop(scene, "frame_end", text="")
            else:
                sub.prop(scene, "frame_preview_start", text="")
                sub.prop(scene, "frame_preview_end", text="")
        layout.separator()                                            
        row = layout.row()         
               
        if rd.has_multiple_engines:
            row.prop(rd, "engine", text="")          
            
        #row = layout.row()
                  
        row.prop(rd, "display_mode", text="")
        row.prop(rd, "use_lock_interface", text="", emboss=False, icon='DECORATE_UNLOCKED') 
        
        layout.separator()  


# CAMERA MANAGER PANEL ######################################################################################                      
class CAMMANAGER_PT_Cammanager(Panel):
    bl_space_type  = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_context     = "objectmode"  
    bl_category    = "Render"
    bl_label       = "Camera Manager"
    bl_idname      = "CAMMANAGER_PT_Cammanager"
    

    def draw(self, context):
        layout  = self.layout 
        scene   = context.scene
        rs      = scene.RBTab_Settings
        render  = scene.render      
        cameras = sorted([o for o in scene.objects if o.type == 'CAMERA'],key=lambda o: o.name)
        render_all_list = []
                
        for camera in cameras:
            rs_obj = camera.RBTab_obj_Settings
            if rs_obj.Custom_CamRender_prop == True:
                render_all_list += sorted([cameras])
                
        marker_list        = context.scene.timeline_markers        
        marker_list_camera = [o.camera for o in marker_list]
        render_marker_list = []
        
        for marker in marker_list:
            rs_obj = marker.camera.RBTab_obj_Settings
            if rs_obj.Custom_CamRender_prop == True:
                render_marker_list += sorted([marker])
                
        layout.operator("cameramanager.add_scene_camera",text='Add Camera To View', icon='ADD')
        
        view = context.space_data  
                
        if len(cameras) > 0:
            row = layout.row(align=True)
            
            #Camera Lock view button 
            if bpy.context.space_data.lock_camera == True: row.prop(view, "lock_camera", text="Lock Camera",icon='LOCKED')
            else: row.prop(view, "lock_camera", text="Lock Camera",icon='UNLOCKED')            
 
            row.separator()
            
            #Use as local Camera button
            if bpy.context.space_data.use_local_camera == True: row.prop(view, "use_local_camera", text="Use Local",icon='PINNED')
            else: row.prop(view, "use_local_camera", text="Use Local",icon='UNPINNED')
                    
            layout.separator()
            
            for camera in cameras:                
                rs_obj = camera.RBTab_obj_Settings
                row    = layout.row(align=True)
                                                
                row.context_pointer_set("active_object", camera)
                                
                #Preview Camera button                
                if camera == bpy.context.space_data.camera:                    
                    row.operator("cameramanager.activpreview_scene_camera",text='', icon='RESTRICT_VIEW_OFF')
                else:
                    if rs_obj.Custom_CamRes_prop == True:
                        if camera == scene.camera: row.operator("cameramanager.activpreview_scene_camera",text='', icon='CAMERA_DATA', emboss=False)                            
                        else: row.operator("cameramanager.activpreview_scene_camera",text='', icon='WORKSPACE', emboss=False)                    
                    else:
                        if camera == scene.camera: row.operator("cameramanager.activpreview_scene_camera",text='', icon='CAMERA_DATA', emboss=False)                         
                        else: row.operator("cameramanager.activpreview_scene_camera",text='', icon='RESTRICT_VIEW_ON', emboss=False)

            
                #Render button     
                row.operator("cameramanager.render_scene_camera",text='', icon='SEQ_PREVIEW').renderFrom = 'CAMANAGER'
                
                #Camera name          
                row.prop(camera, "name", text="")
                
                #Align View button               
                row.operator("cameramanager.alignview_scene_camera", text="", icon='VIEW_PERSPECTIVE')
                
                #Align Obj button               
                row.operator("cameramanager.alignobj_scene_camera", text="", icon='CUBE')
                
                #Track To button: Add/Remove
                if len(camera.constraints) == 0:
                    #Add TrackTo button
                    row.operator("cameramanager.trackto_scene_camera", text="", icon='TRACKER')
                else :
                    #Remove TrackTo button
                    row.operator("cameramanager.removetrackto_scene_camera", text="", icon='CON_FOLLOWTRACK', emboss=False)                            

                #Marker button: Add/Remove
                if camera in marker_list_camera : 
                    m = 0                    
                    for i,marker in enumerate(marker_list_camera):
                        if marker_list[i].frame != 0:
                            if marker == camera and m < 1:#prevent adding button if multiple marker on same camera
                                #Remove marker button
                                row.operator("cameramanager.remove_camera_marker",text='', icon='MARKER_HLT', emboss=False)
                                m += 1
                        elif marker_list[i].frame == 0 and marker == camera: row.operator("cameramanager.add_camera_marker",text='', icon='MARKER')
                #Add marker button                                                                 
                else: row.operator("cameramanager.add_camera_marker",text='', icon='MARKER')
                                                  
                row.separator()

                #Remove camera button                
                row.operator("cameramanager.del_scene_camera",text='', icon='PANEL_CLOSE', emboss=False)
                
                #Render Selection prop
                if len(cameras) >2 and rs.switchRenderSelection == True :
                    if rs_obj.Custom_CamRender_prop == True:
                        row.prop(rs_obj,'Custom_CamRender_prop',text='')
                    else:
                        row.prop(rs_obj,'Custom_CamRender_prop',text='')                  
                                      
            #Render All buttons for batch rendering    
            if len(cameras) >1 :                
                if len(render_all_list) <= 1 and rs.switchRenderSelection == True and len(cameras) >2:
                    layout.separator()
                    row = layout.row(align=True)
                    row.label(text='Select at least two Cameras', icon ='ERROR')                                
                elif len(render_all_list) > 1 and rs.switchRenderSelection == True:                    
                    layout.separator()
                    row = layout.row(align=True)
                    
                    row.prop(rs,'SwitchPropertiesBatch',text='', icon ='PROPERTIES')
                                                            
                    if len(render_all_list) == len(cameras):
                        row.operator("cameramanager.render_all_camera",text='Render All Cameras', icon='RENDER_RESULT')
                    elif len(render_all_list) < len(cameras):
                        if len(render_all_list):
                            row.operator("cameramanager.render_all_camera",text='Render Selection: {0}'.format(len(render_all_list)), icon='RENDER_RESULT')                           
                else :
                    layout.separator()
                    row = layout.row(align=True)
                    
                    row.prop(rs,'SwitchPropertiesBatch',text='', icon ='PROPERTIES')
                                        
                    if len(marker_list) <= 1: row.operator("cameramanager.render_all_camera",text='Render All Cameras', icon='RENDER_RESULT')                  
                    elif len(marker_list) > 1 :
                        row.operator("cameramanager.render_all_camera",text='Render All', icon='RENDER_RESULT')                        
                        if (len(cameras) != len(marker_list)):
                            row.operator("cameramanager.render_all_camera",text='Render Markers', icon='RENDER_RESULT').tmarkers = True            

            #Switch button for cameras selection mode, for batch rendering
            if len(cameras) > 2:
                row.separator()
                row.prop(rs,"switchRenderSelection",text='', icon='RESTRICT_SELECT_OFF')
                            
            if rs.SwitchPropertiesBatch  == True:
                
                layout = self.layout 
                split  = layout.split()

                layout.use_property_split    = True       
                layout.use_property_decorate = False

                box = layout.box()
                row = box.row()
                
                if bpy.data.is_saved == False:
                    row.label(text=' Save Blend File First  --->', icon='INFO')
                    row.operator('wm.save_mainfile', text='', icon='FILE_TICK')
                    
                else:    
                    row.prop(rs,'saveInBlendFolder',text='Save render in .blend folder')
               
                    if rs.saveInBlendFolder == False:
                        row = box.row()
                        row.prop(render, "filepath", text="")
                    row = box.row()
                         
                    row.prop(rs,'storeRenderInSlots',text='Store outputs in render slots')
                    img = bpy.data.images['Render Result']                 
                        
            row = layout.row(align=True)
                                                                    
        else:
            layout.label(text="  No cameras in this scene", icon ='ERROR')  



# CAMERA QUICK SETTINGS ######################################################################################                      
class CAMMANAGER_PT_QuickSettings(Panel):
    bl_space_type  = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_context     = "objectmode"
    bl_category    = "Render"
    bl_label       = "Quick Settings :"
    #bl_options     = {'DEFAULT_CLOSED'}     
    bl_idname      = "CAMMANAGER_PT_QuickSettings"
    bl_parent_id   = "CAMMANAGER_PT_Cammanager"
    
    @classmethod
    def poll(cls, context):
        return context.active_object is not None and context.active_object==bpy.context.space_data.camera #context.active_object.type == 'CAMERA'

    def draw_header_preset(self, context):
        scene   = context.scene
        cameras = sorted([o for o in scene.objects if o.type == 'CAMERA'],key=lambda o: o.name)
        ob      = context.active_object         
        
        layout = self.layout
        layout.emboss = 'NONE' 
        row = layout.row(align=True)

        if len(cameras) > 0 and (ob in cameras):
            chosen_camera = context.active_object 
            row.label(text="{0} ".format(chosen_camera .name)) 


    def draw(self, context):
        scene         = context.scene
        rs            = scene.RBTab_Settings
        ob            = context.active_object
        cs            = ob.RBTab_obj_Settings
        render        = scene.render        
        cameras       = sorted([o for o in scene.objects if o.type == 'CAMERA'],key=lambda o: o.name)    
        view          = context.space_data
        chosen_camera = bpy.context.object.data
        cam           = chosen_camera        
        
        layout  = self.layout   
                
        if len(cameras) > 0 and (ob in cameras): 
  
            row = layout.row(align=True) 
                                
            row.prop(cam, "type", text="")            
            row = layout.row(align=True) 
                
            if cam.type == 'PERSP':
                row.prop(cam, "lens", text="Focal")
                    
            elif cam.type == 'ORTHO':
                row.prop(cam, "ortho_scale", text="Scale")
                    
            elif cam.type == 'PANO':
                engine = context.engine
                if engine == 'CYCLES':
                    ccam = cam.cycles
                    row  = box.row()
                    row.prop(ccam, "panorama_type", text="")
                    row  = box.row()
                    
                    if ccam.panorama_type == 'FISHEYE_EQUIDISTANT':
                        row.prop(ccam, "fisheye_fov", text="FOV")
                        
                    elif ccam.panorama_type == 'FISHEYE_EQUISOLID':
                        row.prop(ccam, "fisheye_lens", text="Lens")
                        row.prop(ccam, "fisheye_fov", text="FOV")
                        
                    elif ccam.panorama_type == 'EQUIRECTANGULAR':
                        row = box.row()
                        row.label(text="Latitude:")
                        row = box.row()
                        row.prop(ccam, "latitude_min", text="Min")
                        row.prop(ccam, "latitude_max", text="Max")

                        row = box.row()
                        row.label(text="Longitude:")
                        row = box.row()                            
                        row.prop(ccam, "longitude_min", text="Min")
                        row.prop(ccam, "longitude_max", text="Max")
                        
                elif engine in {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}:
                    if cam.lens_unit == 'MILLIMETERS':
                        row.prop(cam, "lens")
                        
                    elif cam.lens_unit == 'FOV':
                        row.prop(cam, "angle")
                        
                    row.prop(cam, "lens_unit")

            row = layout.row(align=True) 
            row.prop(cam, "shift_x", text="Shift H")
            row.prop(cam, "shift_y", text="V")

            layout.separator()
            row = layout.row(align=True)             
          
            if cs.Custom_CamRes_prop == False:
                row.operator('cameramanager.custom_resolution',text="Save Custom Resolution",icon='FILE_TICK').crrefresh = False


            elif cs.Custom_CamRes_prop == True and (cs.Custom_CamHRes_prop == render.resolution_x) and (cs.Custom_CamVRes_prop == render.resolution_y):
                row.operator('cameramanager.custom_resolution',text="{0} x {1}".format(cs.Custom_CamHRes_prop,cs.Custom_CamVRes_prop), icon='LOCKED')
                row.operator('cameramanager.custom_resolution',text="", icon='PANEL_CLOSE',emboss=False).crdel = True

            elif cs.Custom_CamRes_prop == True and (cs.Custom_CamHRes_prop != render.resolution_x) or (cs.Custom_CamVRes_prop != render.resolution_y):
                row.operator('cameramanager.custom_resolution',text="{0} x {1}".format(cs.Custom_CamHRes_prop,cs.Custom_CamVRes_prop), icon='LOCKED').crrefresh = True                
                row.operator('cameramanager.custom_resolution',text="", icon='PANEL_CLOSE',emboss=False).crdel = True

 


# CAMERA MANAGER FOOTER INFOS ######################################################################################                      
class CAMMANAGER_PT_InfosCamActiv(Panel):
    bl_space_type  = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_context     = "objectmode"
    bl_category    = "Render"
    bl_label       = "Camera Infos"
    bl_idname      = "CAMMANAGER_PT_InfosCamActiv"
    bl_options     = {'HIDE_HEADER'}
    bl_parent_id   = "CAMMANAGER_PT_Cammanager"
    
    @classmethod
    def poll(cls, context):
        return context.active_object is not None and context.active_object==bpy.context.space_data.camera #context.active_object.type == 'CAMERA'

    def draw(self, context):                 
        scene         = context.scene
        ob            = context.active_object
        cs            = ob.RBTab_obj_Settings 
        marker_list   = context.scene.timeline_markers
        chosen_camera = context.active_object
        render        = context.scene.render
        cameras       = sorted([o for o in scene.objects if o.type == 'CAMERA'],key=lambda o: o.name)
        
        layout = self.layout
        split  = layout.split()

        layout.use_property_split = True
        layout.use_property_decorate = False
        
        row         = layout.row(align=True)
        row.scale_y = 0.7   
        
        if (context.active_object is not None):
                             
            if len(cameras) > 0 and (ob in cameras): 
                
                _customDim   = ""
                _trackTo     = "" 
                _markerName  = ""
                _markerFrame = ""
                _infos       = ""
                                                        
                if cs.Custom_CamRes_prop == True: _customDim = "{0}x{1} ".format(cs.Custom_CamHRes_prop,cs.Custom_CamVRes_prop)
                 
                if len(chosen_camera.constraints) > 0: _trackTo = " [{0}] ".format(chosen_camera.constraints[0].target.name) 

                for marker in marker_list:
                    if marker.camera == chosen_camera and scene.frame_current != 0:
                        _markerName  = " <{0}>".format(marker.camera.name)
                        _markerFrame = "({0})".format(marker.frame)
                        
                _infos = _customDim + _trackTo + _markerName + _markerFrame     
                        
                if _infos != "": row.label(text = _infos, icon ='INFO')                
              

# RENDER PRESET ######################################################################################
class RENDER_PT_presets(PresetPanel, Panel):
    bl_label = "Render Presets"
    preset_subdir = "render"
    preset_operator = "script.execute_preset"
    preset_add_operator = "render.preset_add"


# RENDER DIMENSIONS SUBPANEL ###################################################################################### 
class MYBIGBUTTONTAB_PT_RenderDimensions(Panel):
    bl_space_type  = "VIEW_3D"
    bl_region_type = "UI"
    bl_category    = "Render"   
    bl_label       = "Dimensions"
    bl_options     = {'DEFAULT_CLOSED'}    
    bl_idname      = "MYBIGBUTTON_PT_RenderDimensions"
    bl_parent_id   = "MYBIGBUTTONTAB_PT_MyBigButton"


    @classmethod
    def poll(cls, context):
        return context.mode == 'OBJECT'


    def draw_header_preset(self, _context):
        RENDER_PT_presets.draw_panel_header(self.layout)


    def draw(self, context):
        scene  = context.scene        
        rd     = scene.render
        rs     = scene.RBTab_Settings
        
        layout = self.layout         
        row    = layout.row(align=True)
            
        row.prop(scene.render, 'resolution_x', text="H")
        row.operator("render.toggle_orientation", text="", icon='ARROW_LEFTRIGHT')
        row.prop(scene.render, 'resolution_y', text="V")
                
        if (rd.resolution_x != rs.Default_HRes_prop) or (rd.resolution_y != rs.Default_VRes_prop):
            row.operator("render.store_as_defaultres", text="", icon='FILE_TICK',emboss=False)
                
        layout.prop(context.scene.render, "resolution_percentage", text="")

        row  = layout.row(align=True)         
        area = next(area for area in bpy.context.screen.areas if area.type == 'VIEW_3D')

        if area.spaces[0].region_3d.view_perspective == 'CAMERA':
            row.active  = True
            row.enabled = True
            row.prop(rd, "use_border", text="Render Region", icon='SHADING_BBOX')
            if rd.use_border == True:
                row.prop(rd, "use_crop_to_border", text="Crop Region", icon='IMAGE_PLANE')
        else:
            row.active  = False
            row.enabled = False
            row.prop(rd, "use_border", text="Render Region", icon='SHADING_BBOX')
            if rd.use_border == True:
                row.prop(rd, "use_crop_to_border", text="Crop Region", icon='IMAGE_PLANE')  
                        

#////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
#////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
#//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////                         
classes = (MYBIGBUTTON_Settings,
            MYBIGBUTTON_obj_Settings,
            
            SCENECAMERA_OT_Add,            
            SCENECAMERA_OT_ActivPreview,
            SCENECAMERA_OT_AlignView,            
            SCENECAMERA_OT_AlignObj,
            SCENECAMERA_OT_AddTrackTo,
            SCENECAMERA_OT_RemoveTrackTo,
            SCENECAMERA_OT_BatchRenderAll,
            SCENECAMERA_OT_Render,
            SCENECAMERA_OT_AddMarker,
            SCENECAMERA_OT_removeMarker,            
            SCENECAMERA_OT_Remove,
            SCENECAMERA_OT_CustomResolution,
            
            MYBIGBUTTON_PT_MyBigButton,
            MYBIGBUTTONTAB_OT_toggle_orientation,
            MYBIGBUTTONTAB_OT_store_defaultres,                                    
            MYBIGBUTTONTAB_PT_MyBigButton,
            MYBIGBUTTONTAB_PT_RenderDimensions,
             
            CAMMANAGER_PT_Cammanager,
            CAMMANAGER_PT_QuickSettings,
            CAMMANAGER_PT_InfosCamActiv,
            RENDER_PT_presets,
            )

def register():
    for i in classes:
        register_class(i)
        
    Scene.RBTab_Settings = PointerProperty(type=MYBIGBUTTON_Settings)
    Object.RBTab_obj_Settings = PointerProperty(type=MYBIGBUTTON_obj_Settings)

        
def unregister():
    for i in classes:
        unregister_class(i)
        
    del Scene.RBTab_Settings
    del Object.RBTab_obj_Settings

if __name__ == "__main__":
    try:
        unregister()
    except:
        pass
    register()
