-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from maksimio/maksim_uploadaddon
Выгрузка готового аддона и примеров вх. файлов
- Loading branch information
Showing
9 changed files
with
13,797 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
addon/__pycache__/ | ||
.vscode/ | ||
*.mp4 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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'} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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') |
Oops, something went wrong.