Skip to content

Commit

Permalink
Merge pull request #2 from maksimio/maksim_uploadaddon
Browse files Browse the repository at this point in the history
Выгрузка готового аддона и примеров вх. файлов
  • Loading branch information
Maksim Lopatin authored Apr 17, 2020
2 parents 519721a + c8b9351 commit f9ea846
Show file tree
Hide file tree
Showing 9 changed files with 13,797 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
addon/__pycache__/
.vscode/
*.mp4
41 changes: 41 additions & 0 deletions addon/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
bl_info = {
"name" : "videoCreator",
"author" : "Lopatin M., Savin D., Gureeva I., Briushinin A.",
"blender" : (2, 80, 0),
"version" : (0, 2),
"location" : "View3D",
"category" : "Animation",
"description" : "This addon can create 3D animations based on special input data",
"wiki_url": "https://github.com/maksimio/Video-Creator/wiki"
}

import bpy


from .panel import Main_VC_Panel
from .operators import Video_Generation_Operator, Scene_Properties
from .operators import Set_Camera_To_View_Operator, On_Off_Camera_View_Operator
from .operators import Render_Animation_Operator

classes = (
Main_VC_Panel,
Video_Generation_Operator,
Set_Camera_To_View_Operator,
On_Off_Camera_View_Operator,
Render_Animation_Operator,
Scene_Properties
)

def register():
for item in classes:
bpy.utils.register_class(item)
bpy.types.Scene.custom_props = bpy.props.PointerProperty(type=Scene_Properties)

def unregister():
for item in reversed(classes):
bpy.utils.unregister_class(item)
del bpy.types.Scene.custom_props


if __name__ == "__main__":
register()
154 changes: 154 additions & 0 deletions addon/operators.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import bpy
from os import path
from . script_generate_video import generate_video


class Scene_Properties(bpy.types.PropertyGroup):
# Кастомные свойства для хранения данных
# Присваиваются каждой сцене (см register()) как custom_props

input_filepath: bpy.props.StringProperty(
name="Input file",
description="Choose the input file in .json format",
default="",
maxlen=1024,
subtype='FILE_PATH',
)

set_timeline_status: bpy.props.StringProperty(
name="Status",
description="This is the status of timeline at current scene",
default="Not set",
maxlen=16
)

main_camera_name: bpy.props.StringProperty(
name="Camera",
description="This is the main camera name",
maxlen=64
)

main_light_name: bpy.props.StringProperty(
name="Camera",
description="This is the main camera name",
maxlen=64
)


class Set_Camera_To_View_Operator(bpy.types.Operator):
bl_idname = "camera.set_location_to_view"
bl_label = "Camera to view"
bl_description = "Set the camera position to view. Click from camera view to exit the camera view and end stay in the current camera location"

def execute(self, context):
try: # Вылетит исключение, если нажать кнопку, при уже включенном виде из камеры
bpy.ops.view3d.camera_to_view()
except RuntimeError: # Тогда просто выходим из этого режима
bpy.ops.view3d.view_camera()

return {'FINISHED'}


class On_Off_Camera_View_Operator(bpy.types.Operator):
bl_idname = "camera.on_off_camera_view"
bl_label = "On/Off camera view"
bl_description = "Show the camera view or exit the camera view. Remembers the previous position of the viewport"

def execute(self, context):
bpy.ops.view3d.view_camera()
return {'FINISHED'}


class Render_Animation_Operator(bpy.types.Operator):
bl_idname = "render.start_render"
bl_label = "Render animation"
bl_description = "Start render animation. The same as Render->Render_Animation or Ctrl+F12"

def execute(self, context):
# Манипуляции с именем файла
bpy.context.scene.render.use_file_extension = False
bpy.context.scene.render.views["left"].file_suffix = ""
bpy.context.scene.render.views["right"].file_suffix = ""
if bpy.context.scene.render.filepath.endswith(path.sep):
bpy.context.scene.render.filepath += "videoCreator.mp4"
if not bpy.context.scene.render.filepath.endswith(".mp4"):
bpy.context.scene.render.filepath += ".mp4"

# Сам рендер
bpy.ops.render.render("INVOKE_DEFAULT", animation=True)
return {'FINISHED'}


class Video_Generation_Operator(bpy.types.Operator):
bl_idname = "anim.make_video_generation"
bl_label = "Set objects on the timeline"
bl_description = "Make video based on input data file. Use after open file"

def execute(self, context):
# Автовыставление путей с предыдущей сцены
old_input_filepath = bpy.context.scene.custom_props.input_filepath
old_output_path = context.scene.render.filepath

# ---ГЕНЕРАЦИЯ ВИДЕО НА ОСНОВЕ ВХОДНЫХ ДАННЫХ---
if not old_input_filepath.endswith('.json'):
return {'FINISHED'}
frame_end = generate_video(old_input_filepath)

# ---НАСТРОЙКИ ПО УМОЛЧАНИЮ---
# Кастомные настройки + выходной путь
context.scene.custom_props.set_timeline_status = "Set"
context.scene.custom_props.input_filepath = old_input_filepath
context.scene.render.filepath = old_output_path

# Настройки рендера и окна предосмотра
context.scene.render.engine = 'BLENDER_EEVEE'
context.space_data.shading.type = 'RENDERED'

# Настройки качества
context.scene.render.resolution_x = 1920
context.scene.render.resolution_y = 1080
context.scene.render.resolution_percentage = 100

# Настройки кадров
context.scene.render.fps = 60
context.scene.render.fps_base = 1
context.scene.frame_start = 0
context.scene.frame_step = 1
context.scene.frame_end = frame_end
context.scene.frame_current = 0

# Базовые настройки 3D
context.scene.render.use_multiview = True # Stereoscopy
context.scene.render.image_settings.views_format = 'STEREO_3D' # Views Format
context.scene.render.image_settings.stereo_3d_format.display_mode = 'SIDEBYSIDE' # Stereo Mode
context.scene.render.image_settings.stereo_3d_format.use_sidebyside_crosseyed = False # Cross-Eyed

# Настройки формата выходного файла
context.scene.render.image_settings.file_format = 'FFMPEG'
context.scene.render.ffmpeg.format = 'MPEG4'

# Добавление камеры на сцену
bpy.ops.object.camera_add(rotation=(1, 0, 1))
context.scene.custom_props.main_camera_name = bpy.context.object.name
bpy.ops.object.select_all(action='SELECT')
bpy.ops.view3d.camera_to_view_selected()
bpy.ops.object.select_all(action='DESELECT')
context.space_data.stereo_3d_camera = 'RIGHT'

# Добавление света на сцену
bpy.ops.object.light_add(type='SUN')
context.scene.custom_props.main_light_name = bpy.context.object.name
bpy.data.objects[context.scene.custom_props.main_light_name].rotation_euler = (
0.279253, 0.139626, 0)
bpy.data.objects[context.scene.custom_props.main_light_name].data.angle = 0.0349066
bpy.data.objects[context.scene.custom_props.main_light_name].data.energy = 1
bpy.data.objects[context.scene.custom_props.main_light_name].data.use_shadow = False

# Добавление текстуры мира на сцену
new_world = bpy.data.worlds.new(context.scene.name)
new_world.use_nodes = True
context.scene.world = new_world
context.scene.world.node_tree.nodes["Background"].inputs[0].default_value = (
0.0196063, 0.0196063, 0.0196063, 1)

return {'FINISHED'}
116 changes: 116 additions & 0 deletions addon/panel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import bpy


class Main_VC_Panel(bpy.types.Panel):
bl_idname = "Main_VC_Panel"
bl_label = "Video Creator"
bl_category = "videoCreator"
bl_space_type = "VIEW_3D"
bl_region_type = "UI"

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

# -+-+-+-+-+-+-+-+-+-+-+-+ MAIN SETTINGS:
b_1 = layout.split()
c_1 = b_1.column()
c_1.label(text='MAIN SETTINGS:')

c_1.prop(context.scene.custom_props, 'input_filepath')
c_1.separator(factor=0.2)

s_r_c11_1 = c_1.row()
ss_c_src11_1 = s_r_c11_1.row()
ss_c_src11_1.label(text='Status:')
not_enable = ss_c_src11_1.split()
not_enable.prop(context.scene.custom_props,
'set_timeline_status', text='')
not_enable.enabled = False

ss_c_src11_2 = s_r_c11_1.row()
ss_c_src11_2.operator(
'anim.make_video_generation', icon='MODIFIER_ON')
ss_c_src11_2.scale_x = 2.15

c_1.separator(factor=0.2)
c_1.prop(st_rend_sets, 'filepath')

if context.scene.custom_props.set_timeline_status == 'Set':
layout.operator('render.start_render', icon='RENDER_ANIMATION')
layout.separator(factor=0.8)

# -+-+-+-+-+-+-+-+-+-+-+-+ RENDER SETTINGS:
b_2 = layout.split()
c_2_1 = b_2.column()
c_2_1.separator(factor=1)
c_2_1.label(text='RENDER SETTINGS:')

s_r_c21_1 = c_2_1.row()
ss_c_src211_1 = s_r_c21_1.column()
ss_c_src211_1.label(text='Resolution:')

ss_c_src211_2 = s_r_c21_1.column()
sss_c_sscsrc2112 = ss_c_src211_2.column()
local_col_left = sss_c_sscsrc2112
local_col_left.label(text='X')
local_col_left.label(text='Y')
local_col_left.scale_x = 0.4

sss_c_sscsrc2112_2 = s_r_c21_1.column()
local_col_right = sss_c_sscsrc2112_2
local_col_right.prop(st_rend_sets, 'resolution_x', text='')
local_col_right.prop(st_rend_sets, 'resolution_y', text='')
local_col_right.scale_x = 2.6

local_row = c_2_1.row()
local_row.label(text='Side-by-Side video:')
local_row.prop(st_rend_sets.image_settings.stereo_3d_format,
'use_sidebyside_crosseyed')

layout.separator(factor=0.8)

# -+-+-+-+-+-+-+-+-+-+-+-+ CAMERA SETTINGS:
b_3 = layout.split()
c_3_1 = b_3.column()
c_3_1.label(text='CAMERA SETTINGS:')

s_r_c31 = c_3_1.row()
s_r_c31.operator('camera.set_location_to_view')
s_r_c31.operator('camera.on_off_camera_view')
c_3_1.separator(factor=0.5)

c_3_1.prop(bpy.context.space_data, 'stereo_3d_camera')
s_r_c31_2 = c_3_1.row()
s_r_c31_2.label(text='Convergence Plane Distance')
s_r_c31_2.prop(
bpy.data.objects[context.scene.custom_props.main_camera_name].data.stereo, 'convergence_distance', text='')

s_r_c31_3 = c_3_1.row()
s_r_c31_3.label(text='Interocular Distance')
s_r_c31_3.prop(
bpy.data.objects[context.scene.custom_props.main_camera_name].data.stereo, 'interocular_distance', text='')
layout.separator(factor=0.8)

# -+-+-+-+-+-+-+-+-+-+-+-+ LIGHT SETTINGS:
b_4 = layout.split()
c_4_1 = b_4.column()
c_4_1.separator(factor=1)
c_4_1.label(text='LIGHT SETTINGS:')

s_r_c41_1 = c_4_1.row()
ss_c_rc41_1 = s_r_c41_1.column()

ss_c_rc41_1.prop(
bpy.data.objects[context.scene.custom_props.main_light_name].data, 'use_shadow', text='Shadow')
ss_c_rc41_1.prop(
bpy.data.objects[context.scene.custom_props.main_light_name], 'rotation_euler', text='Sun rotation')

ss_c_rc41_2 = s_r_c41_1.column()
ss_c_rc41_2.prop(
bpy.data.objects[context.scene.custom_props.main_light_name].data, 'energy', text='Power light')
ss_c_rc41_2.prop(
bpy.data.objects[context.scene.custom_props.main_light_name].data, 'angle')
ss_c_rc41_2.separator(factor=2.65)
ss_c_rc41_2.prop(
context.scene.world.node_tree.nodes['Background'].inputs[0], 'default_value', text='World color')
Loading

0 comments on commit f9ea846

Please sign in to comment.