Compare commits
378 Commits
fixed_widt
...
multiview
Author | SHA1 | Date | |
---|---|---|---|
![]() |
3519a9f517 | ||
![]() |
bdf398daa8 | ||
![]() |
25d55cb560 | ||
![]() |
259c649a0f | ||
![]() |
a400c95c94 | ||
![]() |
cc6c55c4af | ||
![]() |
6ffd218444 | ||
![]() |
3fbab3bbba | ||
![]() |
af38ace3ae | ||
![]() |
ed94a8def2 | ||
![]() |
717d10154b | ||
![]() |
7f02b9e869 | ||
![]() |
bbf2305155 | ||
![]() |
7fc167f10f | ||
![]() |
ed5515dec3 | ||
![]() |
4f0f84fb05 | ||
![]() |
4728dbd309 | ||
![]() |
2179f01ef4 | ||
![]() |
18dab1fa80 | ||
![]() |
781efee98d | ||
![]() |
2bfabfd4b1 | ||
![]() |
2a69362b2b | ||
![]() |
a2ff63ca09 | ||
![]() |
35f1662d25 | ||
![]() |
8c064a83cf | ||
![]() |
3e1790feb1 | ||
![]() |
c6d2db21d3 | ||
![]() |
52ca9a1921 | ||
![]() |
83a729e471 | ||
![]() |
d3b915c273 | ||
![]() |
ced7d8fb79 | ||
![]() |
926a56a5a6 | ||
![]() |
156b1ccba0 | ||
![]() |
e426e18f77 | ||
![]() |
1fb36fe650 | ||
![]() |
2055cced49 | ||
![]() |
20c043d422 | ||
![]() |
bcc3cb7a75 | ||
![]() |
0a1942fbb4 | ||
![]() |
7ad48ff467 | ||
![]() |
fb658d87ff | ||
![]() |
82b26c553d | ||
![]() |
458a78d7f9 | ||
![]() |
8f3f8e66be | ||
![]() |
106d00eec0 | ||
![]() |
34cfd02806 | ||
![]() |
39423a894c | ||
![]() |
83cef40fa6 | ||
![]() |
347339d653 | ||
![]() |
48ab2d5984 | ||
![]() |
6df28be1f7 | ||
![]() |
92780acaeb | ||
![]() |
3cb5a07783 | ||
![]() |
43e10a6853 | ||
![]() |
38b854a544 | ||
![]() |
1566cb3291 | ||
![]() |
3302e5cc49 | ||
5370c00e6b | |||
21f6e13835 | |||
270b487360 | |||
![]() |
82139c399f | ||
![]() |
45d76c110f | ||
![]() |
cc4129b7bb | ||
![]() |
93ca780e4d | ||
![]() |
6da622c95f | ||
![]() |
1a574e51fe | ||
![]() |
56ec0bd871 | ||
![]() |
27a69cf4b0 | ||
![]() |
e6a45d88d8 | ||
f21db785d9 | |||
fa5c238950 | |||
04a9635686 | |||
fd5573c700 | |||
fcbf89b4d6 | |||
606e290500 | |||
9c30eaa675 | |||
ea3aeb974f | |||
f66f765c79 | |||
715db49f42 | |||
7b17b02669 | |||
f53ee18e0e | |||
![]() |
bf3a031e9b | ||
![]() |
a6a8cb846a | ||
![]() |
14c9d575ce | ||
![]() |
f426d4b173 | ||
![]() |
99779ccb6f | ||
![]() |
a1a5bff7d9 | ||
![]() |
7092a7a737 | ||
![]() |
f862307b5a | ||
![]() |
281b49cfa8 | ||
![]() |
84ac66445f | ||
![]() |
9697d1375f | ||
![]() |
c71d3a6232 | ||
![]() |
20e023541c | ||
![]() |
f6bd5b34e0 | ||
![]() |
5891dba59f | ||
![]() |
d6dcae331e | ||
![]() |
ec6b87e89f | ||
![]() |
9b5bb695dd | ||
![]() |
4156618620 | ||
![]() |
d845727661 | ||
![]() |
a07a020e5e | ||
![]() |
6bed3b60d6 | ||
![]() |
8ca0401d67 | ||
![]() |
3694692aec | ||
![]() |
3f795ec6f3 | ||
![]() |
9a6d9c16f3 | ||
![]() |
dce6d7b1ec | ||
![]() |
2cfe4f6858 | ||
![]() |
f7f6a44022 | ||
![]() |
1f3114ef63 | ||
![]() |
6478240648 | ||
![]() |
56cf38b00a | ||
![]() |
1a8769917c | ||
![]() |
39037fe06c | ||
![]() |
089c6d6694 | ||
![]() |
ebdedf8a96 | ||
![]() |
34069b71c4 | ||
4338e1298f | |||
fb7efc0541 | |||
21d3acb79f | |||
6ccc61c346 | |||
![]() |
fc9622a167 | ||
![]() |
4c050676e8 | ||
![]() |
2e207f9154 | ||
![]() |
11cb2ab919 | ||
![]() |
2da034db2f | ||
![]() |
7095b9555e | ||
![]() |
55d75953ce | ||
![]() |
a2ee2d866f | ||
![]() |
6b0b2783d6 | ||
![]() |
e692b3d1e3 | ||
![]() |
56be796099 | ||
![]() |
b6f853a4fc | ||
![]() |
ec4670d857 | ||
![]() |
a5a614e78e | ||
![]() |
2ae2e54a92 | ||
![]() |
7d24f22b79 | ||
![]() |
fb01c00286 | ||
![]() |
a96b382206 | ||
![]() |
0d5c4fceef | ||
![]() |
b9db39ab5e | ||
![]() |
dd3a2979a3 | ||
![]() |
67a2def60a | ||
![]() |
a74c5742cc | ||
![]() |
289c8d6c6c | ||
![]() |
fb2577ab31 | ||
![]() |
e150f4f268 | ||
![]() |
fb37fd9961 | ||
![]() |
7e62853719 | ||
![]() |
a6e05ad1dc | ||
![]() |
a87fd88c6b | ||
![]() |
4c5c103258 | ||
![]() |
803bf25dc8 | ||
![]() |
76ad40fbf7 | ||
![]() |
cc7b45ae1f | ||
![]() |
589209412d | ||
![]() |
0b4c9043e2 | ||
![]() |
046a5babb0 | ||
![]() |
d9d94d0cfc | ||
![]() |
774d02930d | ||
![]() |
f17f665e0c | ||
![]() |
293b795e9b | ||
![]() |
967d65960d | ||
![]() |
610c4273ec | ||
![]() |
7fefdaadc8 | ||
1b1090081b | |||
![]() |
a5176676b8 | ||
6f81acd7f9 | |||
281db468f1 | |||
![]() |
54596a84f5 | ||
d73d9629fb | |||
3480409ae8 | |||
c0c2881a92 | |||
cf1054bb75 | |||
8f4f6f3405 | |||
bce859c805 | |||
22995bf9dc | |||
0fb6b7a71f | |||
![]() |
7f1ebeb6ca | ||
![]() |
9674b10798 | ||
![]() |
058ec78f87 | ||
![]() |
ba81c53ba4 | ||
![]() |
70bb90e1e0 | ||
![]() |
e438d861ed | ||
![]() |
ef109f9032 | ||
![]() |
b132cbda03 | ||
![]() |
0b03ccbbcd | ||
![]() |
8eb050c058 | ||
![]() |
52bc4bff69 | ||
![]() |
5352fef28f | ||
![]() |
af29905d48 | ||
![]() |
6725532363 | ||
![]() |
a094c395c0 | ||
![]() |
d13789ccdc | ||
![]() |
7edc16245a | ||
![]() |
6dcbd52c44 | ||
![]() |
0a6402535d | ||
![]() |
7d36655e51 | ||
![]() |
6d6e0a7736 | ||
![]() |
53f3860622 | ||
![]() |
df888ef0cf | ||
![]() |
4ef8927781 | ||
![]() |
0e163beaf1 | ||
![]() |
aad21b5e17 | ||
![]() |
f8812fab51 | ||
![]() |
df0b4840ed | ||
![]() |
59bf863273 | ||
![]() |
5ed6e4a029 | ||
![]() |
08f2122d7a | ||
![]() |
20a7889df1 | ||
![]() |
306732ec56 | ||
![]() |
1a8cf4f8a4 | ||
![]() |
04a361f090 | ||
![]() |
482eac61a2 | ||
![]() |
3ce1849f25 | ||
![]() |
407d60330d | ||
![]() |
5b16c78913 | ||
![]() |
f9cb232851 | ||
![]() |
b62b55b03b | ||
![]() |
7b0c812a5b | ||
![]() |
53b48b9568 | ||
![]() |
11270fc3f1 | ||
![]() |
a1a66a8887 | ||
![]() |
a913047549 | ||
![]() |
6593212027 | ||
89dd233d5f | |||
97a7d3d7b1 | |||
5bf989d609 | |||
![]() |
c5211463f9 | ||
![]() |
8d4c498cb8 | ||
![]() |
560ee80286 | ||
04516721a0 | |||
6f662de83a | |||
e11fd354d4 | |||
3c70ec25c8 | |||
![]() |
268ab9e1b7 | ||
![]() |
876bc2b947 | ||
![]() |
c95e71a5fe | ||
![]() |
176bbdc3cf | ||
![]() |
3232751301 | ||
![]() |
cb12fac477 | ||
![]() |
fd5ee4dd18 | ||
![]() |
c588080245 | ||
![]() |
bf72d65607 | ||
![]() |
fc35c8ae26 | ||
![]() |
87d67a0c46 | ||
![]() |
4bb1566944 | ||
![]() |
7739ac8691 | ||
![]() |
153696489d | ||
![]() |
f4759ed978 | ||
![]() |
304f81b086 | ||
![]() |
85eadbf776 | ||
![]() |
c36dfb5950 | ||
![]() |
2910b0c77f | ||
![]() |
d75a10e986 | ||
![]() |
f964ccd582 | ||
![]() |
fd377e2612 | ||
![]() |
b0373525ca | ||
![]() |
1111b2101e | ||
![]() |
dbf135f53e | ||
![]() |
2a7f2287e6 | ||
![]() |
9ba7bb0e61 | ||
![]() |
2d1218a76e | ||
![]() |
c1a25c10c3 | ||
![]() |
008474521e | ||
![]() |
d73683af12 | ||
![]() |
6a324c1967 | ||
![]() |
0095ac2186 | ||
![]() |
04cd487448 | ||
![]() |
af178735ad | ||
![]() |
626a2865f5 | ||
![]() |
b3685a8ea3 | ||
![]() |
d2363db238 | ||
![]() |
53edcd5f97 | ||
![]() |
69bac908da | ||
![]() |
192039c355 | ||
![]() |
a4e537d0f4 | ||
![]() |
655804f23e | ||
![]() |
14da4996cc | ||
![]() |
04c20fd7b3 | ||
![]() |
483b9532a5 | ||
![]() |
2d677941f5 | ||
![]() |
58880ec965 | ||
![]() |
4dd894d1f5 | ||
![]() |
26f38f3fc0 | ||
![]() |
8216fb119c | ||
![]() |
7ae4b8ef1a | ||
![]() |
9e1d326892 | ||
![]() |
afe8054596 | ||
![]() |
a16fef8e61 | ||
![]() |
529484ed77 | ||
![]() |
2b606dc130 | ||
![]() |
b239314f29 | ||
![]() |
26ca7deae9 | ||
![]() |
1c33e9bb4d | ||
![]() |
2c35b52d16 | ||
![]() |
ea85ef9a17 | ||
![]() |
055c4feeb5 | ||
![]() |
8884eb8882 | ||
![]() |
c00d8fdb09 | ||
![]() |
cc4236efda | ||
![]() |
c556dc44da | ||
![]() |
327007e933 | ||
![]() |
610a66bf8c | ||
![]() |
920d6403f4 | ||
![]() |
8b96cf5d0b | ||
![]() |
ca14760dad | ||
![]() |
4f1e311d1b | ||
![]() |
45159fa2e3 | ||
![]() |
477daa9337 | ||
![]() |
273345ed84 | ||
![]() |
16d58a115b | ||
![]() |
f424d433f6 | ||
![]() |
92d846c7bb | ||
![]() |
1e2ddc45c1 | ||
![]() |
a79d4e0c1e | ||
2f839c26ac | |||
![]() |
79a3861413 | ||
![]() |
9475d5e8c2 | ||
![]() |
3fbc866077 | ||
![]() |
1e3a4891be | ||
![]() |
7f706ce3ab | ||
![]() |
fd14bbeee1 | ||
![]() |
4d4841f810 | ||
![]() |
d428079782 | ||
![]() |
f955759ba8 | ||
![]() |
eb19c93cb2 | ||
![]() |
77598ecd38 | ||
![]() |
f220d46679 | ||
![]() |
c65d6abd3b | ||
![]() |
6bd7e44a40 | ||
![]() |
a4ac20287c | ||
![]() |
97c8c290e8 | ||
![]() |
3051deeddd | ||
![]() |
f56325f0c1 | ||
![]() |
737e70e4f3 | ||
![]() |
7f3c4200aa | ||
![]() |
04b6f38a64 | ||
![]() |
43ffe6ef0c | ||
![]() |
e85098266d | ||
![]() |
01e15e5037 | ||
![]() |
c47cd40944 | ||
![]() |
09c6b31395 | ||
![]() |
a76a84225c | ||
![]() |
f230d15ce1 | ||
![]() |
4e85d8daea | ||
![]() |
5ec6e7091e | ||
![]() |
bf86d65273 | ||
![]() |
5c1da8a78a | ||
![]() |
05c8590896 | ||
![]() |
6311911466 | ||
![]() |
361ed81048 | ||
![]() |
136823c3d1 | ||
![]() |
633f55ac6b | ||
![]() |
029938fb96 | ||
![]() |
e611409068 | ||
![]() |
4bd686cc95 | ||
![]() |
e480f93e21 | ||
![]() |
65510c0bcd | ||
![]() |
0147d96aea | ||
![]() |
dd7469df12 | ||
![]() |
edeeb7866f | ||
![]() |
0f56e3d6ed | ||
![]() |
9c2dd855ea | ||
![]() |
0bfc90a317 | ||
![]() |
205afa0a06 | ||
![]() |
c7bcd6310b | ||
![]() |
99c988ce84 | ||
![]() |
baaf31864a | ||
![]() |
a0b49f357a | ||
![]() |
5bd7ed4298 | ||
![]() |
042cf19838 | ||
![]() |
aef5800b8c | ||
![]() |
f4eae173c2 | ||
![]() |
63d30c704d | ||
![]() |
04b98f6118 | ||
![]() |
92a1b76e29 |
@@ -18,7 +18,7 @@
|
||||
|
||||
import bpy
|
||||
|
||||
from bpy.types import Panel, Menu, Operator
|
||||
from bpy.types import Panel, Menu, Operator, UIList
|
||||
|
||||
|
||||
class CYCLES_MT_sampling_presets(Menu):
|
||||
@@ -413,6 +413,49 @@ class CyclesRender_PT_layer_passes(CyclesButtonsPanel, Panel):
|
||||
col.prop(rl, "use_pass_environment")
|
||||
|
||||
|
||||
class CyclesRender_PT_views(CyclesButtonsPanel, Panel):
|
||||
bl_label = "Views"
|
||||
bl_context = "render_layer"
|
||||
|
||||
def draw_header(self, context):
|
||||
rd = context.scene.render
|
||||
self.layout.prop(rd, "use_multiview", text="")
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
scene = context.scene
|
||||
rd = scene.render
|
||||
rv = rd.views.active
|
||||
|
||||
|
||||
layout.active = rd.use_multiview
|
||||
basic_stereo = (rd.views_format == 'STEREO_3D')
|
||||
|
||||
row = layout.row()
|
||||
row.prop(rd, "views_format", expand=True)
|
||||
|
||||
if basic_stereo:
|
||||
row = layout.row()
|
||||
row.template_list("RENDERLAYER_UL_renderviews", "name", rd, "stereo_views", rd.views, "active_index", rows=2)
|
||||
|
||||
row = layout.row()
|
||||
row.label(text="File Suffix:")
|
||||
row.prop(rv, "file_suffix", text="")
|
||||
|
||||
else:
|
||||
row = layout.row()
|
||||
row.template_list("RENDERLAYER_UL_renderviews", "name", rd, "views", rd.views, "active_index", rows=2)
|
||||
|
||||
col = row.column(align=True)
|
||||
col.operator("scene.render_view_add", icon='ZOOMIN', text="")
|
||||
col.operator("scene.render_view_remove", icon='ZOOMOUT', text="")
|
||||
|
||||
row = layout.row()
|
||||
row.label(text="Camera Suffix:")
|
||||
row.prop(rv, "camera_suffix", text="")
|
||||
|
||||
|
||||
class Cycles_PT_post_processing(CyclesButtonsPanel, Panel):
|
||||
bl_label = "Post Processing"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
@@ -1428,6 +1471,7 @@ def get_panels():
|
||||
"DATA_PT_vertex_colors",
|
||||
"DATA_PT_camera",
|
||||
"DATA_PT_camera_display",
|
||||
"DATA_PT_camera_stereoscopy",
|
||||
"DATA_PT_camera_safe_areas",
|
||||
"DATA_PT_lens",
|
||||
"DATA_PT_speaker",
|
||||
|
@@ -95,7 +95,7 @@ static void blender_camera_init(BlenderCamera *bcam, BL::RenderSettings b_render
|
||||
bcam->full_height = render_resolution_y(b_render);
|
||||
}
|
||||
|
||||
static float blender_camera_focal_distance(BL::Object b_ob, BL::Camera b_camera)
|
||||
static float blender_camera_focal_distance(BL::RenderEngine b_engine, BL::Object b_ob, BL::Camera b_camera)
|
||||
{
|
||||
BL::Object b_dof_object = b_camera.dof_object();
|
||||
|
||||
@@ -103,14 +103,16 @@ static float blender_camera_focal_distance(BL::Object b_ob, BL::Camera b_camera)
|
||||
return b_camera.dof_distance();
|
||||
|
||||
/* for dof object, return distance along camera Z direction */
|
||||
Transform obmat = transform_clear_scale(get_transform(b_ob.matrix_world()));
|
||||
BL::Array<float, 16> b_ob_matrix;
|
||||
b_engine.camera_model_matrix(b_ob, b_ob_matrix);
|
||||
Transform obmat = get_transform(b_ob_matrix);
|
||||
Transform dofmat = get_transform(b_dof_object.matrix_world());
|
||||
Transform mat = transform_inverse(obmat) * dofmat;
|
||||
|
||||
return fabsf(transform_get_column(&mat, 3).z);
|
||||
}
|
||||
|
||||
static void blender_camera_from_object(BlenderCamera *bcam, BL::Object b_ob, bool skip_panorama = false)
|
||||
static void blender_camera_from_object(BlenderCamera *bcam, BL::RenderEngine b_engine, BL::Object b_ob, bool skip_panorama = false)
|
||||
{
|
||||
BL::ID b_ob_data = b_ob.data();
|
||||
|
||||
@@ -181,10 +183,10 @@ static void blender_camera_from_object(BlenderCamera *bcam, BL::Object b_ob, boo
|
||||
|
||||
bcam->apertureblades = RNA_int_get(&ccamera, "aperture_blades");
|
||||
bcam->aperturerotation = RNA_float_get(&ccamera, "aperture_rotation");
|
||||
bcam->focaldistance = blender_camera_focal_distance(b_ob, b_camera);
|
||||
bcam->focaldistance = blender_camera_focal_distance(b_engine, b_ob, b_camera);
|
||||
bcam->aperture_ratio = RNA_float_get(&ccamera, "aperture_ratio");
|
||||
|
||||
bcam->shift.x = b_camera.shift_x();
|
||||
bcam->shift.x = b_engine.camera_shift_x(b_ob);
|
||||
bcam->shift.y = b_camera.shift_y();
|
||||
|
||||
bcam->sensor_width = b_camera.sensor_width();
|
||||
@@ -402,8 +404,10 @@ void BlenderSync::sync_camera(BL::RenderSettings b_render, BL::Object b_override
|
||||
b_ob = b_override;
|
||||
|
||||
if(b_ob) {
|
||||
blender_camera_from_object(&bcam, b_ob);
|
||||
bcam.matrix = get_transform(b_ob.matrix_world());
|
||||
BL::Array<float, 16> b_ob_matrix;
|
||||
blender_camera_from_object(&bcam, b_engine, b_ob);
|
||||
b_engine.camera_model_matrix(b_ob, b_ob_matrix);
|
||||
bcam.matrix = get_transform(b_ob_matrix);
|
||||
}
|
||||
|
||||
/* sync */
|
||||
@@ -414,8 +418,9 @@ void BlenderSync::sync_camera(BL::RenderSettings b_render, BL::Object b_override
|
||||
void BlenderSync::sync_camera_motion(BL::Object b_ob, float motion_time)
|
||||
{
|
||||
Camera *cam = scene->camera;
|
||||
|
||||
Transform tfm = get_transform(b_ob.matrix_world());
|
||||
BL::Array<float, 16> b_ob_matrix;
|
||||
b_engine.camera_model_matrix(b_ob, b_ob_matrix);
|
||||
Transform tfm = get_transform(b_ob_matrix);
|
||||
tfm = blender_camera_matrix(tfm, cam->type);
|
||||
|
||||
if(tfm != cam->matrix) {
|
||||
@@ -433,10 +438,10 @@ void BlenderSync::sync_camera_motion(BL::Object b_ob, float motion_time)
|
||||
|
||||
/* Sync 3D View Camera */
|
||||
|
||||
static void blender_camera_view_subset(BL::RenderSettings b_render, BL::Scene b_scene, BL::Object b_ob, BL::SpaceView3D b_v3d,
|
||||
static void blender_camera_view_subset(BL::RenderEngine b_engine, BL::RenderSettings b_render, BL::Scene b_scene, BL::Object b_ob, BL::SpaceView3D b_v3d,
|
||||
BL::RegionView3D b_rv3d, int width, int height, BoundBox2D *view_box, BoundBox2D *cam_box);
|
||||
|
||||
static void blender_camera_from_view(BlenderCamera *bcam, BL::Scene b_scene, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height, bool skip_panorama = false)
|
||||
static void blender_camera_from_view(BlenderCamera *bcam, BL::RenderEngine b_engine, BL::Scene b_scene, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height, bool skip_panorama = false)
|
||||
{
|
||||
/* 3d view parameters */
|
||||
bcam->nearclip = b_v3d.clip_start();
|
||||
@@ -449,13 +454,13 @@ static void blender_camera_from_view(BlenderCamera *bcam, BL::Scene b_scene, BL:
|
||||
BL::Object b_ob = (b_v3d.lock_camera_and_layers())? b_scene.camera(): b_v3d.camera();
|
||||
|
||||
if(b_ob) {
|
||||
blender_camera_from_object(bcam, b_ob, skip_panorama);
|
||||
blender_camera_from_object(bcam, b_engine, b_ob, skip_panorama);
|
||||
|
||||
if(!skip_panorama && bcam->type == CAMERA_PANORAMA) {
|
||||
/* in panorama camera view, we map viewplane to camera border */
|
||||
BoundBox2D view_box, cam_box;
|
||||
|
||||
blender_camera_view_subset(b_scene.render(), b_scene, b_ob, b_v3d, b_rv3d, width, height,
|
||||
blender_camera_view_subset(b_engine, b_scene.render(), b_scene, b_ob, b_v3d, b_rv3d, width, height,
|
||||
&view_box, &cam_box);
|
||||
|
||||
bcam->pano_viewplane = view_box.make_relative_to(cam_box);
|
||||
@@ -493,7 +498,7 @@ static void blender_camera_from_view(BlenderCamera *bcam, BL::Scene b_scene, BL:
|
||||
bcam->matrix = transform_inverse(get_transform(b_rv3d.view_matrix()));
|
||||
}
|
||||
|
||||
static void blender_camera_view_subset(BL::RenderSettings b_render, BL::Scene b_scene, BL::Object b_ob, BL::SpaceView3D b_v3d,
|
||||
static void blender_camera_view_subset(BL::RenderEngine b_engine, BL::RenderSettings b_render, BL::Scene b_scene, BL::Object b_ob, BL::SpaceView3D b_v3d,
|
||||
BL::RegionView3D b_rv3d, int width, int height, BoundBox2D *view_box, BoundBox2D *cam_box)
|
||||
{
|
||||
BoundBox2D cam, view;
|
||||
@@ -502,7 +507,7 @@ static void blender_camera_view_subset(BL::RenderSettings b_render, BL::Scene b_
|
||||
/* get viewport viewplane */
|
||||
BlenderCamera view_bcam;
|
||||
blender_camera_init(&view_bcam, b_render);
|
||||
blender_camera_from_view(&view_bcam, b_scene, b_v3d, b_rv3d, width, height, true);
|
||||
blender_camera_from_view(&view_bcam, b_engine, b_scene, b_v3d, b_rv3d, width, height, true);
|
||||
|
||||
blender_camera_viewplane(&view_bcam, width, height,
|
||||
&view, &view_aspect, &sensor_size);
|
||||
@@ -510,7 +515,7 @@ static void blender_camera_view_subset(BL::RenderSettings b_render, BL::Scene b_
|
||||
/* get camera viewplane */
|
||||
BlenderCamera cam_bcam;
|
||||
blender_camera_init(&cam_bcam, b_render);
|
||||
blender_camera_from_object(&cam_bcam, b_ob, true);
|
||||
blender_camera_from_object(&cam_bcam, b_engine, b_ob, true);
|
||||
|
||||
blender_camera_viewplane(&cam_bcam, cam_bcam.full_width, cam_bcam.full_height,
|
||||
&cam, &cam_aspect, &sensor_size);
|
||||
@@ -520,7 +525,8 @@ static void blender_camera_view_subset(BL::RenderSettings b_render, BL::Scene b_
|
||||
*cam_box = cam * (1.0f/cam_aspect);
|
||||
}
|
||||
|
||||
static void blender_camera_border_subset(BL::RenderSettings b_render,
|
||||
static void blender_camera_border_subset(BL::RenderEngine b_engine,
|
||||
BL::RenderSettings b_render,
|
||||
BL::Scene b_scene,
|
||||
BL::SpaceView3D b_v3d,
|
||||
BL::RegionView3D b_rv3d,
|
||||
@@ -531,7 +537,7 @@ static void blender_camera_border_subset(BL::RenderSettings b_render,
|
||||
{
|
||||
/* Determine camera viewport subset. */
|
||||
BoundBox2D view_box, cam_box;
|
||||
blender_camera_view_subset(b_render, b_scene, b_ob, b_v3d, b_rv3d, width, height,
|
||||
blender_camera_view_subset(b_engine, b_render, b_scene, b_ob, b_v3d, b_rv3d, width, height,
|
||||
&view_box, &cam_box);
|
||||
|
||||
/* Determine viewport subset matching given border. */
|
||||
@@ -539,7 +545,7 @@ static void blender_camera_border_subset(BL::RenderSettings b_render,
|
||||
*result = cam_box.subset(border);
|
||||
}
|
||||
|
||||
static void blender_camera_border(BlenderCamera *bcam, BL::RenderSettings b_render, BL::Scene b_scene, BL::SpaceView3D b_v3d,
|
||||
static void blender_camera_border(BlenderCamera *bcam, BL::RenderEngine b_engine, BL::RenderSettings b_render, BL::Scene b_scene, BL::SpaceView3D b_v3d,
|
||||
BL::RegionView3D b_rv3d, int width, int height)
|
||||
{
|
||||
bool is_camera_view;
|
||||
@@ -568,7 +574,8 @@ static void blender_camera_border(BlenderCamera *bcam, BL::RenderSettings b_rend
|
||||
|
||||
/* Determine camera border inside the viewport. */
|
||||
BoundBox2D full_border;
|
||||
blender_camera_border_subset(b_render,
|
||||
blender_camera_border_subset(b_engine,
|
||||
b_render,
|
||||
b_scene,
|
||||
b_v3d,
|
||||
b_rv3d,
|
||||
@@ -587,7 +594,8 @@ static void blender_camera_border(BlenderCamera *bcam, BL::RenderSettings b_rend
|
||||
bcam->border.top = b_render.border_max_y();
|
||||
|
||||
/* Determine viewport subset matching camera border. */
|
||||
blender_camera_border_subset(b_render,
|
||||
blender_camera_border_subset(b_engine,
|
||||
b_render,
|
||||
b_scene,
|
||||
b_v3d,
|
||||
b_rv3d,
|
||||
@@ -602,8 +610,8 @@ void BlenderSync::sync_view(BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int
|
||||
{
|
||||
BlenderCamera bcam;
|
||||
blender_camera_init(&bcam, b_scene.render());
|
||||
blender_camera_from_view(&bcam, b_scene, b_v3d, b_rv3d, width, height);
|
||||
blender_camera_border(&bcam, b_scene.render(), b_scene, b_v3d, b_rv3d, width, height);
|
||||
blender_camera_from_view(&bcam, b_engine, b_scene, b_v3d, b_rv3d, width, height);
|
||||
blender_camera_border(&bcam, b_engine, b_scene.render(), b_scene, b_v3d, b_rv3d, width, height);
|
||||
|
||||
blender_camera_sync(scene->camera, &bcam, width, height);
|
||||
}
|
||||
|
@@ -331,9 +331,9 @@ static ShaderEvalType get_shader_type(const string& pass_type)
|
||||
return SHADER_EVAL_BAKE;
|
||||
}
|
||||
|
||||
static BL::RenderResult begin_render_result(BL::RenderEngine b_engine, int x, int y, int w, int h, const char *layername)
|
||||
static BL::RenderResult begin_render_result(BL::RenderEngine b_engine, int x, int y, int w, int h, const char *layername, const char *viewname)
|
||||
{
|
||||
return b_engine.begin_result(x, y, w, h, layername);
|
||||
return b_engine.begin_result(x, y, w, h, layername, viewname);
|
||||
}
|
||||
|
||||
static void end_render_result(BL::RenderEngine b_engine, BL::RenderResult b_rr, bool cancel, bool do_merge_results)
|
||||
@@ -350,7 +350,7 @@ void BlenderSession::do_write_update_render_tile(RenderTile& rtile, bool do_upda
|
||||
int h = params.height;
|
||||
|
||||
/* get render result */
|
||||
BL::RenderResult b_rr = begin_render_result(b_engine, x, y, w, h, b_rlay_name.c_str());
|
||||
BL::RenderResult b_rr = begin_render_result(b_engine, x, y, w, h, b_rlay_name.c_str(), b_rview_name.c_str());
|
||||
|
||||
/* can happen if the intersected rectangle gives 0 width or height */
|
||||
if(b_rr.ptr.data == NULL) {
|
||||
@@ -415,13 +415,14 @@ void BlenderSession::render()
|
||||
|
||||
/* render each layer */
|
||||
BL::RenderSettings r = b_scene.render();
|
||||
BL::RenderSettings::layers_iterator b_iter;
|
||||
BL::RenderSettings::layers_iterator b_layer_iter;
|
||||
BL::RenderResult::views_iterator b_view_iter;
|
||||
|
||||
for(r.layers.begin(b_iter); b_iter != r.layers.end(); ++b_iter) {
|
||||
b_rlay_name = b_iter->name();
|
||||
for(r.layers.begin(b_layer_iter); b_layer_iter != r.layers.end(); ++b_layer_iter) {
|
||||
b_rlay_name = b_layer_iter->name();
|
||||
|
||||
/* temporary render result to find needed passes */
|
||||
BL::RenderResult b_rr = begin_render_result(b_engine, 0, 0, 1, 1, b_rlay_name.c_str());
|
||||
/* temporary render result to find needed passes and views */
|
||||
BL::RenderResult b_rr = begin_render_result(b_engine, 0, 0, 1, 1, b_rlay_name.c_str(), NULL);
|
||||
BL::RenderResult::layers_iterator b_single_rlay;
|
||||
b_rr.layers.begin(b_single_rlay);
|
||||
|
||||
@@ -456,31 +457,41 @@ void BlenderSession::render()
|
||||
}
|
||||
}
|
||||
|
||||
/* free result without merging */
|
||||
end_render_result(b_engine, b_rr, true, false);
|
||||
|
||||
buffer_params.passes = passes;
|
||||
scene->film->pass_alpha_threshold = b_iter->pass_alpha_threshold();
|
||||
scene->film->pass_alpha_threshold = b_layer_iter->pass_alpha_threshold();
|
||||
scene->film->tag_passes_update(scene, passes);
|
||||
scene->film->tag_update(scene);
|
||||
scene->integrator->tag_update(scene);
|
||||
|
||||
/* update scene */
|
||||
sync->sync_camera(b_render, b_engine.camera_override(), width, height);
|
||||
sync->sync_data(b_v3d, b_engine.camera_override(), &python_thread_state, b_rlay_name.c_str());
|
||||
for(b_rr.views.begin(b_view_iter); b_view_iter != b_rr.views.end(); ++b_view_iter) {
|
||||
b_rview_name = b_view_iter->name();
|
||||
|
||||
/* update number of samples per layer */
|
||||
int samples = sync->get_layer_samples();
|
||||
bool bound_samples = sync->get_layer_bound_samples();
|
||||
/* set the current view */
|
||||
b_engine.active_view_set(b_rview_name.c_str());
|
||||
|
||||
if(samples != 0 && (!bound_samples || (samples < session_params.samples)))
|
||||
session->reset(buffer_params, samples);
|
||||
else
|
||||
session->reset(buffer_params, session_params.samples);
|
||||
/* update scene */
|
||||
sync->sync_camera(b_render, b_engine.camera_override(), width, height);
|
||||
sync->sync_data(b_v3d, b_engine.camera_override(), &python_thread_state, b_rlay_name.c_str());
|
||||
|
||||
/* render */
|
||||
session->start();
|
||||
session->wait();
|
||||
/* update number of samples per layer */
|
||||
int samples = sync->get_layer_samples();
|
||||
bool bound_samples = sync->get_layer_bound_samples();
|
||||
|
||||
if(samples != 0 && (!bound_samples || (samples < session_params.samples)))
|
||||
session->reset(buffer_params, samples);
|
||||
else
|
||||
session->reset(buffer_params, session_params.samples);
|
||||
|
||||
/* render */
|
||||
session->start();
|
||||
session->wait();
|
||||
|
||||
if(session->progress.get_cancel())
|
||||
break;
|
||||
}
|
||||
|
||||
/* free result without merging */
|
||||
end_render_result(b_engine, b_rr, true, false);
|
||||
|
||||
if(session->progress.get_cancel())
|
||||
break;
|
||||
@@ -619,10 +630,12 @@ void BlenderSession::do_write_update_render_result(BL::RenderResult b_rr, BL::Re
|
||||
b_pass.rect(&pixels[0]);
|
||||
}
|
||||
}
|
||||
|
||||
/* copy combined pass */
|
||||
if(buffers->get_pass_rect(PASS_COMBINED, exposure, rtile.sample, 4, &pixels[0]))
|
||||
b_rlay.rect(&pixels[0]);
|
||||
else {
|
||||
/* copy combined pass */
|
||||
BL::RenderPass b_combined_pass(b_rlay.passes.find_by_type(BL::RenderPass::type_COMBINED, b_rview_name.c_str()));
|
||||
if(buffers->get_pass_rect(PASS_COMBINED, exposure, rtile.sample, 4, &pixels[0]))
|
||||
b_combined_pass.rect(&pixels[0]);
|
||||
}
|
||||
|
||||
/* tag result as updated */
|
||||
b_engine.update_result(b_rr);
|
||||
@@ -841,6 +854,9 @@ void BlenderSession::update_status_progress()
|
||||
scene += " | " + b_scene.name();
|
||||
if(b_rlay_name != "")
|
||||
scene += ", " + b_rlay_name;
|
||||
|
||||
if(b_rview_name != "")
|
||||
scene += ", " + b_rview_name;
|
||||
}
|
||||
else {
|
||||
BLI_timestr(total_time, time_str, sizeof(time_str));
|
||||
|
@@ -90,6 +90,7 @@ public:
|
||||
BL::SpaceView3D b_v3d;
|
||||
BL::RegionView3D b_rv3d;
|
||||
string b_rlay_name;
|
||||
string b_rview_name;
|
||||
|
||||
string last_status;
|
||||
string last_error;
|
||||
|
@@ -135,6 +135,35 @@ class DATA_PT_lens(CameraButtonsPanel, Panel):
|
||||
col.prop(cam, "clip_end", text="End")
|
||||
|
||||
|
||||
class DATA_PT_camera_stereoscopy(CameraButtonsPanel, Panel):
|
||||
bl_label = "Stereoscopy"
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
render = context.scene.render
|
||||
return (super().poll(context) and render.use_multiview \
|
||||
and render.views_format == 'STEREO_3D')
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
render = context.scene.render
|
||||
st = context.camera.stereo
|
||||
|
||||
col = layout.column()
|
||||
col.row().prop(st, "convergence_mode", expand=True)
|
||||
|
||||
if st.convergence_mode == 'PARALLEL':
|
||||
col.prop(st, "viewport_convergence")
|
||||
else:
|
||||
col.prop(st, "convergence_distance")
|
||||
|
||||
col.prop(st, "interocular_distance")
|
||||
|
||||
col.label(text="Pivot:")
|
||||
col.row().prop(st, "pivot", expand=True)
|
||||
|
||||
|
||||
class DATA_PT_camera(CameraButtonsPanel, Panel):
|
||||
bl_label = "Camera"
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
|
||||
|
@@ -404,6 +404,8 @@ class RENDER_PT_output(RenderButtonsPanel, Panel):
|
||||
col.prop(rd, "use_render_cache")
|
||||
|
||||
layout.template_image_settings(image_settings, color_management=False)
|
||||
if rd.use_multiview:
|
||||
layout.template_image_views(image_settings)
|
||||
|
||||
if file_format == 'QUICKTIME':
|
||||
quicktime = rd.quicktime
|
||||
|
@@ -167,5 +167,63 @@ class RENDERLAYER_PT_layer_passes(RenderLayerButtonsPanel, Panel):
|
||||
self.draw_pass_type_buttons(col, rl, "refraction")
|
||||
|
||||
|
||||
class RENDERLAYER_UL_renderviews(UIList):
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
|
||||
# assert(isinstance(item, bpy.types.SceneRenderView)
|
||||
view = item
|
||||
if self.layout_type in {'DEFAULT', 'COMPACT'}:
|
||||
if view.name in {'left', 'right'}:
|
||||
layout.label(view.name, icon_value=icon + (not view.use))
|
||||
else:
|
||||
layout.prop(view, "name", text="", index=index, icon_value=icon, emboss=False)
|
||||
layout.prop(view, "use", text="", index=index)
|
||||
|
||||
elif self.layout_type == 'GRID':
|
||||
layout.alignment = 'CENTER'
|
||||
layout.label("", icon_value=icon + (not view.use))
|
||||
|
||||
|
||||
class RENDERLAYER_PT_views(RenderLayerButtonsPanel, Panel):
|
||||
bl_label = "Views"
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER'}
|
||||
|
||||
def draw_header(self, context):
|
||||
rd = context.scene.render
|
||||
self.layout.prop(rd, "use_multiview", text="")
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
scene = context.scene
|
||||
rd = scene.render
|
||||
rv = rd.views.active
|
||||
|
||||
layout.active = rd.use_multiview
|
||||
basic_stereo = rd.views_format == 'STEREO_3D'
|
||||
|
||||
row = layout.row()
|
||||
row.prop(rd, "views_format", expand=True)
|
||||
|
||||
if basic_stereo:
|
||||
row = layout.row()
|
||||
row.template_list("RENDERLAYER_UL_renderviews", "name", rd, "stereo_views", rd.views, "active_index", rows=2)
|
||||
|
||||
row = layout.row()
|
||||
row.label(text="File Suffix:")
|
||||
row.prop(rv, "file_suffix", text="")
|
||||
|
||||
else:
|
||||
row = layout.row()
|
||||
row.template_list("RENDERLAYER_UL_renderviews", "name", rd, "views", rd.views, "active_index", rows=2)
|
||||
|
||||
col = row.column(align=True)
|
||||
col.operator("scene.render_view_add", icon='ZOOMIN', text="")
|
||||
col.operator("scene.render_view_remove", icon='ZOOMOUT', text="")
|
||||
|
||||
row = layout.row()
|
||||
row.label(text="Camera Suffix:")
|
||||
row.prop(rv, "camera_suffix", text="")
|
||||
|
||||
|
||||
if __name__ == "__main__": # only for live edit.
|
||||
bpy.utils.register_module(__name__)
|
||||
|
@@ -458,6 +458,10 @@ class IMAGE_HT_header(Header):
|
||||
layout.prop_search(mesh.uv_textures, "active", mesh, "uv_textures", text="")
|
||||
|
||||
if ima:
|
||||
if ima.is_stereo_3d:
|
||||
row = layout.row()
|
||||
row.prop(sima, "show_stereo_3d", text="")
|
||||
|
||||
# layers
|
||||
layout.template_image_layers(ima, iuser)
|
||||
|
||||
|
@@ -282,6 +282,10 @@ class INFO_MT_window(Menu):
|
||||
layout.separator()
|
||||
layout.operator("wm.console_toggle", icon='CONSOLE')
|
||||
|
||||
if context.scene.render.use_multiview:
|
||||
layout.separator()
|
||||
layout.operator("wm.set_stereo_3d", icon='CAMERA_STEREO')
|
||||
|
||||
|
||||
class INFO_MT_help(Menu):
|
||||
bl_label = "Help"
|
||||
|
@@ -659,6 +659,7 @@ class SEQUENCER_PT_input(SequencerButtonsPanel, Panel):
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
scene = context.scene
|
||||
|
||||
strip = act_strip(context)
|
||||
|
||||
@@ -672,7 +673,7 @@ class SEQUENCER_PT_input(SequencerButtonsPanel, Panel):
|
||||
|
||||
# Current element for the filename
|
||||
|
||||
elem = strip.strip_elem_from_frame(context.scene.frame_current)
|
||||
elem = strip.strip_elem_from_frame(scene.frame_current)
|
||||
if elem:
|
||||
split = layout.split(percentage=0.2)
|
||||
split.label(text="File:")
|
||||
@@ -718,6 +719,19 @@ class SEQUENCER_PT_input(SequencerButtonsPanel, Panel):
|
||||
col.prop(strip, "frame_offset_start", text="Start")
|
||||
col.prop(strip, "frame_offset_end", text="End")
|
||||
|
||||
if scene.render.use_multiview and seq_type in {'IMAGE', 'MOVIE'}:
|
||||
layout.prop(strip, "use_multiview")
|
||||
|
||||
col = layout.column()
|
||||
col.active = strip.use_multiview
|
||||
|
||||
col.label(text="Views Format:")
|
||||
col.row().prop(strip, "views_format", expand=True)
|
||||
|
||||
box = col.box()
|
||||
box.active = strip.views_format == 'STEREO_3D'
|
||||
box.template_image_stereo_3d(strip.stereo_3d_format)
|
||||
|
||||
|
||||
class SEQUENCER_PT_sound(SequencerButtonsPanel, Panel):
|
||||
bl_label = "Sound"
|
||||
|
@@ -2936,16 +2936,50 @@ class VIEW3D_PT_view3d_display(Panel):
|
||||
row.prop(region, "use_box_clip")
|
||||
|
||||
|
||||
class VIEW3D_PT_view3d_shading(Panel):
|
||||
class VIEW3D_PT_view3d_stereo(Panel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
bl_region_type = 'UI'
|
||||
bl_label = "Shading"
|
||||
bl_label = "Stereoscopy"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
scene = context.scene
|
||||
|
||||
multiview = scene.render.use_multiview
|
||||
return context.space_data and multiview
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
view = context.space_data
|
||||
return (view)
|
||||
|
||||
basic_stereo = context.scene.render.views_format == 'STEREO_3D'
|
||||
|
||||
col = layout.column()
|
||||
col.row().prop(view, "stereo_3d_camera", expand=True)
|
||||
|
||||
col.label(text="Display:")
|
||||
row = col.row()
|
||||
row.active = basic_stereo
|
||||
row.prop(view, "show_stereo_3d_cameras")
|
||||
row = col.row()
|
||||
row.active = basic_stereo
|
||||
split = row.split()
|
||||
split.prop(view, "show_stereo_3d_convergence_plane")
|
||||
split = row.split()
|
||||
split.prop(view, "stereo_3d_convergence_plane_alpha", text="Alpha")
|
||||
split.active = view.show_stereo_3d_convergence_plane
|
||||
row = col.row()
|
||||
split = row.split()
|
||||
split.prop(view, "show_stereo_3d_volume")
|
||||
split = row.split()
|
||||
split.prop(view, "stereo_3d_volume_alpha", text="Alpha")
|
||||
|
||||
|
||||
class VIEW3D_PT_view3d_shading(Panel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
bl_region_type = 'UI'
|
||||
bl_label = "Shading"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
@@ -328,6 +328,7 @@ compositor_node_categories = [
|
||||
NodeItem("CompositorNodeCombYUVA"),
|
||||
NodeItem("CompositorNodeSepYCCA"),
|
||||
NodeItem("CompositorNodeCombYCCA"),
|
||||
NodeItem("CompositorNodeSwitchView"),
|
||||
]),
|
||||
CompositorNodeCategory("CMP_OP_FILTER", "Filter", items=[
|
||||
NodeItem("CompositorNodeBlur"),
|
||||
|
@@ -42,7 +42,7 @@ extern "C" {
|
||||
* and keep comment above the defines.
|
||||
* Use STRINGIFY() rather than defining with quotes */
|
||||
#define BLENDER_VERSION 274
|
||||
#define BLENDER_SUBVERSION 3
|
||||
#define BLENDER_SUBVERSION 4
|
||||
/* Several breakages with 270, e.g. constraint deg vs rad */
|
||||
#define BLENDER_MINVERSION 270
|
||||
#define BLENDER_MINSUBVERSION 5
|
||||
|
@@ -136,6 +136,14 @@ bool BKE_camera_view_frame_fit_to_coords(
|
||||
|
||||
void BKE_camera_to_gpu_dof(struct Object *camera, struct GPUFXSettings *r_fx_settings);
|
||||
|
||||
/* Camera multi-view API */
|
||||
|
||||
struct Object *BKE_camera_multiview_render(struct Scene *scene, struct Object *camera, const char *viewname);
|
||||
void BKE_camera_multiview_view_matrix(struct RenderData *rd, struct Object *camera, const bool is_left, float r_viewmat[4][4]);
|
||||
void BKE_camera_multiview_model_matrix(struct RenderData *rd, struct Object *camera, const char *viewname, float r_modelmat[4][4]);
|
||||
float BKE_camera_multiview_shift_x(struct RenderData *rd, struct Object *camera, const char *viewname);
|
||||
void BKE_camera_multiview_params(struct RenderData *rd, struct CameraParams *params, struct Object *camera, const char *viewname);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@@ -45,34 +45,34 @@ struct Object;
|
||||
struct ImageFormatData;
|
||||
struct ImagePool;
|
||||
struct Main;
|
||||
struct ReportList;
|
||||
|
||||
#define IMA_MAX_SPACE 64
|
||||
|
||||
void BKE_images_init(void);
|
||||
void BKE_images_exit(void);
|
||||
|
||||
void BKE_image_free_packedfiles(struct Image *image);
|
||||
void BKE_image_free_views(struct Image *image);
|
||||
void BKE_image_free_buffers(struct Image *image);
|
||||
/* call from library */
|
||||
void BKE_image_free(struct Image *image);
|
||||
|
||||
void BKE_imbuf_stamp_info(struct Scene *scene, struct Object *camera, struct ImBuf *ibuf);
|
||||
void BKE_image_stamp_buf(
|
||||
struct Scene *scene, struct Object *camera,
|
||||
unsigned char *rect, float *rectf, int width, int height, int channels);
|
||||
void BKE_image_stamp_buf(struct Scene *scene, struct Object *camera, unsigned char *rect, float *rectf, int width, int height, int channels);
|
||||
bool BKE_imbuf_alpha_test(struct ImBuf *ibuf);
|
||||
int BKE_imbuf_write_stamp(struct Scene *scene, struct Object *camera, struct ImBuf *ibuf, const char *name, struct ImageFormatData *imf);
|
||||
void BKE_imbuf_write_prepare(struct ImBuf *ibuf, struct ImageFormatData *imf);
|
||||
int BKE_imbuf_write(struct ImBuf *ibuf, const char *name, struct ImageFormatData *imf);
|
||||
int BKE_imbuf_write_as(struct ImBuf *ibuf, const char *name, struct ImageFormatData *imf, const bool is_copy);
|
||||
|
||||
void BKE_image_path_from_imformat(
|
||||
char *string, const char *base, const char *relbase, int frame,
|
||||
const struct ImageFormatData *im_format, const bool use_ext, const bool use_frames);
|
||||
const struct ImageFormatData *im_format, const bool use_ext, const bool use_frames, const char *suffix);
|
||||
void BKE_image_path_from_imtype(
|
||||
char *string, const char *base, const char *relbase, int frame,
|
||||
const char imtype, const bool use_ext, const bool use_frames);
|
||||
|
||||
bool BKE_image_path_ensure_ext_from_imformat(char *string, const struct ImageFormatData *im_format);
|
||||
bool BKE_image_path_ensure_ext_from_imtype(char *string, const char imtype);
|
||||
const char imtype, const bool use_ext, const bool use_frames, const char *suffix);
|
||||
int BKE_image_path_ensure_ext_from_imformat(char *string, const struct ImageFormatData *im_format);
|
||||
int BKE_image_path_ensure_ext_from_imtype(char *string, const char imtype);
|
||||
char BKE_image_ftype_to_imtype(const int ftype);
|
||||
int BKE_image_imtype_to_ftype(const char imtype);
|
||||
|
||||
@@ -103,6 +103,7 @@ void BKE_image_tag_time(struct Image *ima);
|
||||
/* ImageUser is in Texture, in Nodes, Background Image, Image Window, .... */
|
||||
/* should be used in conjunction with an ID * to Image. */
|
||||
struct ImageUser;
|
||||
struct RenderData;
|
||||
struct RenderPass;
|
||||
struct RenderResult;
|
||||
|
||||
@@ -172,11 +173,12 @@ struct Image *BKE_image_load_exists(const char *filepath);
|
||||
|
||||
/* adds image, adds ibuf, generates color or pattern */
|
||||
struct Image *BKE_image_add_generated(
|
||||
struct Main *bmain, unsigned int width, unsigned int height, const char *name, int depth, int floatbuf, short gen_type, const float color[4]);
|
||||
struct Main *bmain, unsigned int width, unsigned int height, const char *name, int depth, int floatbuf, short gen_type, const float color[4], const bool stereo3d);
|
||||
/* adds image from imbuf, owns imbuf */
|
||||
struct Image *BKE_image_add_from_imbuf(struct ImBuf *ibuf);
|
||||
|
||||
/* for reload, refresh, pack */
|
||||
void BKE_image_init_imageuser(struct Image *ima, struct ImageUser *iuser);
|
||||
void BKE_image_signal(struct Image *ima, struct ImageUser *iuser, int signal);
|
||||
|
||||
void BKE_image_walk_all_users(const struct Main *mainp, void *customdata,
|
||||
@@ -184,6 +186,8 @@ void BKE_image_walk_all_users(const struct Main *mainp, void *customdata,
|
||||
|
||||
/* ensures an Image exists for viewing nodes or render */
|
||||
struct Image *BKE_image_verify_viewer(int type, const char *name);
|
||||
/* ensures the view node cache is compatible with the scene views */
|
||||
void BKE_image_verify_viewer_views(const struct RenderData *rd, struct Image *ima, struct ImageUser *iuser);
|
||||
|
||||
/* called on frame change or before render */
|
||||
void BKE_image_user_frame_calc(struct ImageUser *iuser, int cfra, int fieldnr);
|
||||
@@ -195,13 +199,23 @@ void BKE_image_update_frame(const struct Main *bmain, int cfra);
|
||||
/* sets index offset for multilayer files */
|
||||
struct RenderPass *BKE_image_multilayer_index(struct RenderResult *rr, struct ImageUser *iuser);
|
||||
|
||||
/* sets index offset for multiview files */
|
||||
void BKE_image_multiview_index(struct Image *ima, struct ImageUser *iuser);
|
||||
|
||||
/* for multilayer images as well as for render-viewer */
|
||||
bool BKE_image_is_multilayer(struct Image *ima);
|
||||
struct RenderResult *BKE_image_acquire_renderresult(struct Scene *scene, struct Image *ima);
|
||||
void BKE_image_release_renderresult(struct Scene *scene, struct Image *ima);
|
||||
|
||||
/* for multilayer images as well as for singlelayer */
|
||||
bool BKE_image_is_openexr(struct Image *ima);
|
||||
|
||||
/* for multiple slot render, call this before render */
|
||||
void BKE_image_backup_render(struct Scene *scene, struct Image *ima);
|
||||
|
||||
|
||||
/* for singlelayer openexr saving */
|
||||
bool BKE_image_save_openexr_multiview(struct Image *ima, struct ImBuf *ibuf, const char *filepath, const int flags);
|
||||
|
||||
/* goes over all textures that use images */
|
||||
void BKE_image_free_all_textures(void);
|
||||
|
||||
@@ -212,6 +226,7 @@ void BKE_image_free_anim_ibufs(struct Image *ima, int except_frame);
|
||||
void BKE_image_all_free_anim_ibufs(int except_frame);
|
||||
|
||||
void BKE_image_memorypack(struct Image *ima);
|
||||
void BKE_image_packfiles(struct ReportList *reports, struct Image *ima, const char *basepath);
|
||||
|
||||
/* prints memory statistics for images */
|
||||
void BKE_image_print_memlist(void);
|
||||
@@ -243,7 +258,8 @@ float *BKE_image_get_float_pixels_for_frame(struct Image *image, int frame);
|
||||
|
||||
/* Guess offset for the first frame in the sequence */
|
||||
int BKE_image_sequence_guess_offset(struct Image *image);
|
||||
|
||||
bool BKE_image_has_anim(struct Image *image);
|
||||
bool BKE_image_has_packedfile(struct Image *image);
|
||||
bool BKE_image_is_animated(struct Image *image);
|
||||
bool BKE_image_is_dirty(struct Image *image);
|
||||
void BKE_image_file_format_set(struct Image *image, int ftype);
|
||||
|
@@ -941,6 +941,7 @@ void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMateria
|
||||
#define CMP_NODE_MAP_RANGE 319
|
||||
#define CMP_NODE_PLANETRACKDEFORM 320
|
||||
#define CMP_NODE_CORNERPIN 321
|
||||
#define CMP_NODE_SWITCH_VIEW 322
|
||||
|
||||
/* channel toggles */
|
||||
#define CMP_CHAN_RGB 1
|
||||
@@ -975,7 +976,8 @@ void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMateria
|
||||
|
||||
/* API */
|
||||
void ntreeCompositExecTree(struct Scene *scene, struct bNodeTree *ntree, struct RenderData *rd, int rendering, int do_previews,
|
||||
const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings);
|
||||
const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings,
|
||||
const char *view_name);
|
||||
void ntreeCompositTagRender(struct Scene *sce);
|
||||
int ntreeCompositTagAnimated(struct bNodeTree *ntree);
|
||||
void ntreeCompositTagGenerators(struct bNodeTree *ntree);
|
||||
|
@@ -70,6 +70,7 @@ void BKE_scene_free(struct Scene *sce);
|
||||
struct Scene *BKE_scene_add(struct Main *bmain, const char *name);
|
||||
|
||||
/* base functions */
|
||||
struct Base *BKE_scene_base_find_by_name(struct Scene *scene, const char *name);
|
||||
struct Base *BKE_scene_base_find(struct Scene *scene, struct Object *ob);
|
||||
struct Base *BKE_scene_base_add(struct Scene *sce, struct Object *ob);
|
||||
void BKE_scene_base_unlink(struct Scene *sce, struct Base *base);
|
||||
@@ -122,6 +123,9 @@ void BKE_scene_update_for_newframe_ex(struct EvaluationContext *eval_ctx, struct
|
||||
struct SceneRenderLayer *BKE_scene_add_render_layer(struct Scene *sce, const char *name);
|
||||
bool BKE_scene_remove_render_layer(struct Main *main, struct Scene *scene, struct SceneRenderLayer *srl);
|
||||
|
||||
struct SceneRenderView *BKE_scene_add_render_view(struct Scene *sce, const char *name);
|
||||
bool BKE_scene_remove_render_view(struct Scene *scene, struct SceneRenderView *srv);
|
||||
|
||||
/* render profile */
|
||||
int get_render_subsurf_level(const struct RenderData *r, int level);
|
||||
int get_render_child_particle_number(const struct RenderData *r, int num);
|
||||
@@ -142,6 +146,23 @@ int BKE_render_num_threads(const struct RenderData *r);
|
||||
|
||||
double BKE_scene_unit_scale(const struct UnitSettings *unit, const int unit_type, double value);
|
||||
|
||||
/* multiview */
|
||||
bool BKE_scene_multiview_is_stereo3d(const struct RenderData *rd);
|
||||
bool BKE_scene_multiview_is_render_view_active(const struct RenderData *rd, const struct SceneRenderView *srv);
|
||||
bool BKE_scene_multiview_is_render_view_first(const struct RenderData *rd, const char *viewname);
|
||||
bool BKE_scene_multiview_is_render_view_last(const struct RenderData *rd, const char *viewname);
|
||||
size_t BKE_scene_multiview_num_views_get(const struct RenderData *rd);
|
||||
struct SceneRenderView *BKE_scene_multiview_render_view_findindex(const struct RenderData *rd, const int view_id);
|
||||
const char *BKE_scene_multiview_render_view_name_get(const struct RenderData *rd, const int view_id);
|
||||
size_t BKE_scene_multiview_view_id_get(const struct RenderData *rd, const char *viewname);
|
||||
void BKE_scene_multiview_filepath_get(struct SceneRenderView *srv, const char *filepath, char *r_filepath);
|
||||
void BKE_scene_multiview_view_filepath_get(const struct RenderData *rd, const char *filepath, const char *view, char *r_filepath);
|
||||
const char *BKE_scene_multiview_view_suffix_get(const struct RenderData *rd, const char *viewname);
|
||||
const char *BKE_scene_multiview_view_id_suffix_get(const struct RenderData *rd, const size_t view_id);
|
||||
void BKE_scene_multiview_view_prefix_get(struct Scene *scene, const char *name, char *rprefix, char **rext);
|
||||
void BKE_scene_multiview_videos_dimensions_get(const struct RenderData *rd, const size_t width, const size_t height, size_t *r_width, size_t *r_height);
|
||||
size_t BKE_scene_multiview_num_videos_get(const struct RenderData *rd);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@@ -41,6 +41,7 @@ struct Mask;
|
||||
struct Scene;
|
||||
struct Sequence;
|
||||
struct SequenceModifierData;
|
||||
struct Stereo3dFormat;
|
||||
struct StripElem;
|
||||
struct bSound;
|
||||
|
||||
@@ -99,6 +100,7 @@ typedef struct SeqRenderData {
|
||||
float motion_blur_shutter;
|
||||
bool skip_cache;
|
||||
bool is_proxy_render;
|
||||
size_t view_id;
|
||||
} SeqRenderData;
|
||||
|
||||
void BKE_sequencer_new_render_data(
|
||||
@@ -223,6 +225,7 @@ void BKE_sequencer_base_clipboard_pointers_store(struct ListBase *seqbase);
|
||||
void BKE_sequencer_base_clipboard_pointers_restore(struct ListBase *seqbase, struct Main *bmain);
|
||||
|
||||
void BKE_sequence_free(struct Scene *scene, struct Sequence *seq);
|
||||
void BKE_sequence_free_anim(struct Sequence *seq);
|
||||
const char *BKE_sequence_give_name(struct Sequence *seq);
|
||||
void BKE_sequence_calc(struct Scene *scene, struct Sequence *seq);
|
||||
void BKE_sequence_calc_disp(struct Scene *scene, struct Sequence *seq);
|
||||
@@ -235,7 +238,7 @@ struct StripElem *BKE_sequencer_give_stripelem(struct Sequence *seq, int cfra);
|
||||
void BKE_sequencer_update_changed_seq_and_deps(struct Scene *scene, struct Sequence *changed_seq, int len_change, int ibuf_change);
|
||||
bool BKE_sequencer_input_have_to_preprocess(const SeqRenderData *context, struct Sequence *seq, float cfra);
|
||||
|
||||
struct SeqIndexBuildContext *BKE_sequencer_proxy_rebuild_context(struct Main *bmain, struct Scene *scene, struct Sequence *seq, struct GSet *file_list);
|
||||
void BKE_sequencer_proxy_rebuild_context(struct Main *bmain, struct Scene *scene, struct Sequence *seq, struct GSet *file_list, ListBase *queue);
|
||||
void BKE_sequencer_proxy_rebuild(struct SeqIndexBuildContext *context, short *stop, short *do_update, float *progress);
|
||||
void BKE_sequencer_proxy_rebuild_finish(struct SeqIndexBuildContext *context, bool stop);
|
||||
|
||||
@@ -355,6 +358,10 @@ typedef struct SeqLoadInfo {
|
||||
int len; /* only for image strips */
|
||||
char path[1024]; /* 1024 = FILE_MAX */
|
||||
|
||||
/* multiview */
|
||||
char views_format;
|
||||
struct Stereo3dFormat *stereo3d_format;
|
||||
|
||||
/* return values */
|
||||
char name[64];
|
||||
struct Sequence *seq_sound; /* for movie's */
|
||||
@@ -399,7 +406,7 @@ struct Sequence *BKE_sequencer_add_sound_strip(struct bContext *C, ListBase *seq
|
||||
struct Sequence *BKE_sequencer_add_movie_strip(struct bContext *C, ListBase *seqbasep, struct SeqLoadInfo *seq_load);
|
||||
|
||||
/* view3d draw callback, run when not in background view */
|
||||
typedef struct ImBuf *(*SequencerDrawView)(struct Scene *, struct Object *, int, int, unsigned int, int, bool, bool, bool, int, char[256]);
|
||||
typedef struct ImBuf *(*SequencerDrawView)(struct Scene *, struct Object *, int, int, unsigned int, int, bool, bool, bool, int, const char *, char[256]);
|
||||
extern SequencerDrawView sequencer_view3d_cb;
|
||||
|
||||
/* copy/paste */
|
||||
|
@@ -43,16 +43,20 @@ struct ReportList;
|
||||
struct Scene;
|
||||
|
||||
typedef struct bMovieHandle {
|
||||
int (*start_movie)(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports, bool preview);
|
||||
int (*append_movie)(struct RenderData *rd, int start_frame, int frame, int *pixels,
|
||||
int rectx, int recty, struct ReportList *reports);
|
||||
void (*end_movie)(void);
|
||||
int (*get_next_frame)(struct RenderData *rd, struct ReportList *reports); /* optional */
|
||||
void (*get_movie_path)(char *string, struct RenderData *rd, bool preview); /* optional */
|
||||
int (*start_movie)(void *context_v, struct Scene *scene, struct RenderData *rd, int rectx, int recty,
|
||||
struct ReportList *reports, bool preview, const char *suffix);
|
||||
int (*append_movie)(void *context_v, struct RenderData *rd, int start_frame, int frame, int *pixels,
|
||||
int rectx, int recty, const char *suffix, struct ReportList *reports);
|
||||
void (*end_movie)(void *context_v);
|
||||
int (*get_next_frame)(void *context_v, struct RenderData *rd, struct ReportList *reports); /* optional */
|
||||
void (*get_movie_path)(char *string, struct RenderData *rd, bool preview, const char *suffix); /* optional */
|
||||
void *(*context_create)(void);
|
||||
void (*context_free)(void *context_v);
|
||||
} bMovieHandle;
|
||||
|
||||
bMovieHandle *BKE_movie_handle_get(const char imtype);
|
||||
void BKE_movie_filepath_get(char *string, struct RenderData *rd, bool preview);
|
||||
void BKE_movie_filepath_get(char *string, struct RenderData *rd, bool preview, const char *suffix);
|
||||
void BKE_context_create(bMovieHandle *mh);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@@ -68,11 +68,11 @@ struct RenderData;
|
||||
struct ReportList;
|
||||
struct Scene;
|
||||
|
||||
int BKE_ffmpeg_start(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports, bool preview);
|
||||
void BKE_ffmpeg_end(void);
|
||||
int BKE_ffmpeg_append(struct RenderData *rd, int start_frame, int frame, int *pixels,
|
||||
int rectx, int recty, struct ReportList *reports);
|
||||
void BKE_ffmpeg_filepath_get(char *string, struct RenderData *rd, bool preview);
|
||||
int BKE_ffmpeg_start(void *context_v, struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports, bool preview, const char *suffix);
|
||||
void BKE_ffmpeg_end(void *context_v);
|
||||
int BKE_ffmpeg_append(void *context_v, struct RenderData *rd, int start_frame, int frame, int *pixels,
|
||||
int rectx, int recty, const char *suffix, struct ReportList *reports);
|
||||
void BKE_ffmpeg_filepath_get(char *string, struct RenderData *rd, bool preview, const char *suffix);
|
||||
|
||||
void BKE_ffmpeg_preset_set(struct RenderData *rd, int preset);
|
||||
void BKE_ffmpeg_image_type_verify(struct RenderData *rd, struct ImageFormatData *imf);
|
||||
@@ -82,6 +82,9 @@ bool BKE_ffmpeg_alpha_channel_is_supported(struct RenderData *rd);
|
||||
int BKE_ffmpeg_property_add_string(struct RenderData *rd, const char *type, const char *str);
|
||||
void BKE_ffmpeg_property_del(struct RenderData *rd, void *type, void *prop_);
|
||||
|
||||
void *BKE_ffmpeg_context_create(void);
|
||||
void BKE_ffmpeg_context_free(void *context_v);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@@ -40,11 +40,14 @@ struct RenderData;
|
||||
struct ReportList;
|
||||
struct Scene;
|
||||
|
||||
int BKE_frameserver_start(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports, bool preview);
|
||||
void BKE_frameserver_end(void);
|
||||
int BKE_frameserver_append(struct RenderData *rd, int start_frame, int frame, int *pixels,
|
||||
int rectx, int recty, struct ReportList *reports);
|
||||
int BKE_frameserver_loop(struct RenderData *rd, struct ReportList *reports);
|
||||
int BKE_frameserver_start(void *context_v, struct Scene *scene, struct RenderData *rd, int rectx, int recty,
|
||||
struct ReportList *reports, bool preview, const char *suffix);
|
||||
void BKE_frameserver_end(void *context_v);
|
||||
int BKE_frameserver_append(void *context_v, struct RenderData *rd, int start_frame, int frame, int *pixels,
|
||||
int rectx, int recty, const char*suffix, struct ReportList *reports);
|
||||
int BKE_frameserver_loop(void *context_v, struct RenderData *rd, struct ReportList *reports);
|
||||
void *BKE_frameserver_context_create(void);
|
||||
void BKE_frameserver_context_free(void *context_v);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@@ -423,10 +423,10 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int
|
||||
{
|
||||
Image *ima;
|
||||
ima = (Image *)id;
|
||||
if (ima->packedfile == NULL || (flag & BKE_BPATH_TRAVERSE_SKIP_PACKED) == 0) {
|
||||
if (BKE_image_has_packedfile(ima) == false || (flag & BKE_BPATH_TRAVERSE_SKIP_PACKED) == 0) {
|
||||
if (ELEM(ima->source, IMA_SRC_FILE, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
|
||||
if (rewrite_path_fixed(ima->name, visit_cb, absbase, bpath_user_data)) {
|
||||
if (!ima->packedfile) {
|
||||
if (!BKE_image_has_packedfile(ima)) {
|
||||
BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD);
|
||||
BKE_image_walk_all_users(bmain, ima, bpath_traverse_image_user_cb);
|
||||
}
|
||||
|
@@ -30,16 +30,19 @@
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "DNA_camera_types.h"
|
||||
#include "DNA_lamp_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_view3d_types.h"
|
||||
#include "DNA_ID.h"
|
||||
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_rect.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BKE_animsys.h"
|
||||
#include "BKE_camera.h"
|
||||
@@ -47,6 +50,7 @@
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_library.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_scene.h"
|
||||
#include "BKE_screen.h"
|
||||
|
||||
#include "GPU_compositing.h"
|
||||
@@ -71,6 +75,10 @@ void *BKE_camera_add(Main *bmain, const char *name)
|
||||
|
||||
GPU_fx_compositor_init_dof_settings(&cam->gpu_dof);
|
||||
|
||||
/* stereoscopy 3d */
|
||||
cam->stereo.interocular_distance = 0.065f;
|
||||
cam->stereo.convergence_distance = 30.f * 0.065f;
|
||||
|
||||
return cam;
|
||||
}
|
||||
|
||||
@@ -695,6 +703,250 @@ bool BKE_camera_view_frame_fit_to_coords(
|
||||
return camera_frame_fit_calc_from_data(¶ms, &data_cb, r_co, r_scale);
|
||||
}
|
||||
|
||||
/******************* multiview matrix functions ***********************/
|
||||
|
||||
static void camera_model_matrix(Object *camera, float r_modelmat[4][4])
|
||||
{
|
||||
copy_m4_m4(r_modelmat, camera->obmat);
|
||||
}
|
||||
|
||||
static void camera_stereo3d_model_matrix(Object *camera, const bool is_left, float r_modelmat[4][4])
|
||||
{
|
||||
Camera *data = (Camera *)camera->data;
|
||||
float interocular_distance, convergence_distance;
|
||||
short convergence_mode, pivot;
|
||||
float sizemat[4][4];
|
||||
|
||||
float fac = 1.0f;
|
||||
float fac_signed;
|
||||
|
||||
interocular_distance = data->stereo.interocular_distance;
|
||||
convergence_distance = data->stereo.convergence_distance;
|
||||
convergence_mode = data->stereo.convergence_mode;
|
||||
pivot = data->stereo.pivot;
|
||||
|
||||
if (((pivot == CAM_S3D_PIVOT_LEFT) && is_left) ||
|
||||
((pivot == CAM_S3D_PIVOT_RIGHT) && !is_left))
|
||||
{
|
||||
return camera_model_matrix(camera, r_modelmat);
|
||||
}
|
||||
else {
|
||||
float size[3];
|
||||
mat4_to_size(size, camera->obmat);
|
||||
size_to_mat4(sizemat, size);
|
||||
}
|
||||
|
||||
if (pivot == CAM_S3D_PIVOT_CENTER)
|
||||
fac = 0.5f;
|
||||
|
||||
fac_signed = is_left ? fac : -fac;
|
||||
|
||||
/* rotation */
|
||||
if (convergence_mode == CAM_S3D_TOE) {
|
||||
float angle;
|
||||
float angle_sin, angle_cos;
|
||||
float toeinmat[4][4];
|
||||
float rotmat[4][4];
|
||||
|
||||
unit_m4(rotmat);
|
||||
|
||||
if (pivot == CAM_S3D_PIVOT_CENTER) {
|
||||
fac = -fac;
|
||||
fac_signed = -fac_signed;
|
||||
}
|
||||
|
||||
angle = atanf((interocular_distance * 0.5f) / convergence_distance) / fac;
|
||||
|
||||
angle_cos = cosf(angle * fac_signed);
|
||||
angle_sin = sinf(angle * fac_signed);
|
||||
|
||||
rotmat[0][0] = angle_cos;
|
||||
rotmat[2][0] = -angle_sin;
|
||||
rotmat[0][2] = angle_sin;
|
||||
rotmat[2][2] = angle_cos;
|
||||
|
||||
if (pivot == CAM_S3D_PIVOT_CENTER) {
|
||||
/* set the rotation */
|
||||
copy_m4_m4(toeinmat, rotmat);
|
||||
/* set the translation */
|
||||
toeinmat[3][0] = interocular_distance * fac_signed;
|
||||
|
||||
/* transform */
|
||||
normalize_m4_m4(r_modelmat, camera->obmat);
|
||||
mul_m4_m4m4(r_modelmat, r_modelmat, toeinmat);
|
||||
|
||||
/* scale back to the original size */
|
||||
mul_m4_m4m4(r_modelmat, r_modelmat, sizemat);
|
||||
}
|
||||
else { /* CAM_S3D_PIVOT_LEFT, CAM_S3D_PIVOT_RIGHT */
|
||||
/* rotate perpendicular to the interocular line */
|
||||
normalize_m4_m4(r_modelmat, camera->obmat);
|
||||
mul_m4_m4m4(r_modelmat, r_modelmat, rotmat);
|
||||
|
||||
/* translate along the interocular line */
|
||||
unit_m4(toeinmat);
|
||||
toeinmat[3][0] = -interocular_distance * fac_signed;
|
||||
mul_m4_m4m4(r_modelmat, r_modelmat, toeinmat);
|
||||
|
||||
/* rotate to toe-in angle */
|
||||
mul_m4_m4m4(r_modelmat, r_modelmat, rotmat);
|
||||
|
||||
/* scale back to the original size */
|
||||
mul_m4_m4m4(r_modelmat, r_modelmat, sizemat);
|
||||
}
|
||||
}
|
||||
else {
|
||||
normalize_m4_m4(r_modelmat, camera->obmat);
|
||||
|
||||
/* translate - no rotation in CAM_S3D_OFFAXIS, CAM_S3D_PARALLEL */
|
||||
translate_m4(r_modelmat, -interocular_distance * fac_signed, 0.0f, 0.0f);
|
||||
|
||||
/* scale back to the original size */
|
||||
mul_m4_m4m4(r_modelmat, r_modelmat, sizemat);
|
||||
}
|
||||
}
|
||||
|
||||
/* the view matrix is used by the viewport drawing, it is basically the inverted model matrix */
|
||||
void BKE_camera_multiview_view_matrix(RenderData *rd, Object *camera, const bool is_left, float r_viewmat[4][4])
|
||||
{
|
||||
BKE_camera_multiview_model_matrix(rd, camera, is_left ? STEREO_LEFT_NAME : STEREO_RIGHT_NAME, r_viewmat);
|
||||
invert_m4(r_viewmat);
|
||||
}
|
||||
|
||||
/* left is the default */
|
||||
static bool camera_is_left(const char *viewname)
|
||||
{
|
||||
if (viewname && viewname[0] != '\0') {
|
||||
return !STREQ(viewname, STEREO_RIGHT_NAME);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void BKE_camera_multiview_model_matrix(RenderData *rd, Object *camera, const char *viewname, float r_modelmat[4][4])
|
||||
{
|
||||
const bool is_multiview = (rd && rd->scemode & R_MULTIVIEW) != 0;
|
||||
|
||||
if (!is_multiview) {
|
||||
camera_model_matrix(camera, r_modelmat);
|
||||
}
|
||||
else if (rd->views_format == SCE_VIEWS_FORMAT_MULTIVIEW) {
|
||||
camera_model_matrix(camera, r_modelmat);
|
||||
}
|
||||
else { /* SCE_VIEWS_SETUP_BASIC */
|
||||
const bool is_left = camera_is_left(viewname);
|
||||
camera_stereo3d_model_matrix(camera, is_left, r_modelmat);
|
||||
}
|
||||
normalize_m4(r_modelmat);
|
||||
}
|
||||
|
||||
static Object *camera_multiview_advanced(Scene *scene, Object *camera, const char *suffix)
|
||||
{
|
||||
SceneRenderView *srv;
|
||||
char name[MAX_NAME];
|
||||
const char *camera_name = camera->id.name + 2;
|
||||
const int len_name = strlen(camera_name);
|
||||
|
||||
name[0] = '\0';
|
||||
|
||||
for (srv = scene->r.views.first; srv; srv = srv->next) {
|
||||
const int len_suffix = strlen(srv->suffix);
|
||||
|
||||
if (len_name < len_suffix)
|
||||
continue;
|
||||
|
||||
if (STREQ(camera_name + (len_name - len_suffix), srv->suffix)) {
|
||||
BLI_snprintf(name, sizeof(name), "%.*s%s", (len_name - len_suffix), camera_name, suffix);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (name[0] != '\0') {
|
||||
Base *base = BKE_scene_base_find_by_name(scene, name);
|
||||
if (base) {
|
||||
return base->object;
|
||||
}
|
||||
}
|
||||
|
||||
return camera;
|
||||
}
|
||||
|
||||
/* returns the camera to be used for render */
|
||||
Object *BKE_camera_multiview_render(Scene *scene, Object *camera, const char *viewname)
|
||||
{
|
||||
const bool is_multiview = (scene->r.scemode & R_MULTIVIEW) != 0;
|
||||
|
||||
if (!is_multiview) {
|
||||
return camera;
|
||||
}
|
||||
else if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) {
|
||||
return camera;
|
||||
}
|
||||
else { /* SCE_VIEWS_FORMAT_MULTIVIEW */
|
||||
const char *suffix = BKE_scene_multiview_view_suffix_get(&scene->r, viewname);
|
||||
return camera_multiview_advanced(scene, camera, suffix);
|
||||
}
|
||||
}
|
||||
|
||||
static float camera_stereo3d_shift_x(Object *camera, const char *viewname)
|
||||
{
|
||||
Camera *data = camera->data;
|
||||
float shift = data->shiftx;
|
||||
float interocular_distance, convergence_distance;
|
||||
short convergence_mode, pivot;
|
||||
bool is_left = true;
|
||||
|
||||
float fac = 1.0f;
|
||||
float fac_signed;
|
||||
|
||||
if (viewname && viewname[0]) {
|
||||
is_left = STREQ(viewname, STEREO_LEFT_NAME);
|
||||
}
|
||||
|
||||
interocular_distance = data->stereo.interocular_distance;
|
||||
convergence_distance = data->stereo.convergence_distance;
|
||||
convergence_mode = data->stereo.convergence_mode;
|
||||
pivot = data->stereo.pivot;
|
||||
|
||||
if (((pivot == CAM_S3D_PIVOT_LEFT) && is_left) ||
|
||||
((pivot == CAM_S3D_PIVOT_RIGHT) && !is_left))
|
||||
{
|
||||
return shift;
|
||||
}
|
||||
|
||||
if (pivot == CAM_S3D_PIVOT_CENTER)
|
||||
fac = 0.5f;
|
||||
|
||||
fac_signed = is_left ? fac : -fac;
|
||||
|
||||
/* Note: in viewport, parallel renders as offaxis, but in render it does parallel */
|
||||
if (ELEM(convergence_mode, CAM_S3D_OFFAXIS, CAM_S3D_PARALLEL)) {
|
||||
shift += ((interocular_distance / data->sensor_x) * (data->lens / convergence_distance)) * fac_signed;
|
||||
}
|
||||
|
||||
return shift;
|
||||
}
|
||||
|
||||
float BKE_camera_multiview_shift_x(RenderData *rd, Object *camera, const char *viewname)
|
||||
{
|
||||
const bool is_multiview = (rd && rd->scemode & R_MULTIVIEW) != 0;
|
||||
Camera *data = camera->data;
|
||||
|
||||
if (!is_multiview) {
|
||||
return data->shiftx;
|
||||
}
|
||||
else if (rd->views_format == SCE_VIEWS_FORMAT_MULTIVIEW) {
|
||||
return data->shiftx;
|
||||
}
|
||||
else { /* SCE_VIEWS_SETUP_BASIC */
|
||||
return camera_stereo3d_shift_x(camera, viewname);
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_camera_multiview_params(RenderData *rd, CameraParams *params, Object *camera, const char *viewname)
|
||||
{
|
||||
params->shiftx = BKE_camera_multiview_shift_x(rd, camera, viewname);
|
||||
}
|
||||
|
||||
void BKE_camera_to_gpu_dof(struct Object *camera, struct GPUFXSettings *r_fx_settings)
|
||||
{
|
||||
if (camera->type == OB_CAMERA) {
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -3475,6 +3475,7 @@ static void registerCompositNodes(void)
|
||||
register_node_type_cmp_bokehimage();
|
||||
register_node_type_cmp_bokehblur();
|
||||
register_node_type_cmp_switch();
|
||||
register_node_type_cmp_switch_view();
|
||||
register_node_type_cmp_pixelate();
|
||||
|
||||
register_node_type_cmp_mask();
|
||||
|
@@ -1002,7 +1002,7 @@ static void cache_filename(char *string, const char *path, const char *relbase,
|
||||
|
||||
BLI_join_dirfile(cachepath, sizeof(cachepath), path, fname);
|
||||
|
||||
BKE_image_path_from_imtype(string, cachepath, relbase, frame, R_IMF_IMTYPE_OPENEXR, true, true);
|
||||
BKE_image_path_from_imtype(string, cachepath, relbase, frame, R_IMF_IMTYPE_OPENEXR, true, true, "");
|
||||
}
|
||||
|
||||
/* silly functions but useful to inline when the args do a lot of indirections */
|
||||
|
@@ -128,8 +128,8 @@ int countPackedFiles(Main *bmain)
|
||||
|
||||
/* let's check if there are packed files... */
|
||||
for (ima = bmain->image.first; ima; ima = ima->id.next)
|
||||
if (ima->packedfile)
|
||||
count++;
|
||||
if (BKE_image_has_packedfile(ima))
|
||||
count ++;
|
||||
|
||||
for (vf = bmain->vfont.first; vf; vf = vf->id.next)
|
||||
if (vf->packedfile)
|
||||
@@ -232,9 +232,9 @@ void packAll(Main *bmain, ReportList *reports)
|
||||
int tot = 0;
|
||||
|
||||
for (ima = bmain->image.first; ima; ima = ima->id.next) {
|
||||
if (ima->packedfile == NULL && ima->id.lib == NULL) {
|
||||
if (BKE_image_has_packedfile(ima) == false && ima->id.lib == NULL) {
|
||||
if (ima->source == IMA_SRC_FILE) {
|
||||
ima->packedfile = newPackedFile(reports, ima->name, ID_BLEND_PATH(bmain, &ima->id));
|
||||
BKE_image_packfiles(reports, ima, ID_BLEND_PATH(bmain, &ima->id));
|
||||
tot ++;
|
||||
}
|
||||
else if (BKE_image_is_animated(ima)) {
|
||||
@@ -564,23 +564,47 @@ int unpackSound(Main *bmain, ReportList *reports, bSound *sound, int how)
|
||||
|
||||
int unpackImage(ReportList *reports, Image *ima, int how)
|
||||
{
|
||||
char localname[FILE_MAX], absname[FILE_MAX];
|
||||
char *newname;
|
||||
int ret_value = RET_ERROR;
|
||||
|
||||
|
||||
if (ima != NULL && ima->name[0]) {
|
||||
unpack_generate_paths(ima->name, (ID *)ima, absname, localname, sizeof(absname), sizeof(localname));
|
||||
newname = unpackFile(reports, absname, localname, ima->packedfile, how);
|
||||
if (newname != NULL) {
|
||||
ret_value = RET_OK;
|
||||
freePackedFile(ima->packedfile);
|
||||
ima->packedfile = NULL;
|
||||
BLI_strncpy(ima->name, newname, sizeof(ima->name));
|
||||
MEM_freeN(newname);
|
||||
BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD);
|
||||
while (ima->packedfiles.last) {
|
||||
char localname[FILE_MAX], absname[FILE_MAX];
|
||||
char *newname;
|
||||
ImagePackedFile *imapf = ima->packedfiles.last;
|
||||
|
||||
unpack_generate_paths(imapf->filepath, (ID *)ima, absname, localname, sizeof(absname), sizeof(localname));
|
||||
newname = unpackFile(reports, absname, localname, imapf->packedfile, how);
|
||||
|
||||
if (newname != NULL) {
|
||||
ImageView *iv;
|
||||
|
||||
ret_value = ret_value == RET_ERROR ? RET_ERROR : RET_OK;
|
||||
freePackedFile(imapf->packedfile);
|
||||
imapf->packedfile = NULL;
|
||||
|
||||
/* update the new corresponding view filepath */
|
||||
iv = BLI_findstring(&ima->views, imapf->filepath, offsetof(ImageView, filepath));
|
||||
if (iv) {
|
||||
BLI_strncpy(iv->filepath, newname, sizeof(imapf->filepath));
|
||||
}
|
||||
|
||||
/* keep the new name in the image for non-pack specific reasons */
|
||||
BLI_strncpy(ima->name, newname, sizeof(imapf->filepath));
|
||||
MEM_freeN(newname);
|
||||
}
|
||||
else {
|
||||
ret_value = RET_ERROR;
|
||||
}
|
||||
|
||||
BLI_remlink(&ima->packedfiles, imapf);
|
||||
MEM_freeN(imapf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (ret_value == RET_OK) {
|
||||
BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD);
|
||||
}
|
||||
|
||||
return(ret_value);
|
||||
}
|
||||
|
||||
@@ -636,7 +660,7 @@ void unpackAll(Main *bmain, ReportList *reports, int how)
|
||||
bSound *sound;
|
||||
|
||||
for (ima = bmain->image.first; ima; ima = ima->id.next)
|
||||
if (ima->packedfile)
|
||||
if (BKE_image_has_packedfile(ima))
|
||||
unpackImage(reports, ima, how);
|
||||
|
||||
for (vf = bmain->vfont.first; vf; vf = vf->id.next)
|
||||
@@ -655,7 +679,7 @@ bool BKE_pack_check(ID *id)
|
||||
case ID_IM:
|
||||
{
|
||||
Image *ima = (Image *)id;
|
||||
return ima->packedfile != NULL;
|
||||
return BKE_image_has_packedfile(ima);
|
||||
}
|
||||
case ID_VF:
|
||||
{
|
||||
@@ -683,7 +707,7 @@ void BKE_unpack_id(Main *bmain, ID *id, ReportList *reports, int how)
|
||||
case ID_IM:
|
||||
{
|
||||
Image *ima = (Image *)id;
|
||||
if (ima->packedfile) {
|
||||
if (BKE_image_has_packedfile(ima)) {
|
||||
unpackImage(reports, ima, how);
|
||||
}
|
||||
break;
|
||||
|
@@ -92,6 +92,7 @@
|
||||
#include "PIL_time.h"
|
||||
|
||||
#include "IMB_colormanagement.h"
|
||||
#include "IMB_imbuf.h"
|
||||
|
||||
#include "bmesh.h"
|
||||
|
||||
@@ -157,14 +158,16 @@ Scene *BKE_scene_copy(Scene *sce, int type)
|
||||
Base *base, *obase;
|
||||
|
||||
if (type == SCE_COPY_EMPTY) {
|
||||
ListBase lb;
|
||||
ListBase rl, rv;
|
||||
/* XXX. main should become an arg */
|
||||
scen = BKE_scene_add(G.main, sce->id.name + 2);
|
||||
|
||||
lb = scen->r.layers;
|
||||
rl = scen->r.layers;
|
||||
rv = scen->r.views;
|
||||
scen->r = sce->r;
|
||||
scen->r.layers = lb;
|
||||
scen->r.layers = rl;
|
||||
scen->r.actlay = 0;
|
||||
scen->r.views = rv;
|
||||
scen->unit = sce->unit;
|
||||
scen->physics_settings = sce->physics_settings;
|
||||
scen->gm = sce->gm;
|
||||
@@ -197,6 +200,7 @@ Scene *BKE_scene_copy(Scene *sce, int type)
|
||||
BLI_duplicatelist(&(scen->markers), &(sce->markers));
|
||||
BLI_duplicatelist(&(scen->transform_spaces), &(sce->transform_spaces));
|
||||
BLI_duplicatelist(&(scen->r.layers), &(sce->r.layers));
|
||||
BLI_duplicatelist(&(scen->r.views), &(sce->r.views));
|
||||
BKE_keyingsets_copy(&(scen->keyingsets), &(sce->keyingsets));
|
||||
|
||||
if (sce->nodetree) {
|
||||
@@ -390,6 +394,7 @@ void BKE_scene_free(Scene *sce)
|
||||
BLI_freelistN(&sce->markers);
|
||||
BLI_freelistN(&sce->transform_spaces);
|
||||
BLI_freelistN(&sce->r.layers);
|
||||
BLI_freelistN(&sce->r.views);
|
||||
|
||||
if (sce->toolsettings) {
|
||||
if (sce->toolsettings->vpaint) {
|
||||
@@ -437,6 +442,7 @@ Scene *BKE_scene_add(Main *bmain, const char *name)
|
||||
ParticleEditSettings *pset;
|
||||
int a;
|
||||
const char *colorspace_name;
|
||||
SceneRenderView *srv;
|
||||
|
||||
sce = BKE_libblock_alloc(bmain, ID_SCE, name);
|
||||
sce->lay = sce->layact = 1;
|
||||
@@ -628,7 +634,16 @@ Scene *BKE_scene_add(Main *bmain, const char *name)
|
||||
|
||||
/* note; in header_info.c the scene copy happens..., if you add more to renderdata it has to be checked there */
|
||||
BKE_scene_add_render_layer(sce, NULL);
|
||||
|
||||
|
||||
/* multiview - stereo */
|
||||
BKE_scene_add_render_view(sce, STEREO_LEFT_NAME);
|
||||
srv = sce->r.views.first;
|
||||
BLI_strncpy(srv->suffix, STEREO_LEFT_SUFFIX, sizeof(srv->suffix));
|
||||
|
||||
BKE_scene_add_render_view(sce, STEREO_RIGHT_NAME);
|
||||
srv = sce->r.views.last;
|
||||
BLI_strncpy(srv->suffix, STEREO_RIGHT_SUFFIX, sizeof(srv->suffix));
|
||||
|
||||
/* game data */
|
||||
sce->gm.stereoflag = STEREO_NOSTEREO;
|
||||
sce->gm.stereomode = STEREO_ANAGLYPH;
|
||||
@@ -701,6 +716,19 @@ Scene *BKE_scene_add(Main *bmain, const char *name)
|
||||
return sce;
|
||||
}
|
||||
|
||||
Base *BKE_scene_base_find_by_name(struct Scene *scene, const char *name)
|
||||
{
|
||||
Base *base;
|
||||
|
||||
for (base = scene->base.first; base; base = base->next) {
|
||||
if (STREQ(base->object->id.name + 2, name)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return base;
|
||||
}
|
||||
|
||||
Base *BKE_scene_base_find(Scene *scene, Object *ob)
|
||||
{
|
||||
return BLI_findptr(&scene->base, ob, offsetof(Base, object));
|
||||
@@ -1892,6 +1920,42 @@ bool BKE_scene_remove_render_layer(Main *bmain, Scene *scene, SceneRenderLayer *
|
||||
return true;
|
||||
}
|
||||
|
||||
/* return default view */
|
||||
SceneRenderView *BKE_scene_add_render_view(Scene *sce, const char *name)
|
||||
{
|
||||
SceneRenderView *srv;
|
||||
|
||||
if (!name)
|
||||
name = DATA_("RenderView");
|
||||
|
||||
srv = MEM_callocN(sizeof(SceneRenderView), "new render view");
|
||||
BLI_strncpy(srv->name, name, sizeof(srv->name));
|
||||
BLI_uniquename(&sce->r.views, srv, DATA_("RenderView"), '.', offsetof(SceneRenderView, name), sizeof(srv->name));
|
||||
BLI_addtail(&sce->r.views, srv);
|
||||
|
||||
return srv;
|
||||
}
|
||||
|
||||
bool BKE_scene_remove_render_view(Scene *scene, SceneRenderView *srv)
|
||||
{
|
||||
const int act = BLI_findindex(&scene->r.views, srv);
|
||||
|
||||
if (act == -1) {
|
||||
return false;
|
||||
}
|
||||
else if (scene->r.views.first == scene->r.views.last) {
|
||||
/* ensure 1 view is kept */
|
||||
return false;
|
||||
}
|
||||
|
||||
BLI_remlink(&scene->r.views, srv);
|
||||
MEM_freeN(srv);
|
||||
|
||||
scene->r.actview = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* render simplification */
|
||||
|
||||
int get_render_subsurf_level(const RenderData *r, int lvl)
|
||||
@@ -2062,3 +2126,281 @@ double BKE_scene_unit_scale(const UnitSettings *unit, const int unit_type, doubl
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
/******************** multiview *************************/
|
||||
|
||||
size_t BKE_scene_multiview_num_views_get(const RenderData *rd)
|
||||
{
|
||||
SceneRenderView *srv;
|
||||
size_t totviews = 0;
|
||||
|
||||
if ((rd->scemode & R_MULTIVIEW) == 0)
|
||||
return 1;
|
||||
|
||||
if (rd->views_format == SCE_VIEWS_FORMAT_STEREO_3D) {
|
||||
if (BLI_findstring(&rd->views, STEREO_LEFT_NAME, offsetof(SceneRenderView, name))) {
|
||||
totviews++;
|
||||
}
|
||||
|
||||
if (BLI_findstring(&rd->views, STEREO_RIGHT_NAME, offsetof(SceneRenderView, name))) {
|
||||
totviews++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (srv = rd->views.first; srv; srv = srv->next) {
|
||||
if ((srv->viewflag & SCE_VIEW_DISABLE) == 0) {
|
||||
totviews++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return totviews;
|
||||
}
|
||||
|
||||
bool BKE_scene_multiview_is_stereo3d(const RenderData *rd)
|
||||
{
|
||||
SceneRenderView *srv[2];
|
||||
|
||||
if ((rd->scemode & R_MULTIVIEW) == 0)
|
||||
return false;
|
||||
|
||||
srv[0] = (SceneRenderView *)BLI_findstring(&rd->views, STEREO_LEFT_NAME, offsetof(SceneRenderView, name));
|
||||
srv[1] = (SceneRenderView *)BLI_findstring(&rd->views, STEREO_RIGHT_NAME, offsetof(SceneRenderView, name));
|
||||
|
||||
return (srv[0] && ((srv[0]->viewflag & SCE_VIEW_DISABLE) == 0) &&
|
||||
srv[1] && ((srv[1]->viewflag & SCE_VIEW_DISABLE) == 0));
|
||||
}
|
||||
|
||||
/* return whether to render this SceneRenderView */
|
||||
bool BKE_scene_multiview_is_render_view_active(const RenderData *rd, const SceneRenderView *srv)
|
||||
{
|
||||
if (srv == NULL)
|
||||
return false;
|
||||
|
||||
if ((rd->scemode & R_MULTIVIEW) == 0)
|
||||
return false;
|
||||
|
||||
if ((srv->viewflag & SCE_VIEW_DISABLE))
|
||||
return false;
|
||||
|
||||
if (rd->views_format == SCE_VIEWS_FORMAT_MULTIVIEW)
|
||||
return true;
|
||||
|
||||
/* SCE_VIEWS_SETUP_BASIC */
|
||||
if (STREQ(srv->name, STEREO_LEFT_NAME) ||
|
||||
STREQ(srv->name, STEREO_RIGHT_NAME))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* return true if viewname is the first or if the name is NULL or not found */
|
||||
bool BKE_scene_multiview_is_render_view_first(const RenderData *rd, const char *viewname)
|
||||
{
|
||||
SceneRenderView *srv;
|
||||
|
||||
if ((rd->scemode & R_MULTIVIEW) == 0)
|
||||
return true;
|
||||
|
||||
if ((!viewname) || (!viewname[0]))
|
||||
return true;
|
||||
|
||||
for (srv = rd->views.first; srv; srv = srv->next) {
|
||||
if (BKE_scene_multiview_is_render_view_active(rd, srv)) {
|
||||
return STREQ(viewname, srv->name);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* return true if viewname is the last or if the name is NULL or not found */
|
||||
bool BKE_scene_multiview_is_render_view_last(const RenderData *rd, const char *viewname)
|
||||
{
|
||||
SceneRenderView *srv;
|
||||
|
||||
if ((rd->scemode & R_MULTIVIEW) == 0)
|
||||
return true;
|
||||
|
||||
if ((!viewname) || (!viewname[0]))
|
||||
return true;
|
||||
|
||||
for (srv = rd->views.last; srv; srv = srv->prev) {
|
||||
if (BKE_scene_multiview_is_render_view_active(rd, srv)) {
|
||||
return STREQ(viewname, srv->name);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
SceneRenderView *BKE_scene_multiview_render_view_findindex(const RenderData *rd, const int view_id)
|
||||
{
|
||||
SceneRenderView *srv;
|
||||
size_t nr;
|
||||
|
||||
if ((rd->scemode & R_MULTIVIEW) == 0)
|
||||
return NULL;
|
||||
|
||||
nr = 0;
|
||||
for (srv = rd->views.first, nr = 0; srv; srv = srv->next) {
|
||||
if (BKE_scene_multiview_is_render_view_active(rd, srv)) {
|
||||
if (nr++ == view_id)
|
||||
return srv;
|
||||
}
|
||||
}
|
||||
return srv;
|
||||
}
|
||||
|
||||
const char *BKE_scene_multiview_render_view_name_get(const RenderData *rd, const int view_id)
|
||||
{
|
||||
SceneRenderView *srv = BKE_scene_multiview_render_view_findindex(rd, view_id);
|
||||
|
||||
if (srv)
|
||||
return srv->name;
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
size_t BKE_scene_multiview_view_id_get(const RenderData *rd, const char *viewname)
|
||||
{
|
||||
SceneRenderView *srv;
|
||||
size_t nr;
|
||||
|
||||
if ((!rd) || ((rd->scemode & R_MULTIVIEW) == 0))
|
||||
return 0;
|
||||
|
||||
if ((!viewname) || (!viewname[0]))
|
||||
return 0;
|
||||
|
||||
nr = 0;
|
||||
for (srv = rd->views.first, nr = 0; srv; srv = srv->next) {
|
||||
if (BKE_scene_multiview_is_render_view_active(rd, srv)) {
|
||||
if (STREQ(viewname, srv->name)) {
|
||||
return nr;
|
||||
}
|
||||
else {
|
||||
nr += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void BKE_scene_multiview_filepath_get(
|
||||
SceneRenderView *srv, const char *filepath,
|
||||
char *r_filepath)
|
||||
{
|
||||
BLI_strncpy(r_filepath, filepath, FILE_MAX);
|
||||
BLI_path_suffix(r_filepath, FILE_MAX, srv->suffix, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* When multiview is not used the filepath is as usual (e.g., ``Image.jpg``).
|
||||
* When multiview is on, even if only one view is enabled the view is incorporated
|
||||
* into the file name (e.g., ``Image_L.jpg``). That allows for the user to re-render
|
||||
* individual views.
|
||||
*/
|
||||
void BKE_scene_multiview_view_filepath_get(
|
||||
const RenderData *rd, const char *filepath, const char *viewname,
|
||||
char *r_filepath)
|
||||
{
|
||||
SceneRenderView *srv;
|
||||
char suffix[FILE_MAX];
|
||||
|
||||
srv = BLI_findstring(&rd->views, viewname, offsetof(SceneRenderView, name));
|
||||
if (srv)
|
||||
BLI_strncpy(suffix, srv->suffix, sizeof(suffix));
|
||||
else
|
||||
BLI_strncpy(suffix, viewname, sizeof(suffix));
|
||||
|
||||
BLI_strncpy(r_filepath, filepath, FILE_MAX);
|
||||
BLI_path_suffix(r_filepath, FILE_MAX, suffix, "");
|
||||
}
|
||||
|
||||
const char *BKE_scene_multiview_view_suffix_get(const RenderData *rd, const char *viewname)
|
||||
{
|
||||
SceneRenderView *srv;
|
||||
|
||||
if ((viewname == NULL) || (viewname[0] == '\0'))
|
||||
return viewname;
|
||||
|
||||
srv = BLI_findstring(&rd->views, viewname, offsetof(SceneRenderView, name));
|
||||
if (srv)
|
||||
return srv->suffix;
|
||||
else
|
||||
return viewname;
|
||||
}
|
||||
|
||||
const char *BKE_scene_multiview_view_id_suffix_get(const RenderData *rd, const size_t view_id)
|
||||
{
|
||||
if ((rd->scemode & R_MULTIVIEW) == 0) {
|
||||
return "";
|
||||
}
|
||||
else {
|
||||
const char *viewname = BKE_scene_multiview_render_view_name_get(rd, view_id);
|
||||
return BKE_scene_multiview_view_suffix_get(rd, viewname);
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_scene_multiview_view_prefix_get(Scene *scene, const char *name, char *rprefix, char **rext)
|
||||
{
|
||||
SceneRenderView *srv;
|
||||
size_t index_act;
|
||||
char *suf_act;
|
||||
const char delims[] = {'.', '\0'};
|
||||
|
||||
rprefix[0] = '\0';
|
||||
|
||||
/* begin of extension */
|
||||
index_act = BLI_str_rpartition(name, delims, rext, &suf_act);
|
||||
BLI_assert(index_act > 0);
|
||||
|
||||
for (srv = scene->r.views.first; srv; srv = srv->next) {
|
||||
if (BKE_scene_multiview_is_render_view_active(&scene->r, srv)) {
|
||||
size_t len = strlen(srv->suffix);
|
||||
if (STREQLEN(*rext - len, srv->suffix, len)) {
|
||||
BLI_strncpy(rprefix, name, strlen(name) - strlen(*rext) - len + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_scene_multiview_videos_dimensions_get(
|
||||
const RenderData *rd, const size_t width, const size_t height,
|
||||
size_t *r_width, size_t *r_height)
|
||||
{
|
||||
if ((rd->scemode & R_MULTIVIEW) &&
|
||||
rd->im_format.views_format == R_IMF_VIEWS_STEREO_3D)
|
||||
{
|
||||
IMB_stereo3d_write_dimensions(
|
||||
rd->im_format.stereo3d_format.display_mode,
|
||||
(rd->im_format.stereo3d_format.flag & S3D_SQUEEZED_FRAME) != 0,
|
||||
width, height,
|
||||
r_width, r_height);
|
||||
}
|
||||
else {
|
||||
*r_width = width;
|
||||
*r_height = height;
|
||||
}
|
||||
}
|
||||
|
||||
size_t BKE_scene_multiview_num_videos_get(const RenderData *rd)
|
||||
{
|
||||
if (BKE_imtype_is_movie(rd->im_format.imtype) == false)
|
||||
return 0;
|
||||
|
||||
if ((rd->scemode & R_MULTIVIEW) == 0)
|
||||
return 1;
|
||||
|
||||
if (rd->im_format.views_format == R_IMF_VIEWS_STEREO_3D) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
/* R_IMF_VIEWS_INDIVIDUAL */
|
||||
return BKE_scene_multiview_num_views_get(rd);
|
||||
}
|
||||
}
|
||||
|
@@ -33,6 +33,7 @@
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "DNA_sequence_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "IMB_moviecache.h"
|
||||
#include "IMB_imbuf.h"
|
||||
@@ -41,6 +42,7 @@
|
||||
#include "BLI_listbase.h"
|
||||
|
||||
#include "BKE_sequencer.h"
|
||||
#include "BKE_scene.h"
|
||||
|
||||
typedef struct SeqCacheKey {
|
||||
struct Sequence *seq;
|
||||
@@ -77,7 +79,9 @@ static bool seq_cmp_render_data(const SeqRenderData *a, const SeqRenderData *b)
|
||||
(a->bmain != b->bmain) ||
|
||||
(a->scene != b->scene) ||
|
||||
(a->motion_blur_shutter != b->motion_blur_shutter) ||
|
||||
(a->motion_blur_samples != b->motion_blur_samples));
|
||||
(a->motion_blur_samples != b->motion_blur_samples) ||
|
||||
(a->scene->r.views_format != b->scene->r.views_format) ||
|
||||
(a->view_id != b->view_id));
|
||||
}
|
||||
|
||||
static unsigned int seq_hash_render_data(const SeqRenderData *a)
|
||||
@@ -89,6 +93,7 @@ static unsigned int seq_hash_render_data(const SeqRenderData *a)
|
||||
rval ^= ((intptr_t) a->scene) << 6;
|
||||
rval ^= (int)(a->motion_blur_shutter * 100.0f) << 10;
|
||||
rval ^= a->motion_blur_samples << 24;
|
||||
rval ^= ((a->scene->r.views_format * 2) + a->view_id) << 32;
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -50,26 +50,34 @@
|
||||
|
||||
/* ********************** general blender movie support ***************************** */
|
||||
|
||||
static int start_stub(Scene *UNUSED(scene), RenderData *UNUSED(rd), int UNUSED(rectx), int UNUSED(recty),
|
||||
ReportList *UNUSED(reports), bool UNUSED(preview))
|
||||
static int start_stub(void *UNUSED(context_v), Scene *UNUSED(scene), RenderData *UNUSED(rd), int UNUSED(rectx), int UNUSED(recty),
|
||||
ReportList *UNUSED(reports), bool UNUSED(preview), const char *UNUSED(suffix))
|
||||
{ return 0; }
|
||||
|
||||
static void end_stub(void)
|
||||
static void end_stub(void *UNUSED(context_v))
|
||||
{}
|
||||
|
||||
static int append_stub(RenderData *UNUSED(rd), int UNUSED(start_frame), int UNUSED(frame), int *UNUSED(pixels),
|
||||
int UNUSED(rectx), int UNUSED(recty), ReportList *UNUSED(reports))
|
||||
static int append_stub(void *UNUSED(context_v), RenderData *UNUSED(rd), int UNUSED(start_frame), int UNUSED(frame), int *UNUSED(pixels),
|
||||
int UNUSED(rectx), int UNUSED(recty), const char *UNUSED(suffix), ReportList *UNUSED(reports))
|
||||
{ return 0; }
|
||||
|
||||
static void *context_create_stub(void)
|
||||
{ return NULL; }
|
||||
|
||||
static void context_free_stub(void *UNUSED(context_v))
|
||||
{}
|
||||
|
||||
#ifdef WITH_AVI
|
||||
# include "AVI_avi.h"
|
||||
|
||||
/* callbacks */
|
||||
static int start_avi(Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports, bool preview);
|
||||
static void end_avi(void);
|
||||
static int append_avi(RenderData *rd, int start_frame, int frame, int *pixels,
|
||||
int rectx, int recty, ReportList *reports);
|
||||
static void filepath_avi(char *string, RenderData *rd, bool preview);
|
||||
static int start_avi(void *context_v, Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports, bool preview, const char *suffix);
|
||||
static void end_avi(void *context_v);
|
||||
static int append_avi(void *context_v, RenderData *rd, int start_frame, int frame, int *pixels,
|
||||
int rectx, int recty, const char *suffix, ReportList *reports);
|
||||
static void filepath_avi(char *string, RenderData *rd, bool preview, const char *suffix);
|
||||
static void *context_create_avi(void);
|
||||
static void context_free_avi(void *context_v);
|
||||
#endif /* WITH_AVI */
|
||||
|
||||
#ifdef WITH_QUICKTIME
|
||||
@@ -93,13 +101,17 @@ bMovieHandle *BKE_movie_handle_get(const char imtype)
|
||||
mh.end_movie = end_stub;
|
||||
mh.get_next_frame = NULL;
|
||||
mh.get_movie_path = NULL;
|
||||
|
||||
mh.context_create = context_create_stub;
|
||||
mh.context_free = context_free_stub;
|
||||
|
||||
/* set the default handle, as builtin */
|
||||
#ifdef WITH_AVI
|
||||
mh.start_movie = start_avi;
|
||||
mh.append_movie = append_avi;
|
||||
mh.end_movie = end_avi;
|
||||
mh.get_movie_path = filepath_avi;
|
||||
mh.context_create = context_create_avi;
|
||||
mh.context_free = context_free_avi;
|
||||
#endif
|
||||
|
||||
/* do the platform specific handles */
|
||||
@@ -109,6 +121,8 @@ bMovieHandle *BKE_movie_handle_get(const char imtype)
|
||||
mh.append_movie = append_qt;
|
||||
mh.end_movie = end_qt;
|
||||
mh.get_movie_path = filepath_qt;
|
||||
mh.context_create = context_create_qt;
|
||||
mh.context_free = context_free_qt;
|
||||
}
|
||||
#endif
|
||||
#ifdef WITH_FFMPEG
|
||||
@@ -117,6 +131,8 @@ bMovieHandle *BKE_movie_handle_get(const char imtype)
|
||||
mh.append_movie = BKE_ffmpeg_append;
|
||||
mh.end_movie = BKE_ffmpeg_end;
|
||||
mh.get_movie_path = BKE_ffmpeg_filepath_get;
|
||||
mh.context_create = BKE_ffmpeg_context_create;
|
||||
mh.context_free = BKE_ffmpeg_context_free;
|
||||
}
|
||||
#endif
|
||||
#ifdef WITH_FRAMESERVER
|
||||
@@ -125,6 +141,8 @@ bMovieHandle *BKE_movie_handle_get(const char imtype)
|
||||
mh.append_movie = BKE_frameserver_append;
|
||||
mh.end_movie = BKE_frameserver_end;
|
||||
mh.get_next_frame = BKE_frameserver_loop;
|
||||
mh.context_create = BKE_frameserver_context_create;
|
||||
mh.context_free = BKE_frameserver_context_free;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -137,9 +155,7 @@ bMovieHandle *BKE_movie_handle_get(const char imtype)
|
||||
|
||||
#ifdef WITH_AVI
|
||||
|
||||
static AviMovie *avi = NULL;
|
||||
|
||||
static void filepath_avi(char *string, RenderData *rd, bool preview)
|
||||
static void filepath_avi(char *string, RenderData *rd, bool preview, const char *suffix)
|
||||
{
|
||||
int sfra, efra;
|
||||
|
||||
@@ -170,27 +186,27 @@ static void filepath_avi(char *string, RenderData *rd, bool preview)
|
||||
BLI_path_frame_range(string, sfra, efra, 4);
|
||||
}
|
||||
}
|
||||
|
||||
BLI_path_suffix(string, FILE_MAX, suffix, "");
|
||||
}
|
||||
|
||||
static int start_avi(Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports, bool preview)
|
||||
static int start_avi(void *context_v, Scene *UNUSED(scene), RenderData *rd, int rectx, int recty,
|
||||
ReportList *reports, bool preview, const char *suffix)
|
||||
{
|
||||
int x, y;
|
||||
char name[256];
|
||||
AviFormat format;
|
||||
int quality;
|
||||
double framerate;
|
||||
|
||||
(void)scene; /* unused */
|
||||
|
||||
filepath_avi(name, rd, preview);
|
||||
AviMovie *avi = context_v;
|
||||
|
||||
filepath_avi(name, rd, preview, suffix);
|
||||
|
||||
x = rectx;
|
||||
y = recty;
|
||||
|
||||
quality = rd->im_format.quality;
|
||||
framerate = (double) rd->frs_sec / (double) rd->frs_sec_base;
|
||||
|
||||
avi = MEM_mallocN(sizeof(AviMovie), "avimovie");
|
||||
|
||||
if (rd->im_format.imtype != R_IMF_IMTYPE_AVIJPEG) format = AVI_FORMAT_AVI_RGB;
|
||||
else format = AVI_FORMAT_MJPEG;
|
||||
@@ -216,12 +232,13 @@ static int start_avi(Scene *scene, RenderData *rd, int rectx, int recty, ReportL
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int append_avi(RenderData *UNUSED(rd), int start_frame, int frame, int *pixels,
|
||||
int rectx, int recty, ReportList *UNUSED(reports))
|
||||
static int append_avi(void *context_v, RenderData *UNUSED(rd), int start_frame, int frame, int *pixels,
|
||||
int rectx, int recty, const char *UNUSED(suffix), ReportList *UNUSED(reports))
|
||||
{
|
||||
unsigned int *rt1, *rt2, *rectot;
|
||||
int x, y;
|
||||
char *cp, rt;
|
||||
AviMovie *avi = context_v;
|
||||
|
||||
if (avi == NULL)
|
||||
return 0;
|
||||
@@ -252,22 +269,37 @@ static int append_avi(RenderData *UNUSED(rd), int start_frame, int frame, int *p
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void end_avi(void)
|
||||
static void end_avi(void *context_v)
|
||||
{
|
||||
AviMovie *avi = context_v;
|
||||
|
||||
if (avi == NULL) return;
|
||||
|
||||
AVI_close_compress(avi);
|
||||
MEM_freeN(avi);
|
||||
avi = NULL;
|
||||
}
|
||||
|
||||
static void *context_create_avi(void)
|
||||
{
|
||||
AviMovie *avi = MEM_mallocN(sizeof(AviMovie), "avimovie");
|
||||
return avi;
|
||||
}
|
||||
|
||||
static void context_free_avi(void *context_v)
|
||||
{
|
||||
AviMovie *avi = context_v;
|
||||
if (avi) {
|
||||
MEM_freeN(avi);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* WITH_AVI */
|
||||
|
||||
/* similar to BKE_image_path_from_imformat() */
|
||||
void BKE_movie_filepath_get(char *string, RenderData *rd, bool preview)
|
||||
void BKE_movie_filepath_get(char *string, RenderData *rd, bool preview, const char *suffix)
|
||||
{
|
||||
bMovieHandle *mh = BKE_movie_handle_get(rd->im_format.imtype);
|
||||
if (mh->get_movie_path)
|
||||
mh->get_movie_path(string, rd, preview);
|
||||
mh->get_movie_path(string, rd, preview, suffix);
|
||||
else
|
||||
string[0] = '\0';
|
||||
}
|
||||
|
@@ -61,36 +61,38 @@
|
||||
|
||||
#include "ffmpeg_compat.h"
|
||||
|
||||
static int ffmpeg_type = 0;
|
||||
static int ffmpeg_codec = AV_CODEC_ID_MPEG4;
|
||||
static int ffmpeg_audio_codec = AV_CODEC_ID_NONE;
|
||||
static int ffmpeg_video_bitrate = 1150;
|
||||
static int ffmpeg_audio_bitrate = 128;
|
||||
static int ffmpeg_gop_size = 12;
|
||||
static int ffmpeg_autosplit = 0;
|
||||
static int ffmpeg_autosplit_count = 0;
|
||||
static bool ffmpeg_preview = false;
|
||||
typedef struct FFMpegContext {
|
||||
int ffmpeg_type;
|
||||
int ffmpeg_codec;
|
||||
int ffmpeg_audio_codec;
|
||||
int ffmpeg_video_bitrate;
|
||||
int ffmpeg_audio_bitrate;
|
||||
int ffmpeg_gop_size;
|
||||
int ffmpeg_autosplit;
|
||||
int ffmpeg_autosplit_count;
|
||||
bool ffmpeg_preview;
|
||||
|
||||
static AVFormatContext *outfile = 0;
|
||||
static AVStream *video_stream = 0;
|
||||
static AVStream *audio_stream = 0;
|
||||
static AVFrame *current_frame = 0;
|
||||
static struct SwsContext *img_convert_ctx = 0;
|
||||
AVFormatContext *outfile;
|
||||
AVStream *video_stream;
|
||||
AVStream *audio_stream;
|
||||
AVFrame *current_frame;
|
||||
struct SwsContext *img_convert_ctx;
|
||||
|
||||
static uint8_t *audio_input_buffer = 0;
|
||||
static uint8_t *audio_deinterleave_buffer = 0;
|
||||
static int audio_input_samples = 0;
|
||||
uint8_t *audio_input_buffer;
|
||||
uint8_t *audio_deinterleave_buffer;
|
||||
int audio_input_samples;
|
||||
#ifndef FFMPEG_HAVE_ENCODE_AUDIO2
|
||||
static uint8_t *audio_output_buffer = 0;
|
||||
static int audio_outbuf_size = 0;
|
||||
uint8_t *audio_output_buffer;
|
||||
int audio_outbuf_size;
|
||||
#endif
|
||||
static double audio_time = 0.0f;
|
||||
static bool audio_deinterleave = false;
|
||||
static int audio_sample_size = 0;
|
||||
double audio_time;
|
||||
bool audio_deinterleave;
|
||||
int audio_sample_size;
|
||||
|
||||
#ifdef WITH_AUDASPACE
|
||||
static AUD_Device *audio_mixdown_device = 0;
|
||||
AUD_Device *audio_mixdown_device;
|
||||
#endif
|
||||
} FFMpegContext;
|
||||
|
||||
#define FFMPEG_AUTOSPLIT_SIZE 2000000000
|
||||
|
||||
@@ -99,6 +101,7 @@ static AUD_Device *audio_mixdown_device = 0;
|
||||
static void ffmpeg_dict_set_int(AVDictionary **dict, const char *key, int value);
|
||||
static void ffmpeg_dict_set_float(AVDictionary **dict, const char *key, float value);
|
||||
static void ffmpeg_set_expert_options(RenderData *rd);
|
||||
static void ffmpeg_filepath_get(FFMpegContext *context, char *string, struct RenderData *rd, bool preview, const char *suffix);
|
||||
|
||||
/* Delete a picture buffer */
|
||||
|
||||
@@ -117,50 +120,50 @@ static int request_float_audio_buffer(int codec_id)
|
||||
}
|
||||
|
||||
#ifdef WITH_AUDASPACE
|
||||
static int write_audio_frame(void)
|
||||
static int write_audio_frame(FFMpegContext *context)
|
||||
{
|
||||
AVCodecContext *c = NULL;
|
||||
AVPacket pkt;
|
||||
AVFrame *frame = NULL;
|
||||
int got_output = 0;
|
||||
|
||||
c = audio_stream->codec;
|
||||
c = context->audio_stream->codec;
|
||||
|
||||
av_init_packet(&pkt);
|
||||
pkt.size = 0;
|
||||
pkt.data = NULL;
|
||||
|
||||
AUD_readDevice(audio_mixdown_device, audio_input_buffer, audio_input_samples);
|
||||
audio_time += (double) audio_input_samples / (double) c->sample_rate;
|
||||
AUD_readDevice(context->audio_mixdown_device, context->audio_input_buffer, context->audio_input_samples);
|
||||
context->audio_time += (double) context->audio_input_samples / (double) c->sample_rate;
|
||||
|
||||
#ifdef FFMPEG_HAVE_ENCODE_AUDIO2
|
||||
frame = avcodec_alloc_frame();
|
||||
avcodec_get_frame_defaults(frame);
|
||||
frame->pts = audio_time / av_q2d(c->time_base);
|
||||
frame->nb_samples = audio_input_samples;
|
||||
frame->pts = context->audio_time / av_q2d(c->time_base);
|
||||
frame->nb_samples = context->audio_input_samples;
|
||||
frame->format = c->sample_fmt;
|
||||
#ifdef FFMPEG_HAVE_FRAME_CHANNEL_LAYOUT
|
||||
frame->channel_layout = c->channel_layout;
|
||||
#endif
|
||||
|
||||
if (audio_deinterleave) {
|
||||
if (context->audio_deinterleave) {
|
||||
int channel, i;
|
||||
uint8_t *temp;
|
||||
|
||||
for (channel = 0; channel < c->channels; channel++) {
|
||||
for (i = 0; i < frame->nb_samples; i++) {
|
||||
memcpy(audio_deinterleave_buffer + (i + channel * frame->nb_samples) * audio_sample_size,
|
||||
audio_input_buffer + (c->channels * i + channel) * audio_sample_size, audio_sample_size);
|
||||
memcpy(context->audio_deinterleave_buffer + (i + channel * frame->nb_samples) * context->audio_sample_size,
|
||||
context->audio_input_buffer + (c->channels * i + channel) * context->audio_sample_size, context->audio_sample_size);
|
||||
}
|
||||
}
|
||||
|
||||
temp = audio_deinterleave_buffer;
|
||||
audio_deinterleave_buffer = audio_input_buffer;
|
||||
audio_input_buffer = temp;
|
||||
temp = context->audio_deinterleave_buffer;
|
||||
context->audio_deinterleave_buffer = context->audio_input_buffer;
|
||||
context->audio_input_buffer = temp;
|
||||
}
|
||||
|
||||
avcodec_fill_audio_frame(frame, c->channels, c->sample_fmt, audio_input_buffer,
|
||||
audio_input_samples * c->channels * audio_sample_size, 1);
|
||||
avcodec_fill_audio_frame(frame, c->channels, c->sample_fmt, context->audio_input_buffer,
|
||||
context->audio_input_samples * c->channels * context->audio_sample_size, 1);
|
||||
|
||||
if (avcodec_encode_audio2(c, &pkt, frame, &got_output) < 0) {
|
||||
// XXX error("Error writing audio packet");
|
||||
@@ -172,30 +175,30 @@ static int write_audio_frame(void)
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
pkt.size = avcodec_encode_audio(c, audio_output_buffer, audio_outbuf_size, (short *) audio_input_buffer);
|
||||
pkt.size = avcodec_encode_audio(c, context->audio_output_buffer, context->audio_outbuf_size, (short *) context->audio_input_buffer);
|
||||
|
||||
if (pkt.size < 0) {
|
||||
// XXX error("Error writing audio packet");
|
||||
return -1;
|
||||
}
|
||||
|
||||
pkt.data = audio_output_buffer;
|
||||
pkt.data = context->audio_output_buffer;
|
||||
got_output = 1;
|
||||
#endif
|
||||
|
||||
if (got_output) {
|
||||
if (pkt.pts != AV_NOPTS_VALUE)
|
||||
pkt.pts = av_rescale_q(pkt.pts, c->time_base, audio_stream->time_base);
|
||||
pkt.pts = av_rescale_q(pkt.pts, c->time_base, context->audio_stream->time_base);
|
||||
if (pkt.dts != AV_NOPTS_VALUE)
|
||||
pkt.dts = av_rescale_q(pkt.dts, c->time_base, audio_stream->time_base);
|
||||
pkt.dts = av_rescale_q(pkt.dts, c->time_base, context->audio_stream->time_base);
|
||||
if (pkt.duration > 0)
|
||||
pkt.duration = av_rescale_q(pkt.duration, c->time_base, audio_stream->time_base);
|
||||
pkt.duration = av_rescale_q(pkt.duration, c->time_base, context->audio_stream->time_base);
|
||||
|
||||
pkt.stream_index = audio_stream->index;
|
||||
pkt.stream_index = context->audio_stream->index;
|
||||
|
||||
pkt.flags |= AV_PKT_FLAG_KEY;
|
||||
|
||||
if (av_interleaved_write_frame(outfile, &pkt) != 0) {
|
||||
if (av_interleaved_write_frame(context->outfile, &pkt) != 0) {
|
||||
fprintf(stderr, "Error writing audio packet!\n");
|
||||
if (frame)
|
||||
avcodec_free_frame(&frame);
|
||||
@@ -302,11 +305,11 @@ static const char **get_file_extensions(int format)
|
||||
}
|
||||
|
||||
/* Write a frame to the output file */
|
||||
static int write_video_frame(RenderData *rd, int cfra, AVFrame *frame, ReportList *reports)
|
||||
static int write_video_frame(FFMpegContext *context, RenderData *rd, int cfra, AVFrame *frame, ReportList *reports)
|
||||
{
|
||||
int got_output;
|
||||
int ret, success = 1;
|
||||
AVCodecContext *c = video_stream->codec;
|
||||
AVCodecContext *c = context->video_stream->codec;
|
||||
AVPacket packet = { 0 };
|
||||
|
||||
av_init_packet(&packet);
|
||||
@@ -321,22 +324,22 @@ static int write_video_frame(RenderData *rd, int cfra, AVFrame *frame, ReportLis
|
||||
|
||||
if (ret >= 0 && got_output) {
|
||||
if (packet.pts != AV_NOPTS_VALUE) {
|
||||
packet.pts = av_rescale_q(packet.pts, c->time_base, video_stream->time_base);
|
||||
packet.pts = av_rescale_q(packet.pts, c->time_base, context->video_stream->time_base);
|
||||
PRINT("Video Frame PTS: %d\n", (int)packet.pts);
|
||||
}
|
||||
else {
|
||||
PRINT("Video Frame PTS: not set\n");
|
||||
}
|
||||
if (packet.dts != AV_NOPTS_VALUE) {
|
||||
packet.dts = av_rescale_q(packet.dts, c->time_base, video_stream->time_base);
|
||||
packet.dts = av_rescale_q(packet.dts, c->time_base, context->video_stream->time_base);
|
||||
PRINT("Video Frame DTS: %d\n", (int)packet.dts);
|
||||
}
|
||||
else {
|
||||
PRINT("Video Frame DTS: not set\n");
|
||||
}
|
||||
|
||||
packet.stream_index = video_stream->index;
|
||||
ret = av_interleaved_write_frame(outfile, &packet);
|
||||
packet.stream_index = context->video_stream->index;
|
||||
ret = av_interleaved_write_frame(context->outfile, &packet);
|
||||
success = (ret == 0);
|
||||
}
|
||||
else if (ret < 0) {
|
||||
@@ -350,11 +353,11 @@ static int write_video_frame(RenderData *rd, int cfra, AVFrame *frame, ReportLis
|
||||
}
|
||||
|
||||
/* read and encode a frame of audio from the buffer */
|
||||
static AVFrame *generate_video_frame(uint8_t *pixels, ReportList *reports)
|
||||
static AVFrame *generate_video_frame(FFMpegContext *context, uint8_t *pixels, ReportList *reports)
|
||||
{
|
||||
uint8_t *rendered_frame;
|
||||
|
||||
AVCodecContext *c = video_stream->codec;
|
||||
AVCodecContext *c = context->video_stream->codec;
|
||||
int width = c->width;
|
||||
int height = c->height;
|
||||
AVFrame *rgb_frame;
|
||||
@@ -367,7 +370,7 @@ static AVFrame *generate_video_frame(uint8_t *pixels, ReportList *reports)
|
||||
}
|
||||
}
|
||||
else {
|
||||
rgb_frame = current_frame;
|
||||
rgb_frame = context->current_frame;
|
||||
}
|
||||
|
||||
rendered_frame = pixels;
|
||||
@@ -411,17 +414,17 @@ static AVFrame *generate_video_frame(uint8_t *pixels, ReportList *reports)
|
||||
}
|
||||
|
||||
if (c->pix_fmt != PIX_FMT_BGR32) {
|
||||
sws_scale(img_convert_ctx, (const uint8_t *const *) rgb_frame->data,
|
||||
sws_scale(context->img_convert_ctx, (const uint8_t *const *) rgb_frame->data,
|
||||
rgb_frame->linesize, 0, c->height,
|
||||
current_frame->data, current_frame->linesize);
|
||||
context->current_frame->data, context->current_frame->linesize);
|
||||
delete_picture(rgb_frame);
|
||||
}
|
||||
|
||||
current_frame->format = PIX_FMT_BGR32;
|
||||
current_frame->width = width;
|
||||
current_frame->height = height;
|
||||
context->current_frame->format = PIX_FMT_BGR32;
|
||||
context->current_frame->width = width;
|
||||
context->current_frame->height = height;
|
||||
|
||||
return current_frame;
|
||||
return context->current_frame;
|
||||
}
|
||||
|
||||
static void set_ffmpeg_property_option(AVCodecContext *c, IDProperty *prop, AVDictionary **dictionary)
|
||||
@@ -516,7 +519,7 @@ static void set_ffmpeg_properties(RenderData *rd, AVCodecContext *c, const char
|
||||
|
||||
/* prepare a video stream for the output file */
|
||||
|
||||
static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContext *of,
|
||||
static AVStream *alloc_video_stream(FFMpegContext *context, RenderData *rd, int codec_id, AVFormatContext *of,
|
||||
int rectx, int recty, char *error, int error_size)
|
||||
{
|
||||
AVStream *st;
|
||||
@@ -542,7 +545,7 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
|
||||
c->height = recty;
|
||||
|
||||
/* FIXME: Really bad hack (tm) for NTSC support */
|
||||
if (ffmpeg_type == FFMPEG_DV && rd->frs_sec != 25) {
|
||||
if (context->ffmpeg_type == FFMPEG_DV && rd->frs_sec != 25) {
|
||||
c->time_base.den = 2997;
|
||||
c->time_base.num = 100;
|
||||
}
|
||||
@@ -555,8 +558,8 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
|
||||
c->time_base.num = ((double) rd->frs_sec_base) * 100000;
|
||||
}
|
||||
|
||||
c->gop_size = ffmpeg_gop_size;
|
||||
c->bit_rate = ffmpeg_video_bitrate * 1000;
|
||||
c->gop_size = context->ffmpeg_gop_size;
|
||||
c->bit_rate = context->ffmpeg_video_bitrate * 1000;
|
||||
c->rc_max_rate = rd->ffcodecdata.rc_max_rate * 1000;
|
||||
c->rc_min_rate = rd->ffcodecdata.rc_min_rate * 1000;
|
||||
c->rc_buffer_size = rd->ffcodecdata.rc_buffer_size * 1024;
|
||||
@@ -585,7 +588,7 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
|
||||
c->pix_fmt = PIX_FMT_YUV422P;
|
||||
}
|
||||
|
||||
if (ffmpeg_type == FFMPEG_XVID) {
|
||||
if (context->ffmpeg_type == FFMPEG_XVID) {
|
||||
/* arghhhh ... */
|
||||
c->pix_fmt = PIX_FMT_YUV420P;
|
||||
c->codec_tag = (('D' << 24) + ('I' << 16) + ('V' << 8) + 'X');
|
||||
@@ -655,14 +658,14 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
|
||||
}
|
||||
av_dict_free(&opts);
|
||||
|
||||
current_frame = alloc_picture(c->pix_fmt, c->width, c->height);
|
||||
context->current_frame = alloc_picture(c->pix_fmt, c->width, c->height);
|
||||
|
||||
img_convert_ctx = sws_getContext(c->width, c->height, PIX_FMT_BGR32, c->width, c->height, c->pix_fmt, SWS_BICUBIC,
|
||||
context->img_convert_ctx = sws_getContext(c->width, c->height, PIX_FMT_BGR32, c->width, c->height, c->pix_fmt, SWS_BICUBIC,
|
||||
NULL, NULL, NULL);
|
||||
return st;
|
||||
}
|
||||
|
||||
static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContext *of, char *error, int error_size)
|
||||
static AVStream *alloc_audio_stream(FFMpegContext *context, RenderData *rd, int codec_id, AVFormatContext *of, char *error, int error_size)
|
||||
{
|
||||
AVStream *st;
|
||||
AVCodecContext *c;
|
||||
@@ -680,7 +683,7 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex
|
||||
c->codec_type = AVMEDIA_TYPE_AUDIO;
|
||||
|
||||
c->sample_rate = rd->ffcodecdata.audio_mixrate;
|
||||
c->bit_rate = ffmpeg_audio_bitrate * 1000;
|
||||
c->bit_rate = context->ffmpeg_audio_bitrate * 1000;
|
||||
c->sample_fmt = AV_SAMPLE_FMT_S16;
|
||||
c->channels = rd->ffcodecdata.audio_channels;
|
||||
|
||||
@@ -747,35 +750,35 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex
|
||||
st->codec->time_base.den = st->codec->sample_rate;
|
||||
|
||||
#ifndef FFMPEG_HAVE_ENCODE_AUDIO2
|
||||
audio_outbuf_size = FF_MIN_BUFFER_SIZE;
|
||||
context->audio_outbuf_size = FF_MIN_BUFFER_SIZE;
|
||||
#endif
|
||||
|
||||
if (c->frame_size == 0)
|
||||
// used to be if ((c->codec_id >= CODEC_ID_PCM_S16LE) && (c->codec_id <= CODEC_ID_PCM_DVD))
|
||||
// not sure if that is needed anymore, so let's try out if there are any
|
||||
// complaints regarding some ffmpeg versions users might have
|
||||
audio_input_samples = FF_MIN_BUFFER_SIZE * 8 / c->bits_per_coded_sample / c->channels;
|
||||
context->audio_input_samples = FF_MIN_BUFFER_SIZE * 8 / c->bits_per_coded_sample / c->channels;
|
||||
else {
|
||||
audio_input_samples = c->frame_size;
|
||||
context->audio_input_samples = c->frame_size;
|
||||
#ifndef FFMPEG_HAVE_ENCODE_AUDIO2
|
||||
if (c->frame_size * c->channels * sizeof(int16_t) * 4 > audio_outbuf_size)
|
||||
audio_outbuf_size = c->frame_size * c->channels * sizeof(int16_t) * 4;
|
||||
if (c->frame_size * c->channels * sizeof(int16_t) * 4 > context->audio_outbuf_size)
|
||||
context->audio_outbuf_size = c->frame_size * c->channels * sizeof(int16_t) * 4;
|
||||
#endif
|
||||
}
|
||||
|
||||
audio_deinterleave = av_sample_fmt_is_planar(c->sample_fmt);
|
||||
context->audio_deinterleave = av_sample_fmt_is_planar(c->sample_fmt);
|
||||
|
||||
audio_sample_size = av_get_bytes_per_sample(c->sample_fmt);
|
||||
context->audio_sample_size = av_get_bytes_per_sample(c->sample_fmt);
|
||||
|
||||
audio_input_buffer = (uint8_t *) av_malloc(audio_input_samples * c->channels * audio_sample_size);
|
||||
context->audio_input_buffer = (uint8_t *) av_malloc(context->audio_input_samples * c->channels * context->audio_sample_size);
|
||||
#ifndef FFMPEG_HAVE_ENCODE_AUDIO2
|
||||
audio_output_buffer = (uint8_t *) av_malloc(audio_outbuf_size);
|
||||
context->audio_output_buffer = (uint8_t *) av_malloc(context->audio_outbuf_size);
|
||||
#endif
|
||||
|
||||
if (audio_deinterleave)
|
||||
audio_deinterleave_buffer = (uint8_t *) av_malloc(audio_input_samples * c->channels * audio_sample_size);
|
||||
if (context->audio_deinterleave)
|
||||
context->audio_deinterleave_buffer = (uint8_t *) av_malloc(context->audio_input_samples * c->channels * context->audio_sample_size);
|
||||
|
||||
audio_time = 0.0f;
|
||||
context->audio_time = 0.0f;
|
||||
|
||||
return st;
|
||||
}
|
||||
@@ -799,7 +802,7 @@ static void ffmpeg_dict_set_float(AVDictionary **dict, const char *key, float va
|
||||
av_dict_set(dict, key, buffer, 0);
|
||||
}
|
||||
|
||||
static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, ReportList *reports)
|
||||
static int start_ffmpeg_impl(FFMpegContext *context, struct RenderData *rd, int rectx, int recty, const char *suffix, ReportList *reports)
|
||||
{
|
||||
/* Handle to the output file */
|
||||
AVFormatContext *of;
|
||||
@@ -808,26 +811,26 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
|
||||
char name[256], error[1024];
|
||||
const char **exts;
|
||||
|
||||
ffmpeg_type = rd->ffcodecdata.type;
|
||||
ffmpeg_codec = rd->ffcodecdata.codec;
|
||||
ffmpeg_audio_codec = rd->ffcodecdata.audio_codec;
|
||||
ffmpeg_video_bitrate = rd->ffcodecdata.video_bitrate;
|
||||
ffmpeg_audio_bitrate = rd->ffcodecdata.audio_bitrate;
|
||||
ffmpeg_gop_size = rd->ffcodecdata.gop_size;
|
||||
ffmpeg_autosplit = rd->ffcodecdata.flags & FFMPEG_AUTOSPLIT_OUTPUT;
|
||||
|
||||
context->ffmpeg_type = rd->ffcodecdata.type;
|
||||
context->ffmpeg_codec = rd->ffcodecdata.codec;
|
||||
context->ffmpeg_audio_codec = rd->ffcodecdata.audio_codec;
|
||||
context->ffmpeg_video_bitrate = rd->ffcodecdata.video_bitrate;
|
||||
context->ffmpeg_audio_bitrate = rd->ffcodecdata.audio_bitrate;
|
||||
context->ffmpeg_gop_size = rd->ffcodecdata.gop_size;
|
||||
context->ffmpeg_autosplit = rd->ffcodecdata.flags & FFMPEG_AUTOSPLIT_OUTPUT;
|
||||
|
||||
/* Determine the correct filename */
|
||||
BKE_ffmpeg_filepath_get(name, rd, ffmpeg_preview);
|
||||
ffmpeg_filepath_get(context, name, rd, context->ffmpeg_preview, suffix);
|
||||
PRINT("Starting output to %s(ffmpeg)...\n"
|
||||
" Using type=%d, codec=%d, audio_codec=%d,\n"
|
||||
" video_bitrate=%d, audio_bitrate=%d,\n"
|
||||
" gop_size=%d, autosplit=%d\n"
|
||||
" render width=%d, render height=%d\n",
|
||||
name, ffmpeg_type, ffmpeg_codec, ffmpeg_audio_codec,
|
||||
ffmpeg_video_bitrate, ffmpeg_audio_bitrate,
|
||||
ffmpeg_gop_size, ffmpeg_autosplit, rectx, recty);
|
||||
name, context->ffmpeg_type, context->ffmpeg_codec, context->ffmpeg_audio_codec,
|
||||
context->ffmpeg_video_bitrate, context->ffmpeg_audio_bitrate,
|
||||
context->ffmpeg_gop_size, context->ffmpeg_autosplit, rectx, recty);
|
||||
|
||||
exts = get_file_extensions(ffmpeg_type);
|
||||
exts = get_file_extensions(context->ffmpeg_type);
|
||||
if (!exts) {
|
||||
BKE_report(reports, RPT_ERROR, "No valid formats found");
|
||||
return 0;
|
||||
@@ -846,7 +849,7 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
|
||||
|
||||
of->oformat = fmt;
|
||||
of->packet_size = rd->ffcodecdata.mux_packet_size;
|
||||
if (ffmpeg_audio_codec != AV_CODEC_ID_NONE) {
|
||||
if (context->ffmpeg_audio_codec != AV_CODEC_ID_NONE) {
|
||||
ffmpeg_dict_set_int(&opts, "muxrate", rd->ffcodecdata.mux_rate);
|
||||
}
|
||||
else {
|
||||
@@ -857,15 +860,15 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
|
||||
|
||||
of->max_delay = (int)(0.7 * AV_TIME_BASE);
|
||||
|
||||
fmt->audio_codec = ffmpeg_audio_codec;
|
||||
fmt->audio_codec = context->ffmpeg_audio_codec;
|
||||
|
||||
BLI_strncpy(of->filename, name, sizeof(of->filename));
|
||||
/* set the codec to the user's selection */
|
||||
switch (ffmpeg_type) {
|
||||
switch (context->ffmpeg_type) {
|
||||
case FFMPEG_AVI:
|
||||
case FFMPEG_MOV:
|
||||
case FFMPEG_MKV:
|
||||
fmt->video_codec = ffmpeg_codec;
|
||||
fmt->video_codec = context->ffmpeg_codec;
|
||||
break;
|
||||
case FFMPEG_OGG:
|
||||
fmt->video_codec = AV_CODEC_ID_THEORA;
|
||||
@@ -908,9 +911,9 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
|
||||
}
|
||||
}
|
||||
|
||||
if (ffmpeg_type == FFMPEG_DV) {
|
||||
if (context->ffmpeg_type == FFMPEG_DV) {
|
||||
fmt->audio_codec = AV_CODEC_ID_PCM_S16LE;
|
||||
if (ffmpeg_audio_codec != AV_CODEC_ID_NONE && rd->ffcodecdata.audio_mixrate != 48000 && rd->ffcodecdata.audio_channels != 2) {
|
||||
if (context->ffmpeg_audio_codec != AV_CODEC_ID_NONE && rd->ffcodecdata.audio_mixrate != 48000 && rd->ffcodecdata.audio_channels != 2) {
|
||||
BKE_report(reports, RPT_ERROR, "FFMPEG only supports 48khz / stereo audio for DV!");
|
||||
av_dict_free(&opts);
|
||||
return 0;
|
||||
@@ -918,9 +921,9 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
|
||||
}
|
||||
|
||||
if (fmt->video_codec != AV_CODEC_ID_NONE) {
|
||||
video_stream = alloc_video_stream(rd, fmt->video_codec, of, rectx, recty, error, sizeof(error));
|
||||
PRINT("alloc video stream %p\n", video_stream);
|
||||
if (!video_stream) {
|
||||
context->video_stream = alloc_video_stream(context, rd, fmt->video_codec, of, rectx, recty, error, sizeof(error));
|
||||
PRINT("alloc video stream %p\n", context->video_stream);
|
||||
if (!context->video_stream) {
|
||||
if (error[0])
|
||||
BKE_report(reports, RPT_ERROR, error);
|
||||
else
|
||||
@@ -931,9 +934,9 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
|
||||
}
|
||||
}
|
||||
|
||||
if (ffmpeg_audio_codec != AV_CODEC_ID_NONE) {
|
||||
audio_stream = alloc_audio_stream(rd, fmt->audio_codec, of, error, sizeof(error));
|
||||
if (!audio_stream) {
|
||||
if (context->ffmpeg_audio_codec != AV_CODEC_ID_NONE) {
|
||||
context->audio_stream = alloc_audio_stream(context, rd, fmt->audio_codec, of, error, sizeof(error));
|
||||
if (!context->audio_stream) {
|
||||
if (error[0])
|
||||
BKE_report(reports, RPT_ERROR, error);
|
||||
else
|
||||
@@ -956,7 +959,7 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
|
||||
return 0;
|
||||
}
|
||||
|
||||
outfile = of;
|
||||
context->outfile = of;
|
||||
av_dump_format(of, 0, name, 1);
|
||||
av_dict_free(&opts);
|
||||
|
||||
@@ -980,11 +983,11 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
|
||||
* parameter.
|
||||
* </p>
|
||||
*/
|
||||
static void flush_ffmpeg(void)
|
||||
static void flush_ffmpeg(FFMpegContext *context)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
AVCodecContext *c = video_stream->codec;
|
||||
AVCodecContext *c = context->video_stream->codec;
|
||||
/* get the delayed frames */
|
||||
while (1) {
|
||||
int got_output;
|
||||
@@ -1000,28 +1003,28 @@ static void flush_ffmpeg(void)
|
||||
break;
|
||||
}
|
||||
if (packet.pts != AV_NOPTS_VALUE) {
|
||||
packet.pts = av_rescale_q(packet.pts, c->time_base, video_stream->time_base);
|
||||
packet.pts = av_rescale_q(packet.pts, c->time_base, context->video_stream->time_base);
|
||||
PRINT("Video Frame PTS: %d\n", (int) packet.pts);
|
||||
}
|
||||
else {
|
||||
PRINT("Video Frame PTS: not set\n");
|
||||
}
|
||||
if (packet.dts != AV_NOPTS_VALUE) {
|
||||
packet.dts = av_rescale_q(packet.dts, c->time_base, video_stream->time_base);
|
||||
packet.dts = av_rescale_q(packet.dts, c->time_base, context->video_stream->time_base);
|
||||
PRINT("Video Frame DTS: %d\n", (int) packet.dts);
|
||||
}
|
||||
else {
|
||||
PRINT("Video Frame DTS: not set\n");
|
||||
}
|
||||
|
||||
packet.stream_index = video_stream->index;
|
||||
ret = av_interleaved_write_frame(outfile, &packet);
|
||||
packet.stream_index = context->video_stream->index;
|
||||
ret = av_interleaved_write_frame(context->outfile, &packet);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Error writing delayed frame %d\n", ret);
|
||||
break;
|
||||
}
|
||||
}
|
||||
avcodec_flush_buffers(video_stream->codec);
|
||||
avcodec_flush_buffers(context->video_stream->codec);
|
||||
}
|
||||
|
||||
/* **********************************************************************
|
||||
@@ -1029,7 +1032,7 @@ static void flush_ffmpeg(void)
|
||||
* ********************************************************************** */
|
||||
|
||||
/* Get the output filename-- similar to the other output formats */
|
||||
void BKE_ffmpeg_filepath_get(char *string, RenderData *rd, bool preview)
|
||||
static void ffmpeg_filepath_get(FFMpegContext *context, char *string, RenderData *rd, bool preview, const char *suffix)
|
||||
{
|
||||
char autosplit[20];
|
||||
|
||||
@@ -1056,7 +1059,9 @@ void BKE_ffmpeg_filepath_get(char *string, RenderData *rd, bool preview)
|
||||
autosplit[0] = 0;
|
||||
|
||||
if ((rd->ffcodecdata.flags & FFMPEG_AUTOSPLIT_OUTPUT) != 0) {
|
||||
sprintf(autosplit, "_%03d", ffmpeg_autosplit_count);
|
||||
if (context) {
|
||||
sprintf(autosplit, "_%03d", context->ffmpeg_autosplit_count);
|
||||
}
|
||||
}
|
||||
|
||||
if (rd->scemode & R_EXTENSION) {
|
||||
@@ -1086,19 +1091,28 @@ void BKE_ffmpeg_filepath_get(char *string, RenderData *rd, bool preview)
|
||||
|
||||
strcat(string, autosplit);
|
||||
}
|
||||
|
||||
BLI_path_suffix(string, FILE_MAX, suffix, "");
|
||||
}
|
||||
|
||||
int BKE_ffmpeg_start(struct Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports, bool preview)
|
||||
void BKE_ffmpeg_filepath_get(char *string, RenderData *rd, bool preview, const char *suffix)
|
||||
{
|
||||
ffmpeg_filepath_get(NULL, string, rd, preview, suffix);
|
||||
}
|
||||
|
||||
int BKE_ffmpeg_start(void *context_v, struct Scene *scene, RenderData *rd, int rectx, int recty,
|
||||
ReportList *reports, bool preview, const char *suffix)
|
||||
{
|
||||
int success;
|
||||
FFMpegContext *context = context_v;
|
||||
|
||||
ffmpeg_autosplit_count = 0;
|
||||
ffmpeg_preview = preview;
|
||||
context->ffmpeg_autosplit_count = 0;
|
||||
context->ffmpeg_preview = preview;
|
||||
|
||||
success = start_ffmpeg_impl(rd, rectx, recty, reports);
|
||||
success = start_ffmpeg_impl(context, rd, rectx, recty, suffix, reports);
|
||||
#ifdef WITH_AUDASPACE
|
||||
if (audio_stream) {
|
||||
AVCodecContext *c = audio_stream->codec;
|
||||
if (context->audio_stream) {
|
||||
AVCodecContext *c = context->audio_stream->codec;
|
||||
AUD_DeviceSpecs specs;
|
||||
specs.channels = c->channels;
|
||||
|
||||
@@ -1123,7 +1137,7 @@ int BKE_ffmpeg_start(struct Scene *scene, RenderData *rd, int rectx, int recty,
|
||||
}
|
||||
|
||||
specs.rate = rd->ffcodecdata.audio_mixrate;
|
||||
audio_mixdown_device = BKE_sound_mixdown(scene, specs, preview ? rd->psfra : rd->sfra, rd->ffcodecdata.audio_volume);
|
||||
context->audio_mixdown_device = BKE_sound_mixdown(scene, specs, preview ? rd->psfra : rd->sfra, rd->ffcodecdata.audio_volume);
|
||||
#ifdef FFMPEG_CODEC_TIME_BASE
|
||||
c->time_base.den = specs.rate;
|
||||
c->time_base.num = 1;
|
||||
@@ -1133,16 +1147,16 @@ int BKE_ffmpeg_start(struct Scene *scene, RenderData *rd, int rectx, int recty,
|
||||
return success;
|
||||
}
|
||||
|
||||
static void end_ffmpeg_impl(int is_autosplit);
|
||||
static void end_ffmpeg_impl(FFMpegContext *context, int is_autosplit);
|
||||
|
||||
#ifdef WITH_AUDASPACE
|
||||
static void write_audio_frames(double to_pts)
|
||||
static void write_audio_frames(FFMpegContext *context, double to_pts)
|
||||
{
|
||||
int finished = 0;
|
||||
|
||||
while (audio_stream && !finished) {
|
||||
if ((audio_time >= to_pts) ||
|
||||
(write_audio_frame()))
|
||||
while (context->audio_stream && !finished) {
|
||||
if ((context->audio_time >= to_pts) ||
|
||||
(write_audio_frame(context)))
|
||||
{
|
||||
finished = 1;
|
||||
}
|
||||
@@ -1150,8 +1164,10 @@ static void write_audio_frames(double to_pts)
|
||||
}
|
||||
#endif
|
||||
|
||||
int BKE_ffmpeg_append(RenderData *rd, int start_frame, int frame, int *pixels, int rectx, int recty, ReportList *reports)
|
||||
int BKE_ffmpeg_append(void *context_v, RenderData *rd, int start_frame, int frame, int *pixels,
|
||||
int rectx, int recty, const char *suffix, ReportList *reports)
|
||||
{
|
||||
FFMpegContext *context = context_v;
|
||||
AVFrame *avframe;
|
||||
int success = 1;
|
||||
|
||||
@@ -1160,111 +1176,112 @@ int BKE_ffmpeg_append(RenderData *rd, int start_frame, int frame, int *pixels, i
|
||||
/* why is this done before writing the video frame and again at end_ffmpeg? */
|
||||
// write_audio_frames(frame / (((double)rd->frs_sec) / rd->frs_sec_base));
|
||||
|
||||
if (video_stream) {
|
||||
avframe = generate_video_frame((unsigned char *) pixels, reports);
|
||||
success = (avframe && write_video_frame(rd, frame - start_frame, avframe, reports));
|
||||
if (context->video_stream) {
|
||||
avframe = generate_video_frame(context, (unsigned char *) pixels, reports);
|
||||
success = (avframe && write_video_frame(context, rd, frame - start_frame, avframe, reports));
|
||||
|
||||
if (ffmpeg_autosplit) {
|
||||
if (avio_tell(outfile->pb) > FFMPEG_AUTOSPLIT_SIZE) {
|
||||
end_ffmpeg_impl(true);
|
||||
ffmpeg_autosplit_count++;
|
||||
success &= start_ffmpeg_impl(rd, rectx, recty, reports);
|
||||
if (context->ffmpeg_autosplit) {
|
||||
if (avio_tell(context->outfile->pb) > FFMPEG_AUTOSPLIT_SIZE) {
|
||||
end_ffmpeg_impl(context, true);
|
||||
context->ffmpeg_autosplit_count++;
|
||||
success &= start_ffmpeg_impl(context, rd, rectx, recty, suffix, reports);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WITH_AUDASPACE
|
||||
write_audio_frames((frame - start_frame) / (((double)rd->frs_sec) / (double)rd->frs_sec_base));
|
||||
write_audio_frames(context, (frame - start_frame) / (((double)rd->frs_sec) / (double)rd->frs_sec_base));
|
||||
#endif
|
||||
return success;
|
||||
}
|
||||
|
||||
static void end_ffmpeg_impl(int is_autosplit)
|
||||
static void end_ffmpeg_impl(FFMpegContext *context, int is_autosplit)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
PRINT("Closing ffmpeg...\n");
|
||||
|
||||
#if 0
|
||||
if (audio_stream) { /* SEE UPPER */
|
||||
write_audio_frames();
|
||||
if (context->audio_stream) { /* SEE UPPER */
|
||||
write_audio_frames(context);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_AUDASPACE
|
||||
if (is_autosplit == false) {
|
||||
if (audio_mixdown_device) {
|
||||
AUD_closeReadDevice(audio_mixdown_device);
|
||||
audio_mixdown_device = 0;
|
||||
if (context->audio_mixdown_device) {
|
||||
AUD_closeReadDevice(context->audio_mixdown_device);
|
||||
context->audio_mixdown_device = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (video_stream && video_stream->codec) {
|
||||
if (context->video_stream && context->video_stream->codec) {
|
||||
PRINT("Flushing delayed frames...\n");
|
||||
flush_ffmpeg();
|
||||
flush_ffmpeg(context);
|
||||
}
|
||||
|
||||
if (outfile) {
|
||||
av_write_trailer(outfile);
|
||||
if (context->outfile) {
|
||||
av_write_trailer(context->outfile);
|
||||
}
|
||||
|
||||
/* Close the video codec */
|
||||
|
||||
if (video_stream && video_stream->codec) {
|
||||
avcodec_close(video_stream->codec);
|
||||
PRINT("zero video stream %p\n", video_stream);
|
||||
video_stream = 0;
|
||||
if (context->video_stream && context->video_stream->codec) {
|
||||
avcodec_close(context->video_stream->codec);
|
||||
PRINT("zero video stream %p\n", context->video_stream);
|
||||
context->video_stream = 0;
|
||||
}
|
||||
|
||||
|
||||
/* Close the output file */
|
||||
if (outfile) {
|
||||
for (i = 0; i < outfile->nb_streams; i++) {
|
||||
if (&outfile->streams[i]) {
|
||||
av_freep(&outfile->streams[i]);
|
||||
if (context->outfile) {
|
||||
for (i = 0; i < context->outfile->nb_streams; i++) {
|
||||
if (&context->outfile->streams[i]) {
|
||||
av_freep(&context->outfile->streams[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* free the temp buffer */
|
||||
if (current_frame) {
|
||||
delete_picture(current_frame);
|
||||
current_frame = 0;
|
||||
if (context->current_frame) {
|
||||
delete_picture(context->current_frame);
|
||||
context->current_frame = 0;
|
||||
}
|
||||
if (outfile && outfile->oformat) {
|
||||
if (!(outfile->oformat->flags & AVFMT_NOFILE)) {
|
||||
avio_close(outfile->pb);
|
||||
if (context->outfile && context->outfile->oformat) {
|
||||
if (!(context->outfile->oformat->flags & AVFMT_NOFILE)) {
|
||||
avio_close(context->outfile->pb);
|
||||
}
|
||||
}
|
||||
if (outfile) {
|
||||
av_free(outfile);
|
||||
outfile = 0;
|
||||
if (context->outfile) {
|
||||
av_free(context->outfile);
|
||||
context->outfile = 0;
|
||||
}
|
||||
if (audio_input_buffer) {
|
||||
av_free(audio_input_buffer);
|
||||
audio_input_buffer = 0;
|
||||
if (context->audio_input_buffer) {
|
||||
av_free(context->audio_input_buffer);
|
||||
context->audio_input_buffer = 0;
|
||||
}
|
||||
#ifndef FFMPEG_HAVE_ENCODE_AUDIO2
|
||||
if (audio_output_buffer) {
|
||||
av_free(audio_output_buffer);
|
||||
audio_output_buffer = 0;
|
||||
if (context->audio_output_buffer) {
|
||||
av_free(context->audio_output_buffer);
|
||||
context->audio_output_buffer = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (audio_deinterleave_buffer) {
|
||||
av_free(audio_deinterleave_buffer);
|
||||
audio_deinterleave_buffer = 0;
|
||||
if (context->audio_deinterleave_buffer) {
|
||||
av_free(context->audio_deinterleave_buffer);
|
||||
context->audio_deinterleave_buffer = 0;
|
||||
}
|
||||
|
||||
if (img_convert_ctx) {
|
||||
sws_freeContext(img_convert_ctx);
|
||||
img_convert_ctx = 0;
|
||||
if (context->img_convert_ctx) {
|
||||
sws_freeContext(context->img_convert_ctx);
|
||||
context->img_convert_ctx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_ffmpeg_end(void)
|
||||
void BKE_ffmpeg_end(void *context_v)
|
||||
{
|
||||
end_ffmpeg_impl(false);
|
||||
FFMpegContext *context = context_v;
|
||||
end_ffmpeg_impl(context, false);
|
||||
}
|
||||
|
||||
/* properties */
|
||||
@@ -1658,4 +1675,31 @@ bool BKE_ffmpeg_alpha_channel_is_supported(RenderData *rd)
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
void *BKE_ffmpeg_context_create(void)
|
||||
{
|
||||
FFMpegContext *context;
|
||||
|
||||
/* new ffmpeg data struct */
|
||||
context = MEM_callocN(sizeof(FFMpegContext), "new ffmpeg context");
|
||||
|
||||
context->ffmpeg_codec = AV_CODEC_ID_MPEG4;
|
||||
context->ffmpeg_audio_codec = AV_CODEC_ID_NONE;
|
||||
context->ffmpeg_video_bitrate = 1150;
|
||||
context->ffmpeg_audio_bitrate = 128;
|
||||
context->ffmpeg_gop_size = 12;
|
||||
context->ffmpeg_autosplit = 0;
|
||||
context->ffmpeg_autosplit_count = 0;
|
||||
context->ffmpeg_preview = false;
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
void BKE_ffmpeg_context_free(void *context_v)
|
||||
{
|
||||
FFMpegContext *context = context_v;
|
||||
if (context) {
|
||||
MEM_freeN(context);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* WITH_FFMPEG */
|
||||
|
@@ -66,12 +66,15 @@
|
||||
#include "BKE_report.h"
|
||||
|
||||
#include "DNA_scene_types.h"
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
static int sock;
|
||||
static int connsock;
|
||||
static int write_ppm;
|
||||
static int render_width;
|
||||
static int render_height;
|
||||
typedef struct FrameserverContext {
|
||||
int sock;
|
||||
int connsock;
|
||||
int write_ppm;
|
||||
int render_width;
|
||||
int render_height;
|
||||
} FrameserverContext;
|
||||
|
||||
|
||||
#if defined(_WIN32)
|
||||
@@ -110,10 +113,11 @@ static int closesocket(int fd)
|
||||
}
|
||||
#endif
|
||||
|
||||
int BKE_frameserver_start(struct Scene *scene, RenderData *UNUSED(rd), int rectx, int recty, ReportList *reports, bool UNUSED(preview))
|
||||
int BKE_frameserver_start(void *context_v, struct Scene *scene, RenderData *UNUSED(rd), int rectx, int recty, ReportList *reports, bool UNUSED(preview), const char *UNUSED(suffix))
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
int arg = 1;
|
||||
FrameserverContext *context = context_v;
|
||||
|
||||
(void)scene; /* unused */
|
||||
|
||||
@@ -122,33 +126,33 @@ int BKE_frameserver_start(struct Scene *scene, RenderData *UNUSED(rd), int rectx
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||
if ((context->sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||
shutdown_socket_system();
|
||||
BKE_report(reports, RPT_ERROR, "Cannot open socket");
|
||||
return 0;
|
||||
}
|
||||
|
||||
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &arg, sizeof(arg));
|
||||
setsockopt(context->sock, SOL_SOCKET, SO_REUSEADDR, (char *) &arg, sizeof(arg));
|
||||
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(U.frameserverport);
|
||||
addr.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||
if (bind(context->sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||
shutdown_socket_system();
|
||||
BKE_report(reports, RPT_ERROR, "Cannot bind to socket");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (listen(sock, SOMAXCONN) < 0) {
|
||||
if (listen(context->sock, SOMAXCONN) < 0) {
|
||||
shutdown_socket_system();
|
||||
BKE_report(reports, RPT_ERROR, "Cannot establish listen backlog");
|
||||
return 0;
|
||||
}
|
||||
connsock = -1;
|
||||
context->connsock = -1;
|
||||
|
||||
render_width = rectx;
|
||||
render_height = recty;
|
||||
context->render_width = rectx;
|
||||
context->render_height = recty;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -177,7 +181,7 @@ static char good_bye[] =
|
||||
"<body><pre>\n"
|
||||
"Render stopped. Goodbye</pre></body></html>";
|
||||
|
||||
static int safe_write(char *s, int tosend)
|
||||
static int safe_write(const int connsock, char *s, int tosend)
|
||||
{
|
||||
int total = tosend;
|
||||
do {
|
||||
@@ -192,12 +196,12 @@ static int safe_write(char *s, int tosend)
|
||||
return total;
|
||||
}
|
||||
|
||||
static int safe_puts(char *s)
|
||||
static int safe_puts(const int connsock, char *s)
|
||||
{
|
||||
return safe_write(s, strlen(s));
|
||||
return safe_write(connsock, s, strlen(s));
|
||||
}
|
||||
|
||||
static int handle_request(RenderData *rd, char *req)
|
||||
static int handle_request(FrameserverContext *context, RenderData *rd, char *req)
|
||||
{
|
||||
char *p;
|
||||
char *path;
|
||||
@@ -214,16 +218,16 @@ static int handle_request(RenderData *rd, char *req)
|
||||
|
||||
*p = 0;
|
||||
|
||||
if (STREQ(path, "/index.html") || STREQ(path, "/")) {
|
||||
safe_puts(index_page);
|
||||
if (STREQ(path, "/index.html") || strcmp(path, "/")) {
|
||||
safe_puts(context->connsock, index_page);
|
||||
return -1;
|
||||
}
|
||||
|
||||
write_ppm = 0;
|
||||
context->write_ppm = 0;
|
||||
pathlen = strlen(path);
|
||||
|
||||
if (pathlen > 12 && memcmp(path, "/images/ppm/", 12) == 0) {
|
||||
write_ppm = 1;
|
||||
context->write_ppm = 1;
|
||||
return atoi(path + 12);
|
||||
}
|
||||
if (STREQ(path, "/info.txt")) {
|
||||
@@ -241,24 +245,24 @@ static int handle_request(RenderData *rd, char *req)
|
||||
"ratescale %d\n",
|
||||
rd->sfra,
|
||||
rd->efra,
|
||||
render_width,
|
||||
render_height,
|
||||
context->render_width,
|
||||
context->render_height,
|
||||
rd->frs_sec,
|
||||
1
|
||||
);
|
||||
|
||||
safe_puts(buf);
|
||||
safe_puts(context->connsock, buf);
|
||||
return -1;
|
||||
}
|
||||
if (STREQ(path, "/close.txt")) {
|
||||
safe_puts(good_bye);
|
||||
safe_puts(context->connsock, good_bye);
|
||||
G.is_break = true; /* Abort render */
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BKE_frameserver_loop(RenderData *rd, ReportList *UNUSED(reports))
|
||||
int BKE_frameserver_loop(void *context_v, RenderData *rd, ReportList *UNUSED(reports))
|
||||
{
|
||||
fd_set readfds;
|
||||
struct timeval tv;
|
||||
@@ -271,18 +275,20 @@ int BKE_frameserver_loop(RenderData *rd, ReportList *UNUSED(reports))
|
||||
#endif
|
||||
char buf[4096];
|
||||
|
||||
if (connsock != -1) {
|
||||
closesocket(connsock);
|
||||
connsock = -1;
|
||||
FrameserverContext *context = context_v;
|
||||
|
||||
if (context->connsock != -1) {
|
||||
closesocket(context->connsock);
|
||||
context->connsock = -1;
|
||||
}
|
||||
|
||||
tv.tv_sec = 1;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(sock, &readfds);
|
||||
FD_SET(context->sock, &readfds);
|
||||
|
||||
rval = select(sock + 1, &readfds, NULL, NULL, &tv);
|
||||
rval = select(context->sock + 1, &readfds, NULL, NULL, &tv);
|
||||
if (rval < 0) {
|
||||
return -1;
|
||||
}
|
||||
@@ -293,19 +299,19 @@ int BKE_frameserver_loop(RenderData *rd, ReportList *UNUSED(reports))
|
||||
|
||||
socklen = sizeof(addr);
|
||||
|
||||
if ((connsock = accept(sock, (struct sockaddr *)&addr, &socklen)) < 0) {
|
||||
if ((context->connsock = accept(context->sock, (struct sockaddr *)&addr, &socklen)) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(connsock, &readfds);
|
||||
FD_SET(context->connsock, &readfds);
|
||||
|
||||
for (;;) {
|
||||
/* give 10 seconds for telnet testing... */
|
||||
tv.tv_sec = 10;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
rval = select(connsock + 1, &readfds, NULL, NULL, &tv);
|
||||
rval = select(context->connsock + 1, &readfds, NULL, NULL, &tv);
|
||||
if (rval > 0) {
|
||||
break;
|
||||
}
|
||||
@@ -319,7 +325,7 @@ int BKE_frameserver_loop(RenderData *rd, ReportList *UNUSED(reports))
|
||||
}
|
||||
}
|
||||
|
||||
len = recv(connsock, buf, sizeof(buf) - 1, 0);
|
||||
len = recv(context->connsock, buf, sizeof(buf) - 1, 0);
|
||||
|
||||
if (len < 0) {
|
||||
return -1;
|
||||
@@ -327,13 +333,13 @@ int BKE_frameserver_loop(RenderData *rd, ReportList *UNUSED(reports))
|
||||
|
||||
buf[len] = 0;
|
||||
|
||||
return handle_request(rd, buf);
|
||||
return handle_request(context, rd, buf);
|
||||
}
|
||||
|
||||
static void serve_ppm(int *pixels, int rectx, int recty)
|
||||
static void serve_ppm(FrameserverContext *context, int *pixels, int rectx, int recty)
|
||||
{
|
||||
unsigned char *rendered_frame;
|
||||
unsigned char *row = (unsigned char *) malloc(render_width * 3);
|
||||
unsigned char *row = (unsigned char *) malloc(context->render_width * 3);
|
||||
int y;
|
||||
char header[1024];
|
||||
|
||||
@@ -348,7 +354,7 @@ static void serve_ppm(int *pixels, int rectx, int recty)
|
||||
"255\n",
|
||||
rectx, recty);
|
||||
|
||||
safe_puts(header);
|
||||
safe_puts(context->connsock, header);
|
||||
|
||||
rendered_frame = (unsigned char *)pixels;
|
||||
|
||||
@@ -364,36 +370,54 @@ static void serve_ppm(int *pixels, int rectx, int recty)
|
||||
target += 3;
|
||||
src += 4;
|
||||
}
|
||||
safe_write((char *)row, 3 * rectx);
|
||||
safe_write(context->connsock, (char *)row, 3 * rectx);
|
||||
}
|
||||
free(row);
|
||||
closesocket(connsock);
|
||||
connsock = -1;
|
||||
closesocket(context->connsock);
|
||||
context->connsock = -1;
|
||||
}
|
||||
|
||||
int BKE_frameserver_append(RenderData *UNUSED(rd), int UNUSED(start_frame), int frame, int *pixels,
|
||||
int rectx, int recty, ReportList *UNUSED(reports))
|
||||
int BKE_frameserver_append(void *context_v, RenderData *UNUSED(rd), int UNUSED(start_frame), int frame, int *pixels,
|
||||
int rectx, int recty, const char *UNUSED(suffix), ReportList *UNUSED(reports))
|
||||
{
|
||||
FrameserverContext *context = context_v;
|
||||
|
||||
fprintf(stderr, "Serving frame: %d\n", frame);
|
||||
if (write_ppm) {
|
||||
serve_ppm(pixels, rectx, recty);
|
||||
if (context->write_ppm) {
|
||||
serve_ppm(context, pixels, rectx, recty);
|
||||
}
|
||||
if (connsock != -1) {
|
||||
closesocket(connsock);
|
||||
connsock = -1;
|
||||
if (context->connsock != -1) {
|
||||
closesocket(context->connsock);
|
||||
context->connsock = -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void BKE_frameserver_end(void)
|
||||
void BKE_frameserver_end(void *context_v)
|
||||
{
|
||||
if (connsock != -1) {
|
||||
closesocket(connsock);
|
||||
connsock = -1;
|
||||
FrameserverContext *context = context_v;
|
||||
|
||||
if (context->connsock != -1) {
|
||||
closesocket(context->connsock);
|
||||
context->connsock = -1;
|
||||
}
|
||||
closesocket(sock);
|
||||
closesocket(context->sock);
|
||||
shutdown_socket_system();
|
||||
}
|
||||
|
||||
void *BKE_frameserver_context_create(void)
|
||||
{
|
||||
FrameserverContext *context = MEM_mallocN(sizeof(FrameserverContext), "Frameserver Context");
|
||||
return context;
|
||||
}
|
||||
|
||||
void BKE_frameserver_context_free(void *context_v)
|
||||
{
|
||||
FrameserverContext *context = context_v;
|
||||
if (context) {
|
||||
MEM_freeN(context);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* WITH_FRAMESERVER */
|
||||
|
@@ -89,6 +89,7 @@ int BLI_system_num_threads_override_get(void);
|
||||
#define LOCK_MOVIECLIP 7
|
||||
#define LOCK_COLORMANAGE 8
|
||||
#define LOCK_FFTW 9
|
||||
#define LOCK_VIEW3D 10
|
||||
|
||||
void BLI_lock_thread(int type);
|
||||
void BLI_unlock_thread(int type);
|
||||
|
@@ -122,6 +122,7 @@ static pthread_mutex_t _nodes_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t _movieclip_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t _colormanage_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t _fftw_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t _view3d_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_t mainid;
|
||||
static int thread_levels = 0; /* threads can be invoked inside threads */
|
||||
static int num_threads_override = 0;
|
||||
@@ -402,6 +403,8 @@ void BLI_lock_thread(int type)
|
||||
pthread_mutex_lock(&_colormanage_lock);
|
||||
else if (type == LOCK_FFTW)
|
||||
pthread_mutex_lock(&_fftw_lock);
|
||||
else if (type == LOCK_VIEW3D)
|
||||
pthread_mutex_lock(&_view3d_lock);
|
||||
}
|
||||
|
||||
void BLI_unlock_thread(int type)
|
||||
@@ -426,6 +429,8 @@ void BLI_unlock_thread(int type)
|
||||
pthread_mutex_unlock(&_colormanage_lock);
|
||||
else if (type == LOCK_FFTW)
|
||||
pthread_mutex_unlock(&_fftw_lock);
|
||||
else if (type == LOCK_VIEW3D)
|
||||
pthread_mutex_unlock(&_view3d_lock);
|
||||
}
|
||||
|
||||
/* Mutex Locks */
|
||||
|
@@ -1533,9 +1533,15 @@ void blo_make_packed_pointer_map(FileData *fd, Main *oldmain)
|
||||
|
||||
fd->packedmap = oldnewmap_new();
|
||||
|
||||
for (ima = oldmain->image.first; ima; ima = ima->id.next)
|
||||
for (ima = oldmain->image.first; ima; ima = ima->id.next) {
|
||||
ImagePackedFile *imapf;
|
||||
if (ima->packedfile)
|
||||
insert_packedmap(fd, ima->packedfile);
|
||||
|
||||
for (imapf = ima->packedfiles.first; imapf; imapf = imapf->next)
|
||||
if (imapf->packedfile)
|
||||
insert_packedmap(fd, imapf->packedfile);
|
||||
}
|
||||
|
||||
for (vfont = oldmain->vfont.first; vfont; vfont = vfont->id.next)
|
||||
if (vfont->packedfile)
|
||||
@@ -1568,8 +1574,13 @@ void blo_end_packed_pointer_map(FileData *fd, Main *oldmain)
|
||||
entry->newp = NULL;
|
||||
}
|
||||
|
||||
for (ima = oldmain->image.first; ima; ima = ima->id.next)
|
||||
for (ima = oldmain->image.first; ima; ima = ima->id.next) {
|
||||
ImagePackedFile *imapf;
|
||||
ima->packedfile = newpackedadr(fd, ima->packedfile);
|
||||
|
||||
for (imapf = ima->packedfiles.first; imapf; imapf = imapf->next)
|
||||
imapf->packedfile = newpackedadr(fd, imapf->packedfile);
|
||||
}
|
||||
|
||||
for (vfont = oldmain->vfont.first; vfont; vfont = vfont->id.next)
|
||||
vfont->packedfile = newpackedadr(fd, vfont->packedfile);
|
||||
@@ -3391,6 +3402,8 @@ static void lib_link_image(FileData *fd, Main *main)
|
||||
|
||||
static void direct_link_image(FileData *fd, Image *ima)
|
||||
{
|
||||
ImagePackedFile *imapf;
|
||||
|
||||
/* for undo system, pointers could be restored */
|
||||
if (fd->imamap)
|
||||
ima->cache = newimaadr(fd, ima->cache);
|
||||
@@ -3404,8 +3417,7 @@ static void direct_link_image(FileData *fd, Image *ima)
|
||||
ima->gputexture = NULL;
|
||||
ima->rr = NULL;
|
||||
}
|
||||
|
||||
ima->anim = NULL;
|
||||
|
||||
ima->repbind = NULL;
|
||||
|
||||
/* undo system, try to restore render buffers */
|
||||
@@ -3419,9 +3431,18 @@ static void direct_link_image(FileData *fd, Image *ima)
|
||||
memset(ima->renders, 0, sizeof(ima->renders));
|
||||
ima->last_render_slot = ima->render_slot;
|
||||
}
|
||||
|
||||
|
||||
link_list(fd, &(ima->views));
|
||||
link_list(fd, &(ima->packedfiles));
|
||||
|
||||
for (imapf = ima->packedfiles.first; imapf; imapf = imapf->next) {
|
||||
imapf->packedfile = direct_link_packedfile(fd, imapf->packedfile);
|
||||
}
|
||||
|
||||
ima->anims.first = ima->anims.last = NULL;
|
||||
ima->packedfile = direct_link_packedfile(fd, ima->packedfile);
|
||||
ima->preview = direct_link_preview_image(fd, ima->preview);
|
||||
ima->stereo3d_format = newdataadr(fd, ima->stereo3d_format);
|
||||
ima->ok = 1;
|
||||
}
|
||||
|
||||
@@ -5378,7 +5399,7 @@ static void lib_link_scene(FileData *fd, Main *main)
|
||||
seq->scene_sound = BKE_sound_add_scene_sound_defaults(sce, seq);
|
||||
}
|
||||
}
|
||||
seq->anim = NULL;
|
||||
seq->anims.first = seq->anims.last = NULL;
|
||||
|
||||
lib_link_sequence_modifiers(fd, sce, &seq->modifiers);
|
||||
}
|
||||
@@ -5610,6 +5631,7 @@ static void direct_link_scene(FileData *fd, Scene *sce)
|
||||
if (seq->seq3 == NULL) seq->seq3 = seq->seq2;
|
||||
|
||||
seq->effectdata = newdataadr(fd, seq->effectdata);
|
||||
seq->stereo3d_format = newdataadr(fd, seq->stereo3d_format);
|
||||
|
||||
if (seq->type & SEQ_TYPE_EFFECT)
|
||||
seq->flag |= SEQ_EFFECT_NOT_LOADED;
|
||||
@@ -5722,6 +5744,7 @@ static void direct_link_scene(FileData *fd, Scene *sce)
|
||||
link_list(fd, &(sce->markers));
|
||||
link_list(fd, &(sce->transform_spaces));
|
||||
link_list(fd, &(sce->r.layers));
|
||||
link_list(fd, &(sce->r.views));
|
||||
|
||||
for (srl = sce->r.layers.first; srl; srl = srl->next) {
|
||||
link_list(fd, &(srl->freestyleConfig.modules));
|
||||
@@ -5785,8 +5808,8 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm)
|
||||
BLI_listbase_clear(&win->modalhandlers);
|
||||
BLI_listbase_clear(&win->subwindows);
|
||||
BLI_listbase_clear(&win->gesture);
|
||||
BLI_listbase_clear(&win->drawdata);
|
||||
|
||||
win->drawdata = NULL;
|
||||
win->drawmethod = -1;
|
||||
win->drawfail = 0;
|
||||
win->active = 0;
|
||||
@@ -5794,6 +5817,7 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm)
|
||||
win->cursor = 0;
|
||||
win->lastcursor = 0;
|
||||
win->modalcursor = 0;
|
||||
win->stereo3d_format = newdataadr(fd, win->stereo3d_format);
|
||||
}
|
||||
|
||||
BLI_listbase_clear(&wm->timers);
|
||||
@@ -7765,7 +7789,6 @@ static void do_versions_userdef(FileData *fd, BlendFileData *bfd)
|
||||
user->walk_navigation.jump_height = 0.4f; /* m */
|
||||
user->walk_navigation.teleport_time = 0.2f; /* s */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void do_versions(FileData *fd, Library *lib, Main *main)
|
||||
@@ -7888,7 +7911,7 @@ static BHead *read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead)
|
||||
link_list(fd, &user->user_keymaps);
|
||||
link_list(fd, &user->addons);
|
||||
link_list(fd, &user->autoexec_paths);
|
||||
|
||||
|
||||
for (keymap=user->user_keymaps.first; keymap; keymap=keymap->next) {
|
||||
keymap->modal_items= NULL;
|
||||
keymap->poll = NULL;
|
||||
|
@@ -27,6 +27,7 @@
|
||||
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_compiler_attrs.h"
|
||||
#include "BLI_string.h"
|
||||
|
||||
/* for MinGW32 definition of NULL, could use BLI_blenlib.h instead too */
|
||||
#include <stddef.h>
|
||||
@@ -48,14 +49,18 @@
|
||||
#include "DNA_particle_types.h"
|
||||
#include "DNA_linestyle_types.h"
|
||||
#include "DNA_actuator_types.h"
|
||||
#include "DNA_camera_types.h"
|
||||
#include "DNA_view3d_types.h"
|
||||
|
||||
#include "DNA_genfile.h"
|
||||
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_modifier.h"
|
||||
#include "BKE_node.h"
|
||||
#include "BKE_scene.h"
|
||||
#include "BKE_sequencer.h"
|
||||
#include "BKE_screen.h"
|
||||
#include "BKE_sequencer.h"
|
||||
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_listbase.h"
|
||||
@@ -460,10 +465,10 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
|
||||
br->mtex.random_angle = 2.0 * M_PI;
|
||||
br->mask_mtex.random_angle = 2.0 * M_PI;
|
||||
}
|
||||
}
|
||||
|
||||
#undef BRUSH_RAKE
|
||||
#undef BRUSH_RANDOM_ROTATION
|
||||
}
|
||||
|
||||
/* Customizable Safe Areas */
|
||||
if (!MAIN_VERSION_ATLEAST(main, 273, 2)) {
|
||||
@@ -724,4 +729,85 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
|
||||
#undef SEQ_USE_PROXY_CUSTOM_DIR
|
||||
#undef SEQ_USE_PROXY_CUSTOM_FILE
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_ATLEAST(main, 274, 3))
|
||||
{
|
||||
SceneRenderView *srv;
|
||||
wmWindowManager *wm;
|
||||
bScreen *screen;
|
||||
wmWindow *win;
|
||||
Scene *scene;
|
||||
Camera *cam;
|
||||
Image *ima;
|
||||
|
||||
for (scene = main->scene.first; scene; scene = scene->id.next) {
|
||||
Sequence *seq;
|
||||
|
||||
BKE_scene_add_render_view(scene, STEREO_LEFT_NAME);
|
||||
srv = scene->r.views.first;
|
||||
BLI_strncpy(srv->suffix, STEREO_LEFT_SUFFIX, sizeof(srv->suffix));
|
||||
|
||||
BKE_scene_add_render_view(scene, STEREO_RIGHT_NAME);
|
||||
srv = scene->r.views.last;
|
||||
BLI_strncpy(srv->suffix, STEREO_RIGHT_SUFFIX, sizeof(srv->suffix));
|
||||
|
||||
SEQ_BEGIN (scene->ed, seq)
|
||||
{
|
||||
seq->stereo3d_format = MEM_callocN(sizeof(Stereo3dFormat), "Stereo Display 3d Format");
|
||||
}
|
||||
SEQ_END
|
||||
}
|
||||
|
||||
for (screen = main->screen.first; screen; screen = screen->id.next) {
|
||||
ScrArea *sa;
|
||||
for (sa = screen->areabase.first; sa; sa = sa->next) {
|
||||
SpaceLink *sl;
|
||||
|
||||
for (sl = sa->spacedata.first; sl; sl = sl->next) {
|
||||
switch (sl->spacetype) {
|
||||
case SPACE_VIEW3D:
|
||||
{
|
||||
View3D *v3d = (View3D *)sl;
|
||||
v3d->stereo3d_camera = STEREO_3D_ID;
|
||||
v3d->stereo3d_flag |= V3D_S3D_DISPPLANE;
|
||||
v3d->stereo3d_convergence_alpha = 0.15f;
|
||||
v3d->stereo3d_volume_alpha = 0.05f;
|
||||
break;
|
||||
}
|
||||
case SPACE_IMAGE:
|
||||
{
|
||||
SpaceImage *sima = (SpaceImage *) sl;
|
||||
sima->iuser.flag |= IMA_SHOW_STEREO;
|
||||
sima->iuser.passtype = SCE_PASS_COMBINED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (cam = main->camera.first; cam; cam = cam->id.next) {
|
||||
cam->stereo.interocular_distance = 0.065;
|
||||
cam->stereo.convergence_distance = 30.f * 0.065;
|
||||
}
|
||||
|
||||
for (ima = main->image.first; ima; ima = ima->id.next) {
|
||||
ima->stereo3d_format = MEM_callocN(sizeof(Stereo3dFormat), "Image Stereo 3d Format");
|
||||
|
||||
if (ima->packedfile) {
|
||||
ImagePackedFile *imapf = MEM_mallocN(sizeof(ImagePackedFile), "Image Packed File");
|
||||
BLI_addtail(&ima->packedfiles, imapf);
|
||||
|
||||
imapf->packedfile = ima->packedfile;
|
||||
BLI_strncpy(imapf->filepath, ima->name, FILE_MAX);
|
||||
ima->packedfile = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
for (wm = main->wm.first; wm; wm = wm->id.next) {
|
||||
for (win = wm->windows.first; win; win = win->next) {
|
||||
win->stereo3d_format = MEM_callocN(sizeof(Stereo3dFormat), "Stereo Display 3d Format");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -2124,7 +2124,8 @@ static void write_images(WriteData *wd, ListBase *idbase)
|
||||
{
|
||||
Image *ima;
|
||||
PackedFile * pf;
|
||||
|
||||
ImageView *iv;
|
||||
ImagePackedFile *imapf;
|
||||
|
||||
ima= idbase->first;
|
||||
while (ima) {
|
||||
@@ -2133,13 +2134,20 @@ static void write_images(WriteData *wd, ListBase *idbase)
|
||||
writestruct(wd, ID_IM, "Image", 1, ima);
|
||||
if (ima->id.properties) IDP_WriteProperty(ima->id.properties, wd);
|
||||
|
||||
if (ima->packedfile) {
|
||||
pf = ima->packedfile;
|
||||
writestruct(wd, DATA, "PackedFile", 1, pf);
|
||||
writedata(wd, DATA, pf->size, pf->data);
|
||||
for (imapf = ima->packedfiles.first; imapf; imapf = imapf->next) {
|
||||
writestruct(wd, DATA, "ImagePackedFile", 1, imapf);
|
||||
if (imapf->packedfile) {
|
||||
pf = imapf->packedfile;
|
||||
writestruct(wd, DATA, "PackedFile", 1, pf);
|
||||
writedata(wd, DATA, pf->size, pf->data);
|
||||
}
|
||||
}
|
||||
|
||||
write_previews(wd, ima->preview);
|
||||
|
||||
for (iv = ima->views.first; iv; iv = iv->next)
|
||||
writestruct(wd, DATA, "ImageView", 1, iv);
|
||||
writestruct(wd, DATA, "Stereo3dFormat", 1, ima->stereo3d_format);
|
||||
}
|
||||
ima= ima->id.next;
|
||||
}
|
||||
@@ -2340,6 +2348,7 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
|
||||
TimeMarker *marker;
|
||||
TransformOrientation *ts;
|
||||
SceneRenderLayer *srl;
|
||||
SceneRenderView *srv;
|
||||
ToolSettings *tos;
|
||||
FreestyleModuleConfig *fmc;
|
||||
FreestyleLineSet *fls;
|
||||
@@ -2421,7 +2430,9 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
writestruct(wd, DATA, "Stereo3dFormat", 1, seq->stereo3d_format);
|
||||
|
||||
strip= seq->strip;
|
||||
writestruct(wd, DATA, "Strip", 1, strip);
|
||||
if (seq->flag & SEQ_USE_CROP && strip->crop) {
|
||||
@@ -2486,6 +2497,10 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
|
||||
writestruct(wd, DATA, "FreestyleLineSet", 1, fls);
|
||||
}
|
||||
}
|
||||
|
||||
/* writing MultiView to the blend file */
|
||||
for (srv = sce->r.views.first; srv; srv = srv->next)
|
||||
writestruct(wd, DATA, "SceneRenderView", 1, srv);
|
||||
|
||||
if (sce->nodetree) {
|
||||
writestruct(wd, DATA, "bNodeTree", 1, sce->nodetree);
|
||||
@@ -2548,8 +2563,10 @@ static void write_windowmanagers(WriteData *wd, ListBase *lb)
|
||||
for (wm= lb->first; wm; wm= wm->id.next) {
|
||||
writestruct(wd, ID_WM, "wmWindowManager", 1, wm);
|
||||
|
||||
for (win= wm->windows.first; win; win= win->next)
|
||||
for (win= wm->windows.first; win; win= win->next) {
|
||||
writestruct(wd, DATA, "wmWindow", 1, win);
|
||||
writestruct(wd, DATA, "Stereo3dFormat", 1, win->stereo3d_format);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -74,7 +74,7 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies)
|
||||
|
||||
short image_source = image->source;
|
||||
bool is_generated = image_source == IMA_SRC_GENERATED;
|
||||
bool is_packed = image->packedfile != NULL;
|
||||
bool is_packed = BKE_image_has_packedfile(image);
|
||||
|
||||
char export_path[FILE_MAX];
|
||||
char source_path[FILE_MAX];
|
||||
|
@@ -119,6 +119,8 @@ set(SRC
|
||||
nodes/COM_TimeNode.h
|
||||
nodes/COM_SwitchNode.cpp
|
||||
nodes/COM_SwitchNode.h
|
||||
nodes/COM_SwitchViewNode.cpp
|
||||
nodes/COM_SwitchViewNode.h
|
||||
nodes/COM_MovieClipNode.cpp
|
||||
nodes/COM_MovieClipNode.h
|
||||
nodes/COM_OutputFileNode.cpp
|
||||
@@ -370,6 +372,8 @@ set(SRC
|
||||
operations/COM_CompositorOperation.cpp
|
||||
operations/COM_OutputFileOperation.h
|
||||
operations/COM_OutputFileOperation.cpp
|
||||
operations/COM_OutputFileMultiViewOperation.h
|
||||
operations/COM_OutputFileMultiViewOperation.cpp
|
||||
operations/COM_ViewerOperation.h
|
||||
operations/COM_ViewerOperation.cpp
|
||||
operations/COM_PreviewOperation.h
|
||||
|
@@ -316,7 +316,8 @@ extern "C" {
|
||||
* generation in display space
|
||||
*/
|
||||
void COM_execute(RenderData *rd, Scene *scene, bNodeTree *editingtree, int rendering,
|
||||
const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings);
|
||||
const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings,
|
||||
const char *viewName);
|
||||
|
||||
/**
|
||||
* @brief Deinitialize the compositor caches and allocated memory.
|
||||
|
@@ -87,6 +87,11 @@ private:
|
||||
const ColorManagedViewSettings *m_viewSettings;
|
||||
const ColorManagedDisplaySettings *m_displaySettings;
|
||||
|
||||
/**
|
||||
* @brief active rendering view name
|
||||
*/
|
||||
const char *m_viewName;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief constructor initializes the context with default values.
|
||||
@@ -180,7 +185,17 @@ public:
|
||||
* @brief set has this system active openclDevices?
|
||||
*/
|
||||
void setHasActiveOpenCLDevices(bool hasAvtiveOpenCLDevices) { this->m_hasActiveOpenCLDevices = hasAvtiveOpenCLDevices; }
|
||||
|
||||
|
||||
/**
|
||||
* @brief get the active rendering view
|
||||
*/
|
||||
const char *getViewName() const { return this->m_viewName; }
|
||||
|
||||
/**
|
||||
* @brief set the active rendering view
|
||||
*/
|
||||
void setViewName(const char *viewName) { this->m_viewName = viewName; }
|
||||
|
||||
int getChunksize() const { return this->getbNodeTree()->chunksize; }
|
||||
|
||||
void setFastCalculation(bool fastCalculation) {this->m_fastCalculation = fastCalculation;}
|
||||
|
@@ -101,6 +101,7 @@ extern "C" {
|
||||
#include "COM_Stabilize2dNode.h"
|
||||
#include "COM_SunBeamsNode.h"
|
||||
#include "COM_SwitchNode.h"
|
||||
#include "COM_SwitchViewNode.h"
|
||||
#include "COM_TextureNode.h"
|
||||
#include "COM_TimeNode.h"
|
||||
#include "COM_TonemapNode.h"
|
||||
@@ -328,6 +329,9 @@ Node *Converter::convert(bNode *b_node)
|
||||
case CMP_NODE_SWITCH:
|
||||
node = new SwitchNode(b_node);
|
||||
break;
|
||||
case CMP_NODE_SWITCH_VIEW:
|
||||
node = new SwitchViewNode(b_node);
|
||||
break;
|
||||
case CMP_NODE_GLARE:
|
||||
node = new GlareNode(b_node);
|
||||
break;
|
||||
|
@@ -43,8 +43,10 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
ExecutionSystem::ExecutionSystem(RenderData *rd, Scene *scene, bNodeTree *editingtree, bool rendering, bool fastcalculation,
|
||||
const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings)
|
||||
const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings,
|
||||
const char *viewName)
|
||||
{
|
||||
this->m_context.setViewName(viewName);
|
||||
this->m_context.setScene(scene);
|
||||
this->m_context.setbNodeTree(editingtree);
|
||||
this->m_context.setPreviewHash(editingtree->previews);
|
||||
|
@@ -151,7 +151,8 @@ public:
|
||||
* @param rendering [true false]
|
||||
*/
|
||||
ExecutionSystem(RenderData *rd, Scene *scene, bNodeTree *editingtree, bool rendering, bool fastcalculation,
|
||||
const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings);
|
||||
const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings,
|
||||
const char *viewName);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
|
@@ -45,7 +45,8 @@ static void intern_freeCompositorCaches()
|
||||
|
||||
void COM_execute(RenderData *rd, Scene *scene, bNodeTree *editingtree, int rendering,
|
||||
const ColorManagedViewSettings *viewSettings,
|
||||
const ColorManagedDisplaySettings *displaySettings)
|
||||
const ColorManagedDisplaySettings *displaySettings,
|
||||
const char *viewName)
|
||||
{
|
||||
/* initialize mutex, TODO this mutex init is actually not thread safe and
|
||||
* should be done somewhere as part of blender startup, all the other
|
||||
@@ -82,7 +83,7 @@ void COM_execute(RenderData *rd, Scene *scene, bNodeTree *editingtree, int rende
|
||||
bool twopass = (editingtree->flag & NTREE_TWO_PASS) > 0 && !rendering;
|
||||
/* initialize execution system */
|
||||
if (twopass) {
|
||||
ExecutionSystem *system = new ExecutionSystem(rd, scene, editingtree, rendering, twopass, viewSettings, displaySettings);
|
||||
ExecutionSystem *system = new ExecutionSystem(rd, scene, editingtree, rendering, twopass, viewSettings, displaySettings, viewName);
|
||||
system->execute();
|
||||
delete system;
|
||||
|
||||
@@ -95,7 +96,7 @@ void COM_execute(RenderData *rd, Scene *scene, bNodeTree *editingtree, int rende
|
||||
}
|
||||
|
||||
ExecutionSystem *system = new ExecutionSystem(rd, scene, editingtree, rendering, false,
|
||||
viewSettings, displaySettings);
|
||||
viewSettings, displaySettings, viewName);
|
||||
system->execute();
|
||||
delete system;
|
||||
|
||||
|
@@ -43,6 +43,7 @@ void CompositorNode::convertToOperations(NodeConverter &converter, const Composi
|
||||
CompositorOperation *compositorOperation = new CompositorOperation();
|
||||
compositorOperation->setSceneName(context.getScene()->id.name);
|
||||
compositorOperation->setRenderData(context.getRenderData());
|
||||
compositorOperation->setViewName(context.getViewName());
|
||||
compositorOperation->setbNodeTree(context.getbNodeTree());
|
||||
/* alpha socket gives either 1 or a custom alpha value if "use alpha" is enabled */
|
||||
compositorOperation->setUseAlphaInput(ignore_alpha || alphaSocket->isLinked());
|
||||
|
@@ -40,19 +40,19 @@ ImageNode::ImageNode(bNode *editorNode) : Node(editorNode)
|
||||
|
||||
}
|
||||
NodeOperation *ImageNode::doMultilayerCheck(NodeConverter &converter, RenderLayer *rl, Image *image, ImageUser *user,
|
||||
int framenumber, int outputsocketIndex, int passindex, DataType datatype) const
|
||||
int framenumber, int outputsocketIndex, int passtype, int view, DataType datatype) const
|
||||
{
|
||||
NodeOutput *outputSocket = this->getOutputSocket(outputsocketIndex);
|
||||
MultilayerBaseOperation *operation = NULL;
|
||||
switch (datatype) {
|
||||
case COM_DT_VALUE:
|
||||
operation = new MultilayerValueOperation(passindex);
|
||||
operation = new MultilayerValueOperation(passtype, view);
|
||||
break;
|
||||
case COM_DT_VECTOR:
|
||||
operation = new MultilayerVectorOperation(passindex);
|
||||
operation = new MultilayerVectorOperation(passtype, view);
|
||||
break;
|
||||
case COM_DT_COLOR:
|
||||
operation = new MultilayerColorOperation(passindex);
|
||||
operation = new MultilayerColorOperation(passtype, view);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -96,6 +96,10 @@ void ImageNode::convertToOperations(NodeConverter &converter, const CompositorCo
|
||||
NodeOperation *operation = NULL;
|
||||
socket = this->getOutputSocket(index);
|
||||
bNodeSocket *bnodeSocket = socket->getbNodeSocket();
|
||||
RenderPass *rpass = (RenderPass *)BLI_findstring(&rl->passes, bnodeSocket->identifier, offsetof(RenderPass, internal_name));
|
||||
|
||||
int view = (rpass ? rpass->view_id : 0);
|
||||
|
||||
/* Passes in the file can differ from passes stored in sockets (#36755).
|
||||
* Look up the correct file pass using the socket identifier instead.
|
||||
*/
|
||||
@@ -104,8 +108,22 @@ void ImageNode::convertToOperations(NodeConverter &converter, const CompositorCo
|
||||
int passindex = storage->pass_index;*/
|
||||
RenderPass *rpass = (RenderPass *)BLI_findlink(&rl->passes, passindex);
|
||||
#endif
|
||||
int passindex;
|
||||
RenderPass *rpass;
|
||||
|
||||
/* returns the image view to use for the current active view */
|
||||
if (BLI_listbase_count_ex(&image->rr->views, 2) > 1) {
|
||||
const int view_image = imageuser->view;
|
||||
const bool is_allview = (view_image == 0); /* if view selected == All (0) */
|
||||
|
||||
if (is_allview) {
|
||||
/* heuristic to match image name with scene names
|
||||
* check if the view name exists in the image */
|
||||
view = BLI_findstringindex(&image->rr->views, context.getViewName(), offsetof(RenderView, name));
|
||||
}
|
||||
else {
|
||||
view = view_image - 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (STREQ(bnodeSocket->identifier, "Alpha")) {
|
||||
BLI_assert(combined_operation != NULL);
|
||||
NodeOutput *outputSocket = this->getOutputSocket(index);
|
||||
@@ -118,22 +136,21 @@ void ImageNode::convertToOperations(NodeConverter &converter, const CompositorCo
|
||||
operation = separate_operation;
|
||||
}
|
||||
else {
|
||||
for (rpass = (RenderPass *)rl->passes.first, passindex = 0; rpass; rpass = rpass->next, ++passindex)
|
||||
if (STREQ(rpass->name, bnodeSocket->identifier))
|
||||
break;
|
||||
if (rpass) {
|
||||
imageuser->pass = passindex;
|
||||
switch (rpass->channels) {
|
||||
case 1:
|
||||
operation = doMultilayerCheck(converter, rl, image, imageuser, framenumber, index, passindex, COM_DT_VALUE);
|
||||
operation = doMultilayerCheck(converter, rl, image, imageuser, framenumber, index,
|
||||
rpass->passtype, view, COM_DT_VALUE);
|
||||
break;
|
||||
/* using image operations for both 3 and 4 channels (RGB and RGBA respectively) */
|
||||
/* XXX any way to detect actual vector images? */
|
||||
case 3:
|
||||
operation = doMultilayerCheck(converter, rl, image, imageuser, framenumber, index, passindex, COM_DT_VECTOR);
|
||||
operation = doMultilayerCheck(converter, rl, image, imageuser, framenumber, index,
|
||||
rpass->passtype, view, COM_DT_VECTOR);
|
||||
break;
|
||||
case 4:
|
||||
operation = doMultilayerCheck(converter, rl, image, imageuser, framenumber, index, passindex, COM_DT_COLOR);
|
||||
operation = doMultilayerCheck(converter, rl, image, imageuser, framenumber, index,
|
||||
rpass->passtype, view, COM_DT_COLOR);
|
||||
break;
|
||||
default:
|
||||
/* dummy operation is added below */
|
||||
@@ -168,6 +185,8 @@ void ImageNode::convertToOperations(NodeConverter &converter, const CompositorCo
|
||||
operation->setImage(image);
|
||||
operation->setImageUser(imageuser);
|
||||
operation->setFramenumber(framenumber);
|
||||
operation->setRenderData(context.getRenderData());
|
||||
operation->setViewName(context.getViewName());
|
||||
converter.addOperation(operation);
|
||||
|
||||
if (outputStraightAlpha) {
|
||||
@@ -190,6 +209,8 @@ void ImageNode::convertToOperations(NodeConverter &converter, const CompositorCo
|
||||
alphaOperation->setImage(image);
|
||||
alphaOperation->setImageUser(imageuser);
|
||||
alphaOperation->setFramenumber(framenumber);
|
||||
alphaOperation->setRenderData(context.getRenderData());
|
||||
alphaOperation->setViewName(context.getViewName());
|
||||
converter.addOperation(alphaOperation);
|
||||
|
||||
converter.mapOutputSocket(alphaImage, alphaOperation->getOutputSocket());
|
||||
@@ -200,6 +221,8 @@ void ImageNode::convertToOperations(NodeConverter &converter, const CompositorCo
|
||||
depthOperation->setImage(image);
|
||||
depthOperation->setImageUser(imageuser);
|
||||
depthOperation->setFramenumber(framenumber);
|
||||
depthOperation->setRenderData(context.getRenderData());
|
||||
depthOperation->setViewName(context.getViewName());
|
||||
converter.addOperation(depthOperation);
|
||||
|
||||
converter.mapOutputSocket(depthImage, depthOperation->getOutputSocket());
|
||||
@@ -239,6 +262,7 @@ void ImageNode::convertToOperations(NodeConverter &converter, const CompositorCo
|
||||
}
|
||||
|
||||
if (operation) {
|
||||
/* not supporting multiview for this generic case */
|
||||
converter.addOperation(operation);
|
||||
converter.mapOutputSocket(output, operation->getOutputSocket());
|
||||
}
|
||||
|
@@ -36,7 +36,7 @@ extern "C" {
|
||||
class ImageNode : public Node {
|
||||
private:
|
||||
NodeOperation *doMultilayerCheck(NodeConverter &converter, RenderLayer *rl, Image *image, ImageUser *user,
|
||||
int framenumber, int outputsocketIndex, int passindex, DataType datatype) const;
|
||||
int framenumber, int outputsocketIndex, int passtype, int view, DataType datatype) const;
|
||||
public:
|
||||
ImageNode(bNode *editorNode);
|
||||
void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
|
||||
|
@@ -23,8 +23,11 @@
|
||||
|
||||
#include "COM_OutputFileNode.h"
|
||||
#include "COM_OutputFileOperation.h"
|
||||
#include "COM_OutputFileMultiViewOperation.h"
|
||||
#include "COM_ExecutionSystem.h"
|
||||
|
||||
#include "BKE_scene.h"
|
||||
|
||||
#include "BLI_path_util.h"
|
||||
|
||||
OutputFileNode::OutputFileNode(bNode *editorNode) : Node(editorNode)
|
||||
@@ -35,6 +38,7 @@ OutputFileNode::OutputFileNode(bNode *editorNode) : Node(editorNode)
|
||||
void OutputFileNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
|
||||
{
|
||||
NodeImageMultiFile *storage = (NodeImageMultiFile *)this->getbNode()->storage;
|
||||
const bool is_multiview = (context.getRenderData()->scemode & R_MULTIVIEW) != 0;
|
||||
|
||||
if (!context.isRendering()) {
|
||||
/* only output files when rendering a sequence -
|
||||
@@ -46,10 +50,18 @@ void OutputFileNode::convertToOperations(NodeConverter &converter, const Composi
|
||||
|
||||
if (storage->format.imtype == R_IMF_IMTYPE_MULTILAYER) {
|
||||
/* single output operation for the multilayer file */
|
||||
OutputOpenExrMultiLayerOperation *outputOperation = new OutputOpenExrMultiLayerOperation(
|
||||
context.getRenderData(), context.getbNodeTree(), storage->base_path, storage->format.exr_codec);
|
||||
OutputOpenExrMultiLayerOperation *outputOperation;
|
||||
|
||||
if (is_multiview && storage->format.views_format == R_IMF_VIEWS_MULTIVIEW) {
|
||||
outputOperation = new OutputOpenExrMultiLayerMultiViewOperation(
|
||||
context.getRenderData(), context.getbNodeTree(), storage->base_path, storage->format.exr_codec, context.getViewName());
|
||||
}
|
||||
else {
|
||||
outputOperation = new OutputOpenExrMultiLayerOperation(
|
||||
context.getRenderData(), context.getbNodeTree(), storage->base_path, storage->format.exr_codec, context.getViewName());
|
||||
}
|
||||
converter.addOperation(outputOperation);
|
||||
|
||||
|
||||
int num_inputs = getNumberOfInputSockets();
|
||||
bool previewAdded = false;
|
||||
for (int i = 0; i < num_inputs; ++i) {
|
||||
@@ -76,17 +88,31 @@ void OutputFileNode::convertToOperations(NodeConverter &converter, const Composi
|
||||
NodeImageMultiFileSocket *sockdata = (NodeImageMultiFileSocket *)input->getbNodeSocket()->storage;
|
||||
ImageFormatData *format = (sockdata->use_node_format ? &storage->format : &sockdata->format);
|
||||
char path[FILE_MAX];
|
||||
|
||||
|
||||
/* combine file path for the input */
|
||||
BLI_join_dirfile(path, FILE_MAX, storage->base_path, sockdata->path);
|
||||
|
||||
OutputSingleLayerOperation *outputOperation = new OutputSingleLayerOperation(
|
||||
context.getRenderData(), context.getbNodeTree(), input->getDataType(), format, path,
|
||||
context.getViewSettings(), context.getDisplaySettings());
|
||||
|
||||
NodeOperation *outputOperation = NULL;
|
||||
|
||||
if (is_multiview && format->views_format == R_IMF_VIEWS_MULTIVIEW) {
|
||||
outputOperation = new OutputOpenExrSingleLayerMultiViewOperation(
|
||||
context.getRenderData(), context.getbNodeTree(), input->getDataType(), format, path,
|
||||
context.getViewSettings(), context.getDisplaySettings(), context.getViewName());
|
||||
}
|
||||
else if ((!is_multiview) || (format->views_format == R_IMF_VIEWS_INDIVIDUAL)) {
|
||||
outputOperation = new OutputSingleLayerOperation(
|
||||
context.getRenderData(), context.getbNodeTree(), input->getDataType(), format, path,
|
||||
context.getViewSettings(), context.getDisplaySettings(), context.getViewName());
|
||||
}
|
||||
else { /* R_IMF_VIEWS_STEREO_3D */
|
||||
outputOperation = new OutputStereoOperation(
|
||||
context.getRenderData(), context.getbNodeTree(), input->getDataType(), format, path,
|
||||
sockdata->layer, context.getViewSettings(), context.getDisplaySettings(), context.getViewName());
|
||||
}
|
||||
|
||||
converter.addOperation(outputOperation);
|
||||
|
||||
converter.mapInputSocket(input, outputOperation->getInputSocket(0));
|
||||
|
||||
|
||||
if (!previewAdded) {
|
||||
converter.addNodeInputPreview(input);
|
||||
previewAdded = true;
|
||||
|
@@ -42,7 +42,8 @@ void RenderLayersNode::testSocketLink(NodeConverter &converter, const Compositor
|
||||
operation->setScene(scene);
|
||||
operation->setLayerId(layerId);
|
||||
operation->setRenderData(context.getRenderData());
|
||||
|
||||
operation->setViewName(context.getViewName());
|
||||
|
||||
converter.mapOutputSocket(outputSocket, operation->getOutputSocket());
|
||||
converter.addOperation(operation);
|
||||
|
||||
|
@@ -22,6 +22,8 @@
|
||||
|
||||
#include "COM_SplitViewerNode.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_image.h"
|
||||
#include "BKE_scene.h"
|
||||
|
||||
#include "COM_SplitOperation.h"
|
||||
#include "COM_ViewerOperation.h"
|
||||
@@ -55,6 +57,8 @@ void SplitViewerNode::convertToOperations(NodeConverter &converter, const Compos
|
||||
viewerOperation->setImageUser(imageUser);
|
||||
viewerOperation->setViewSettings(context.getViewSettings());
|
||||
viewerOperation->setDisplaySettings(context.getDisplaySettings());
|
||||
viewerOperation->setRenderData(context.getRenderData());
|
||||
viewerOperation->setViewName(context.getViewName());
|
||||
|
||||
/* defaults - the viewer node has these options but not exposed for split view
|
||||
* we could use the split to define an area of interest on one axis at least */
|
||||
|
42
source/blender/compositor/nodes/COM_SwitchViewNode.cpp
Normal file
42
source/blender/compositor/nodes/COM_SwitchViewNode.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2015, Blender Foundation.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contributor:
|
||||
* Dalai Felinto
|
||||
*/
|
||||
|
||||
#include "COM_SwitchViewNode.h"
|
||||
#include "BLI_listbase.h"
|
||||
|
||||
SwitchViewNode::SwitchViewNode(bNode *editorNode) : Node(editorNode)
|
||||
{
|
||||
/* pass */
|
||||
}
|
||||
|
||||
void SwitchViewNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
|
||||
{
|
||||
NodeOperationOutput *result;
|
||||
const char *viewName = context.getViewName();
|
||||
bNode *bnode = this->getbNode();
|
||||
|
||||
/* get the internal index of the socket with a matching name */
|
||||
int nr = BLI_findstringindex(&bnode->inputs, viewName, offsetof(bNodeSocket, name));
|
||||
nr = max(nr, 0);
|
||||
|
||||
result = converter.addInputProxy(getInputSocket(nr), false);
|
||||
converter.mapOutputSocket(getOutputSocket(0), result);
|
||||
}
|
37
source/blender/compositor/nodes/COM_SwitchViewNode.h
Normal file
37
source/blender/compositor/nodes/COM_SwitchViewNode.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2015, Blender Foundation.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contributor:
|
||||
* Dalai Felinto
|
||||
*/
|
||||
|
||||
#ifndef _COM_SwitchViewNode_h_
|
||||
#define _COM_SwitchViewNode_h_
|
||||
|
||||
#include "COM_Node.h"
|
||||
#include "COM_NodeOperation.h"
|
||||
#include "DNA_node_types.h"
|
||||
/**
|
||||
* @brief SwitchViewNode
|
||||
* @ingroup Node
|
||||
*/
|
||||
class SwitchViewNode : public Node {
|
||||
public:
|
||||
SwitchViewNode(bNode *editorNode);
|
||||
void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
|
||||
};
|
||||
#endif
|
@@ -22,6 +22,9 @@
|
||||
|
||||
#include "COM_ViewerNode.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_image.h"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BKE_scene.h"
|
||||
|
||||
#include "COM_ViewerOperation.h"
|
||||
#include "COM_ExecutionSystem.h"
|
||||
@@ -51,6 +54,8 @@ void ViewerNode::convertToOperations(NodeConverter &converter, const CompositorC
|
||||
viewerOperation->setCenterY(editorNode->custom4);
|
||||
/* alpha socket gives either 1 or a custom alpha value if "use alpha" is enabled */
|
||||
viewerOperation->setUseAlphaInput(ignore_alpha || alphaSocket->isLinked());
|
||||
viewerOperation->setRenderData(context.getRenderData());
|
||||
viewerOperation->setViewName(context.getViewName());
|
||||
|
||||
viewerOperation->setViewSettings(context.getViewSettings());
|
||||
viewerOperation->setDisplaySettings(context.getDisplaySettings());
|
||||
|
@@ -52,6 +52,7 @@ CompositorOperation::CompositorOperation() : NodeOperation()
|
||||
this->m_active = false;
|
||||
|
||||
this->m_sceneName[0] = '\0';
|
||||
this->m_viewName = NULL;
|
||||
}
|
||||
|
||||
void CompositorOperation::initExecution()
|
||||
@@ -81,14 +82,16 @@ void CompositorOperation::deinitExecution()
|
||||
RenderResult *rr = RE_AcquireResultWrite(re);
|
||||
|
||||
if (rr) {
|
||||
if (rr->rectf != NULL) {
|
||||
MEM_freeN(rr->rectf);
|
||||
RenderView *rv = (RenderView *)BLI_findstring(&rr->views, this->m_viewName, offsetof(RenderView, name));
|
||||
|
||||
if (rv->rectf != NULL) {
|
||||
MEM_freeN(rv->rectf);
|
||||
}
|
||||
rr->rectf = this->m_outputBuffer;
|
||||
if (rr->rectz != NULL) {
|
||||
MEM_freeN(rr->rectz);
|
||||
rv->rectf = this->m_outputBuffer;
|
||||
if (rv->rectz != NULL) {
|
||||
MEM_freeN(rv->rectz);
|
||||
}
|
||||
rr->rectz = this->m_depthBuffer;
|
||||
rv->rectz = this->m_depthBuffer;
|
||||
}
|
||||
else {
|
||||
if (this->m_outputBuffer) {
|
||||
|
@@ -75,11 +75,17 @@ private:
|
||||
* @brief operation is active for calculating final compo result
|
||||
*/
|
||||
bool m_active;
|
||||
|
||||
/**
|
||||
* @brief View name, used for multiview
|
||||
*/
|
||||
const char *m_viewName;
|
||||
public:
|
||||
CompositorOperation();
|
||||
const bool isActiveCompositorOutput() const { return this->m_active; }
|
||||
void executeRegion(rcti *rect, unsigned int tileNumber);
|
||||
void setSceneName(const char *sceneName) { BLI_strncpy(this->m_sceneName, sceneName, sizeof(this->m_sceneName)); }
|
||||
void setViewName(const char *viewName) { this->m_viewName = viewName; }
|
||||
void setRenderData(const RenderData *rd) { this->m_rd = rd; }
|
||||
bool isOutputOperation(bool /*rendering*/) const { return this->isActiveCompositorOutput(); }
|
||||
void initExecution();
|
||||
|
@@ -25,6 +25,7 @@
|
||||
#include "BLI_listbase.h"
|
||||
#include "DNA_image_types.h"
|
||||
#include "BKE_image.h"
|
||||
#include "BKE_scene.h"
|
||||
#include "BLI_math.h"
|
||||
|
||||
extern "C" {
|
||||
@@ -48,6 +49,8 @@ BaseImageOperation::BaseImageOperation() : NodeOperation()
|
||||
this->m_framenumber = 0;
|
||||
this->m_depthBuffer = NULL;
|
||||
this->m_numberOfChannels = 0;
|
||||
this->m_rd = NULL;
|
||||
this->m_viewName = NULL;
|
||||
}
|
||||
ImageOperation::ImageOperation() : BaseImageOperation()
|
||||
{
|
||||
@@ -65,8 +68,12 @@ ImageDepthOperation::ImageDepthOperation() : BaseImageOperation()
|
||||
ImBuf *BaseImageOperation::getImBuf()
|
||||
{
|
||||
ImBuf *ibuf;
|
||||
|
||||
ibuf = BKE_image_acquire_ibuf(this->m_image, this->m_imageUser, NULL);
|
||||
ImageUser iuser = *this->m_imageUser;
|
||||
|
||||
/* local changes to the original ImageUser */
|
||||
iuser.multi_index = BKE_scene_multiview_view_id_get(this->m_rd, this->m_viewName);
|
||||
|
||||
ibuf = BKE_image_acquire_ibuf(this->m_image, &iuser, NULL);
|
||||
if (ibuf == NULL || (ibuf->rect == NULL && ibuf->rect_float == NULL)) {
|
||||
BKE_image_release_ibuf(this->m_image, ibuf, NULL);
|
||||
return NULL;
|
||||
|
@@ -49,7 +49,9 @@ protected:
|
||||
int m_imagewidth;
|
||||
int m_framenumber;
|
||||
int m_numberOfChannels;
|
||||
|
||||
const RenderData *m_rd;
|
||||
const char *m_viewName;
|
||||
|
||||
BaseImageOperation();
|
||||
/**
|
||||
* Determine the output resolution. The resolution is retrieved from the Renderer
|
||||
@@ -64,7 +66,8 @@ public:
|
||||
void deinitExecution();
|
||||
void setImage(Image *image) { this->m_image = image; }
|
||||
void setImageUser(ImageUser *imageuser) { this->m_imageUser = imageuser; }
|
||||
|
||||
void setRenderData(const RenderData *rd) { this->m_rd = rd; }
|
||||
void setViewName(const char *viewName) { this->m_viewName = viewName; }
|
||||
void setFramenumber(int framenumber) { this->m_framenumber = framenumber; }
|
||||
};
|
||||
class ImageOperation : public BaseImageOperation {
|
||||
|
@@ -27,18 +27,27 @@ extern "C" {
|
||||
# include "IMB_imbuf_types.h"
|
||||
}
|
||||
|
||||
MultilayerBaseOperation::MultilayerBaseOperation(int passindex) : BaseImageOperation()
|
||||
MultilayerBaseOperation::MultilayerBaseOperation(int passtype, int view) : BaseImageOperation()
|
||||
{
|
||||
this->m_passId = passindex;
|
||||
this->m_passtype = passtype;
|
||||
this->m_view = view;
|
||||
}
|
||||
|
||||
ImBuf *MultilayerBaseOperation::getImBuf()
|
||||
{
|
||||
RenderPass *rpass = (RenderPass *)BLI_findlink(&this->m_renderlayer->passes, this->m_passId);
|
||||
if (rpass) {
|
||||
this->m_imageUser->pass = m_passId;
|
||||
BKE_image_multilayer_index(this->m_image->rr, this->m_imageUser);
|
||||
return BaseImageOperation::getImBuf();
|
||||
/* temporarily changes the view to get the right ImBuf */
|
||||
int view = this->m_imageUser->view;
|
||||
|
||||
this->m_imageUser->view = this->m_view;
|
||||
this->m_imageUser->passtype = this->m_passtype;
|
||||
|
||||
if (BKE_image_multilayer_index(this->m_image->rr, this->m_imageUser)) {
|
||||
ImBuf *ibuf = BaseImageOperation::getImBuf();
|
||||
this->m_imageUser->view = view;
|
||||
return ibuf;
|
||||
}
|
||||
|
||||
this->m_imageUser->view = view;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@@ -29,7 +29,8 @@
|
||||
|
||||
class MultilayerBaseOperation : public BaseImageOperation {
|
||||
private:
|
||||
int m_passId;
|
||||
int m_passtype;
|
||||
int m_view;
|
||||
RenderLayer *m_renderlayer;
|
||||
protected:
|
||||
ImBuf *getImBuf();
|
||||
@@ -37,13 +38,13 @@ public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
MultilayerBaseOperation(int passindex);
|
||||
MultilayerBaseOperation(int passtype, int view);
|
||||
void setRenderLayer(RenderLayer *renderlayer) { this->m_renderlayer = renderlayer; }
|
||||
};
|
||||
|
||||
class MultilayerColorOperation : public MultilayerBaseOperation {
|
||||
public:
|
||||
MultilayerColorOperation(int passindex) : MultilayerBaseOperation(passindex) {
|
||||
MultilayerColorOperation(int passtype, int view) : MultilayerBaseOperation(passtype, view) {
|
||||
this->addOutputSocket(COM_DT_COLOR);
|
||||
}
|
||||
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
|
||||
@@ -51,7 +52,7 @@ public:
|
||||
|
||||
class MultilayerValueOperation : public MultilayerBaseOperation {
|
||||
public:
|
||||
MultilayerValueOperation(int passindex) : MultilayerBaseOperation(passindex) {
|
||||
MultilayerValueOperation(int passtype, int view) : MultilayerBaseOperation(passtype, view) {
|
||||
this->addOutputSocket(COM_DT_VALUE);
|
||||
}
|
||||
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
|
||||
@@ -59,7 +60,7 @@ public:
|
||||
|
||||
class MultilayerVectorOperation : public MultilayerBaseOperation {
|
||||
public:
|
||||
MultilayerVectorOperation(int passindex) : MultilayerBaseOperation(passindex) {
|
||||
MultilayerVectorOperation(int passtype, int view) : MultilayerBaseOperation(passtype, view) {
|
||||
this->addOutputSocket(COM_DT_VECTOR);
|
||||
}
|
||||
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
|
||||
|
@@ -0,0 +1,317 @@
|
||||
/*
|
||||
* Copyright 2015, Blender Foundation.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contributor:
|
||||
* Jeroen Bakker
|
||||
* Monique Dewanchand
|
||||
* Lukas Tönne
|
||||
* Dalai Felinto
|
||||
*/
|
||||
|
||||
#include "COM_OutputFileOperation.h"
|
||||
#include "COM_OutputFileMultiViewOperation.h"
|
||||
|
||||
#include <string.h>
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_path_util.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BKE_image.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_scene.h"
|
||||
|
||||
#include "DNA_color_types.h"
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
extern "C" {
|
||||
#include "IMB_imbuf.h"
|
||||
#include "IMB_colormanagement.h"
|
||||
#include "IMB_imbuf_types.h"
|
||||
}
|
||||
|
||||
/************************************ OpenEXR Singlelayer Multiview *****************************************/
|
||||
|
||||
OutputOpenExrSingleLayerMultiViewOperation::OutputOpenExrSingleLayerMultiViewOperation(
|
||||
const RenderData *rd, const bNodeTree *tree, DataType datatype, ImageFormatData *format, const char *path,
|
||||
const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings,
|
||||
const char *viewName)
|
||||
: OutputSingleLayerOperation(rd, tree, datatype, format, path, viewSettings, displaySettings, viewName)
|
||||
{
|
||||
}
|
||||
|
||||
void *OutputOpenExrSingleLayerMultiViewOperation::get_handle(const char *filename)
|
||||
{
|
||||
size_t width = this->getWidth();
|
||||
size_t height = this->getHeight();
|
||||
SceneRenderView *srv;
|
||||
|
||||
if (width != 0 && height != 0) {
|
||||
void *exrhandle;
|
||||
|
||||
exrhandle = IMB_exr_get_handle_name(filename);
|
||||
|
||||
if (!BKE_scene_multiview_is_render_view_first(this->m_rd, this->m_viewName))
|
||||
return exrhandle;
|
||||
|
||||
IMB_exr_clear_channels(exrhandle);
|
||||
|
||||
for (srv = (SceneRenderView *)this->m_rd->views.first; srv; srv = srv->next) {
|
||||
if (BKE_scene_multiview_is_render_view_active(this->m_rd, srv) == false)
|
||||
continue;
|
||||
|
||||
IMB_exr_add_view(exrhandle, srv->name);
|
||||
add_exr_channels(exrhandle, NULL, this->m_datatype, srv->name, width, NULL);
|
||||
}
|
||||
|
||||
BLI_make_existing_file(filename);
|
||||
|
||||
/* prepare the file with all the channels */
|
||||
|
||||
if (IMB_exr_begin_write(exrhandle, filename, width, height, this->m_format->exr_codec) == 0) {
|
||||
printf("Error Writing Singlelayer Multiview Openexr\n");
|
||||
IMB_exr_close(exrhandle);
|
||||
}
|
||||
else {
|
||||
IMB_exr_clear_channels(exrhandle);
|
||||
return exrhandle;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void OutputOpenExrSingleLayerMultiViewOperation::deinitExecution()
|
||||
{
|
||||
unsigned int width = this->getWidth();
|
||||
unsigned int height = this->getHeight();
|
||||
|
||||
if (width != 0 && height != 0) {
|
||||
void *exrhandle;
|
||||
Main *bmain = G.main; /* TODO, have this passed along */
|
||||
char filename[FILE_MAX];
|
||||
|
||||
BKE_image_path_from_imtype(
|
||||
filename, this->m_path, bmain->name, this->m_rd->cfra, R_IMF_IMTYPE_OPENEXR,
|
||||
(this->m_rd->scemode & R_EXTENSION) != 0, true, NULL);
|
||||
|
||||
exrhandle = this->get_handle(filename);
|
||||
add_exr_channels(exrhandle, NULL, this->m_datatype, this->m_viewName, width, this->m_outputBuffer);
|
||||
|
||||
/* memory can only be freed after we write all views to the file */
|
||||
this->m_outputBuffer = NULL;
|
||||
this->m_imageInput = NULL;
|
||||
|
||||
/* ready to close the file */
|
||||
if (BKE_scene_multiview_is_render_view_last(this->m_rd, this->m_viewName)) {
|
||||
IMB_exr_write_channels(exrhandle);
|
||||
|
||||
/* free buffer memory for all the views */
|
||||
free_exr_channels(exrhandle, this->m_rd, NULL, this->m_datatype);
|
||||
|
||||
/* remove exr handle and data */
|
||||
IMB_exr_close(exrhandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/************************************ OpenEXR Multilayer Multiview *****************************************/
|
||||
|
||||
OutputOpenExrMultiLayerMultiViewOperation::OutputOpenExrMultiLayerMultiViewOperation(
|
||||
const RenderData *rd, const bNodeTree *tree, const char *path, char exr_codec, const char *viewName)
|
||||
: OutputOpenExrMultiLayerOperation(rd, tree, path, exr_codec, viewName)
|
||||
{
|
||||
}
|
||||
|
||||
void *OutputOpenExrMultiLayerMultiViewOperation::get_handle(const char *filename)
|
||||
{
|
||||
unsigned int width = this->getWidth();
|
||||
unsigned int height = this->getHeight();
|
||||
|
||||
if (width != 0 && height != 0) {
|
||||
|
||||
void *exrhandle;
|
||||
SceneRenderView *srv;
|
||||
|
||||
/* get a new global handle */
|
||||
exrhandle = IMB_exr_get_handle_name(filename);
|
||||
|
||||
if (!BKE_scene_multiview_is_render_view_first(this->m_rd, this->m_viewName))
|
||||
return exrhandle;
|
||||
|
||||
IMB_exr_clear_channels(exrhandle);
|
||||
|
||||
/* check renderdata for amount of views */
|
||||
for (srv = (SceneRenderView *) this->m_rd->views.first; srv; srv = srv->next) {
|
||||
|
||||
if (BKE_scene_multiview_is_render_view_active(this->m_rd, srv) == false)
|
||||
continue;
|
||||
|
||||
IMB_exr_add_view(exrhandle, srv->name);
|
||||
|
||||
for (unsigned int i = 0; i < this->m_layers.size(); ++i)
|
||||
add_exr_channels(exrhandle, this->m_layers[i].name, this->m_layers[i].datatype, srv->name, width, NULL);
|
||||
}
|
||||
|
||||
BLI_make_existing_file(filename);
|
||||
|
||||
/* prepare the file with all the channels for the header */
|
||||
if (IMB_exr_begin_write(exrhandle, filename, width, height, this->m_exr_codec) == 0) {
|
||||
printf("Error Writing Multilayer Multiview Openexr\n");
|
||||
IMB_exr_close(exrhandle);
|
||||
}
|
||||
else {
|
||||
IMB_exr_clear_channels(exrhandle);
|
||||
return exrhandle;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void OutputOpenExrMultiLayerMultiViewOperation::deinitExecution()
|
||||
{
|
||||
unsigned int width = this->getWidth();
|
||||
unsigned int height = this->getHeight();
|
||||
|
||||
if (width != 0 && height != 0) {
|
||||
void *exrhandle;
|
||||
Main *bmain = G.main; /* TODO, have this passed along */
|
||||
char filename[FILE_MAX];
|
||||
|
||||
BKE_image_path_from_imtype(
|
||||
filename, this->m_path, bmain->name, this->m_rd->cfra, R_IMF_IMTYPE_MULTILAYER,
|
||||
(this->m_rd->scemode & R_EXTENSION) != 0, true, NULL);
|
||||
|
||||
exrhandle = this->get_handle(filename);
|
||||
|
||||
for (unsigned int i = 0; i < this->m_layers.size(); ++i)
|
||||
add_exr_channels(exrhandle, this->m_layers[i].name, this->m_layers[i].datatype, this->m_viewName, width, this->m_layers[i].outputBuffer);
|
||||
|
||||
for (unsigned int i = 0; i < this->m_layers.size(); ++i) {
|
||||
/* memory can only be freed after we write all views to the file */
|
||||
this->m_layers[i].outputBuffer = NULL;
|
||||
this->m_layers[i].imageInput = NULL;
|
||||
}
|
||||
|
||||
/* ready to close the file */
|
||||
if (BKE_scene_multiview_is_render_view_last(this->m_rd, this->m_viewName)) {
|
||||
IMB_exr_write_channels(exrhandle);
|
||||
|
||||
/* free buffer memory for all the views */
|
||||
for (unsigned int i = 0; i < this->m_layers.size(); ++i) {
|
||||
free_exr_channels(exrhandle, this->m_rd, this->m_layers[i].name, this->m_layers[i].datatype);
|
||||
}
|
||||
|
||||
IMB_exr_close(exrhandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/******************************** Stereo3D ******************************/
|
||||
|
||||
OutputStereoOperation::OutputStereoOperation(
|
||||
const RenderData *rd, const bNodeTree *tree, DataType datatype, ImageFormatData *format, const char *path,
|
||||
const char *name, const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings,
|
||||
const char *viewName)
|
||||
: OutputSingleLayerOperation(rd, tree, datatype, format, path, viewSettings, displaySettings, viewName)
|
||||
{
|
||||
BLI_strncpy(this->m_name, name, sizeof(this->m_name));
|
||||
this->m_channels = get_datatype_size(datatype);
|
||||
}
|
||||
|
||||
void *OutputStereoOperation::get_handle(const char *filename)
|
||||
{
|
||||
size_t width = this->getWidth();
|
||||
size_t height = this->getHeight();
|
||||
const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
|
||||
size_t i;
|
||||
|
||||
if (width != 0 && height != 0) {
|
||||
void *exrhandle;
|
||||
|
||||
exrhandle = IMB_exr_get_handle_name(filename);
|
||||
|
||||
if (!BKE_scene_multiview_is_render_view_first(this->m_rd, this->m_viewName))
|
||||
return exrhandle;
|
||||
|
||||
IMB_exr_clear_channels(exrhandle);
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
IMB_exr_add_view(exrhandle, names[i]);
|
||||
|
||||
return exrhandle;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void OutputStereoOperation::deinitExecution()
|
||||
{
|
||||
unsigned int width = this->getWidth();
|
||||
unsigned int height = this->getHeight();
|
||||
|
||||
if (width != 0 && height != 0) {
|
||||
void *exrhandle;
|
||||
|
||||
exrhandle = this->get_handle(this->m_path);
|
||||
float *buf = this->m_outputBuffer;
|
||||
|
||||
/* populate single EXR channel with view data */
|
||||
IMB_exr_add_channel(exrhandle, NULL, this->m_name, this->m_viewName, 1, this->m_channels * width * height, buf);
|
||||
|
||||
this->m_imageInput = NULL;
|
||||
this->m_outputBuffer = NULL;
|
||||
|
||||
/* create stereo ibuf */
|
||||
if (BKE_scene_multiview_is_render_view_last(this->m_rd, this->m_viewName)) {
|
||||
ImBuf *ibuf[3] = {NULL};
|
||||
const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
|
||||
Main *bmain = G.main; /* TODO, have this passed along */
|
||||
char filename[FILE_MAX];
|
||||
int i;
|
||||
|
||||
/* get rectf from EXR */
|
||||
for (i = 0; i < 2; i++) {
|
||||
float *rectf = IMB_exr_channel_rect(exrhandle, NULL, this->m_name, names[i]);
|
||||
ibuf[i] = IMB_allocImBuf(width, height, this->m_format->planes, 0);
|
||||
|
||||
ibuf[i]->channels = this->m_channels;
|
||||
ibuf[i]->rect_float = rectf;
|
||||
ibuf[i]->mall |= IB_rectfloat;
|
||||
ibuf[i]->dither = this->m_rd->dither_intensity;
|
||||
|
||||
/* do colormanagement in the individual views, so it doesn't need to do in the stereo */
|
||||
IMB_colormanagement_imbuf_for_write(ibuf[i], true, false, this->m_viewSettings,
|
||||
this->m_displaySettings, this->m_format);
|
||||
IMB_prepare_write_ImBuf(IMB_isfloat(ibuf[i]), ibuf[i]);
|
||||
}
|
||||
|
||||
/* create stereo buffer */
|
||||
ibuf[2] = IMB_stereo3d_ImBuf(this->m_format, ibuf[0], ibuf[1]);
|
||||
|
||||
BKE_image_path_from_imformat(
|
||||
filename, this->m_path, bmain->name, this->m_rd->cfra, this->m_format,
|
||||
(this->m_rd->scemode & R_EXTENSION) != 0, true, NULL);
|
||||
|
||||
BKE_imbuf_write(ibuf[2], filename, this->m_format);
|
||||
|
||||
/* imbuf knows which rects are not part of ibuf */
|
||||
for (i = 0; i < 3; i++)
|
||||
IMB_freeImBuf(ibuf[i]);
|
||||
|
||||
IMB_exr_close(exrhandle);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2015, Blender Foundation.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contributor:
|
||||
* Jeroen Bakker
|
||||
* Monique Dewanchand
|
||||
* Lukas Tönne
|
||||
* Dalai Felinto
|
||||
*/
|
||||
|
||||
#ifndef _COM_OutputFileMultiViewOperation_h
|
||||
#define _COM_OutputFileMultiViewOperation_h
|
||||
#include "COM_NodeOperation.h"
|
||||
|
||||
#include "BLI_rect.h"
|
||||
#include "BLI_path_util.h"
|
||||
|
||||
#include "DNA_color_types.h"
|
||||
#include "DNA_userdef_types.h"
|
||||
|
||||
#include "intern/openexr/openexr_multi.h"
|
||||
|
||||
class OutputOpenExrSingleLayerMultiViewOperation : public OutputSingleLayerOperation {
|
||||
private:
|
||||
public:
|
||||
OutputOpenExrSingleLayerMultiViewOperation(const RenderData *rd, const bNodeTree *tree, DataType datatype,
|
||||
ImageFormatData *format, const char *path,
|
||||
const ColorManagedViewSettings *viewSettings,
|
||||
const ColorManagedDisplaySettings *displaySettings,
|
||||
const char *viewName);
|
||||
|
||||
void *get_handle(const char *filename);
|
||||
void deinitExecution();
|
||||
};
|
||||
|
||||
/* Writes inputs into OpenEXR multilayer channels. */
|
||||
class OutputOpenExrMultiLayerMultiViewOperation : public OutputOpenExrMultiLayerOperation {
|
||||
private:
|
||||
public:
|
||||
OutputOpenExrMultiLayerMultiViewOperation(const RenderData *rd, const bNodeTree *tree, const char *path, char exr_codec, const char *viewName);
|
||||
|
||||
void *get_handle(const char *filename);
|
||||
void deinitExecution();
|
||||
};
|
||||
|
||||
/**/
|
||||
class OutputStereoOperation : public OutputSingleLayerOperation {
|
||||
private:
|
||||
char m_name[FILE_MAX];
|
||||
size_t m_channels;
|
||||
public:
|
||||
OutputStereoOperation(const RenderData *rd, const bNodeTree *tree, DataType datatype,
|
||||
struct ImageFormatData *format, const char *path, const char *name,
|
||||
const ColorManagedViewSettings *viewSettings,
|
||||
const ColorManagedDisplaySettings *displaySettings, const char *viewName);
|
||||
void *get_handle(const char *filename);
|
||||
void deinitExecution();
|
||||
};
|
||||
|
||||
#endif
|
@@ -29,6 +29,7 @@
|
||||
#include "BKE_image.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_scene.h"
|
||||
|
||||
#include "DNA_color_types.h"
|
||||
|
||||
@@ -39,7 +40,60 @@ extern "C" {
|
||||
# include "IMB_imbuf_types.h"
|
||||
}
|
||||
|
||||
static int get_datatype_size(DataType datatype)
|
||||
void add_exr_channels(void *exrhandle, const char *layerName, const DataType datatype, const char *viewName, const size_t width, float *buf)
|
||||
{
|
||||
/* create channels */
|
||||
switch (datatype) {
|
||||
case COM_DT_VALUE:
|
||||
IMB_exr_add_channel(exrhandle, layerName, "V", viewName, 1, width, buf ? buf : NULL);
|
||||
break;
|
||||
case COM_DT_VECTOR:
|
||||
IMB_exr_add_channel(exrhandle, layerName, "X", viewName, 3, 3 * width, buf ? buf : NULL);
|
||||
IMB_exr_add_channel(exrhandle, layerName, "Y", viewName, 3, 3 * width, buf ? buf + 1 : NULL);
|
||||
IMB_exr_add_channel(exrhandle, layerName, "Z", viewName, 3, 3 * width, buf ? buf + 2 : NULL);
|
||||
break;
|
||||
case COM_DT_COLOR:
|
||||
IMB_exr_add_channel(exrhandle, layerName, "R", viewName, 4, 4 * width, buf ? buf : NULL);
|
||||
IMB_exr_add_channel(exrhandle, layerName, "G", viewName, 4, 4 * width, buf ? buf + 1 : NULL);
|
||||
IMB_exr_add_channel(exrhandle, layerName, "B", viewName, 4, 4 * width, buf ? buf + 2 : NULL);
|
||||
IMB_exr_add_channel(exrhandle, layerName, "A", viewName, 4, 4 * width, buf ? buf + 3 : NULL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void free_exr_channels(void *exrhandle, const RenderData *rd, const char *layerName, const DataType datatype)
|
||||
{
|
||||
SceneRenderView *srv;
|
||||
|
||||
/* check renderdata for amount of views */
|
||||
for (srv = (SceneRenderView *) rd->views.first; srv; srv = srv->next) {
|
||||
float *rect = NULL;
|
||||
|
||||
if (BKE_scene_multiview_is_render_view_active(rd, srv) == false)
|
||||
continue;
|
||||
|
||||
/* the pointer is stored in the first channel of each datatype */
|
||||
switch (datatype) {
|
||||
case COM_DT_VALUE:
|
||||
rect = IMB_exr_channel_rect(exrhandle, layerName, "V", srv->name);
|
||||
break;
|
||||
case COM_DT_VECTOR:
|
||||
rect = IMB_exr_channel_rect(exrhandle, layerName, "X", srv->name);
|
||||
break;
|
||||
case COM_DT_COLOR:
|
||||
rect = IMB_exr_channel_rect(exrhandle, layerName, "R", srv->name);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (rect)
|
||||
MEM_freeN(rect);
|
||||
}
|
||||
}
|
||||
|
||||
int get_datatype_size(DataType datatype)
|
||||
{
|
||||
switch (datatype) {
|
||||
case COM_DT_VALUE: return 1;
|
||||
@@ -94,7 +148,7 @@ static void write_buffer_rect(rcti *rect, const bNodeTree *tree,
|
||||
|
||||
OutputSingleLayerOperation::OutputSingleLayerOperation(
|
||||
const RenderData *rd, const bNodeTree *tree, DataType datatype, ImageFormatData *format, const char *path,
|
||||
const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings)
|
||||
const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings, const char *viewName)
|
||||
{
|
||||
this->m_rd = rd;
|
||||
this->m_tree = tree;
|
||||
@@ -110,6 +164,7 @@ OutputSingleLayerOperation::OutputSingleLayerOperation(
|
||||
|
||||
this->m_viewSettings = viewSettings;
|
||||
this->m_displaySettings = displaySettings;
|
||||
this->m_viewName = viewName;
|
||||
}
|
||||
|
||||
void OutputSingleLayerOperation::initExecution()
|
||||
@@ -131,6 +186,7 @@ void OutputSingleLayerOperation::deinitExecution()
|
||||
ImBuf *ibuf = IMB_allocImBuf(this->getWidth(), this->getHeight(), this->m_format->planes, 0);
|
||||
Main *bmain = G.main; /* TODO, have this passed along */
|
||||
char filename[FILE_MAX];
|
||||
const char *suffix;
|
||||
|
||||
ibuf->channels = size;
|
||||
ibuf->rect_float = this->m_outputBuffer;
|
||||
@@ -140,10 +196,12 @@ void OutputSingleLayerOperation::deinitExecution()
|
||||
IMB_colormanagement_imbuf_for_write(ibuf, true, false, m_viewSettings, m_displaySettings,
|
||||
this->m_format);
|
||||
|
||||
suffix = BKE_scene_multiview_view_suffix_get(this->m_rd, this->m_viewName);
|
||||
|
||||
BKE_image_path_from_imformat(
|
||||
filename, this->m_path, bmain->name, this->m_rd->cfra,
|
||||
this->m_format, (this->m_rd->scemode & R_EXTENSION) != 0, true);
|
||||
|
||||
filename, this->m_path, bmain->name, this->m_rd->cfra, this->m_format,
|
||||
(this->m_rd->scemode & R_EXTENSION) != 0, true, suffix);
|
||||
|
||||
if (0 == BKE_imbuf_write(ibuf, filename, this->m_format))
|
||||
printf("Cannot save Node File Output to %s\n", filename);
|
||||
else
|
||||
@@ -155,6 +213,7 @@ void OutputSingleLayerOperation::deinitExecution()
|
||||
this->m_imageInput = NULL;
|
||||
}
|
||||
|
||||
/******************************* MultiLayer *******************************/
|
||||
|
||||
OutputOpenExrLayer::OutputOpenExrLayer(const char *name_, DataType datatype_, bool use_layer_)
|
||||
{
|
||||
@@ -168,13 +227,14 @@ OutputOpenExrLayer::OutputOpenExrLayer(const char *name_, DataType datatype_, bo
|
||||
}
|
||||
|
||||
OutputOpenExrMultiLayerOperation::OutputOpenExrMultiLayerOperation(
|
||||
const RenderData *rd, const bNodeTree *tree, const char *path, char exr_codec)
|
||||
const RenderData *rd, const bNodeTree *tree, const char *path, char exr_codec, const char *viewName)
|
||||
{
|
||||
this->m_rd = rd;
|
||||
this->m_tree = tree;
|
||||
|
||||
BLI_strncpy(this->m_path, path, sizeof(this->m_path));
|
||||
this->m_exr_codec = exr_codec;
|
||||
this->m_viewName = viewName;
|
||||
}
|
||||
|
||||
void OutputOpenExrMultiLayerOperation::add_layer(const char *name, DataType datatype, bool use_layer)
|
||||
@@ -210,52 +270,21 @@ void OutputOpenExrMultiLayerOperation::deinitExecution()
|
||||
if (width != 0 && height != 0) {
|
||||
Main *bmain = G.main; /* TODO, have this passed along */
|
||||
char filename[FILE_MAX];
|
||||
const char *suffix;
|
||||
void *exrhandle = IMB_exr_get_handle();
|
||||
|
||||
|
||||
suffix = BKE_scene_multiview_view_suffix_get(this->m_rd, this->m_viewName);
|
||||
BKE_image_path_from_imtype(
|
||||
filename, this->m_path, bmain->name, this->m_rd->cfra, R_IMF_IMTYPE_MULTILAYER,
|
||||
(this->m_rd->scemode & R_EXTENSION) != 0, true);
|
||||
(this->m_rd->scemode & R_EXTENSION) != 0, true, suffix);
|
||||
BLI_make_existing_file(filename);
|
||||
|
||||
|
||||
for (unsigned int i = 0; i < this->m_layers.size(); ++i) {
|
||||
OutputOpenExrLayer &layer = this->m_layers[i];
|
||||
if (!layer.imageInput)
|
||||
continue; /* skip unconnected sockets */
|
||||
|
||||
char channelname[EXR_TOT_MAXNAME];
|
||||
BLI_strncpy(channelname, this->m_layers[i].name, sizeof(channelname) - 2);
|
||||
char *channelname_ext = channelname + strlen(channelname);
|
||||
|
||||
float *buf = this->m_layers[i].outputBuffer;
|
||||
|
||||
/* create channels */
|
||||
switch (this->m_layers[i].datatype) {
|
||||
case COM_DT_VALUE:
|
||||
strcpy(channelname_ext, ".V");
|
||||
IMB_exr_add_channel(exrhandle, 0, channelname, 1, width, buf);
|
||||
break;
|
||||
case COM_DT_VECTOR:
|
||||
strcpy(channelname_ext, ".X");
|
||||
IMB_exr_add_channel(exrhandle, 0, channelname, 3, 3 * width, buf);
|
||||
strcpy(channelname_ext, ".Y");
|
||||
IMB_exr_add_channel(exrhandle, 0, channelname, 3, 3 * width, buf + 1);
|
||||
strcpy(channelname_ext, ".Z");
|
||||
IMB_exr_add_channel(exrhandle, 0, channelname, 3, 3 * width, buf + 2);
|
||||
break;
|
||||
case COM_DT_COLOR:
|
||||
strcpy(channelname_ext, ".R");
|
||||
IMB_exr_add_channel(exrhandle, 0, channelname, 4, 4 * width, buf);
|
||||
strcpy(channelname_ext, ".G");
|
||||
IMB_exr_add_channel(exrhandle, 0, channelname, 4, 4 * width, buf + 1);
|
||||
strcpy(channelname_ext, ".B");
|
||||
IMB_exr_add_channel(exrhandle, 0, channelname, 4, 4 * width, buf + 2);
|
||||
strcpy(channelname_ext, ".A");
|
||||
IMB_exr_add_channel(exrhandle, 0, channelname, 4, 4 * width, buf + 3);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
add_exr_channels(exrhandle, this->m_layers[i].name, this->m_layers[i].datatype, "", width, this->m_layers[i].outputBuffer);
|
||||
}
|
||||
|
||||
/* when the filename has no permissions, this can fail */
|
||||
@@ -279,3 +308,4 @@ void OutputOpenExrMultiLayerOperation::deinitExecution()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -34,7 +34,7 @@
|
||||
|
||||
/* Writes the image to a single-layer file. */
|
||||
class OutputSingleLayerOperation : public NodeOperation {
|
||||
private:
|
||||
protected:
|
||||
const RenderData *m_rd;
|
||||
const bNodeTree *m_tree;
|
||||
|
||||
@@ -47,9 +47,11 @@ private:
|
||||
|
||||
const ColorManagedViewSettings *m_viewSettings;
|
||||
const ColorManagedDisplaySettings *m_displaySettings;
|
||||
|
||||
const char *m_viewName;
|
||||
public:
|
||||
OutputSingleLayerOperation(const RenderData *rd, const bNodeTree *tree, DataType datatype, ImageFormatData *format, const char *path,
|
||||
const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings);
|
||||
const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings, const char *viewName);
|
||||
|
||||
void executeRegion(rcti *rect, unsigned int tileNumber);
|
||||
bool isOutputOperation(bool /*rendering*/) const { return true; }
|
||||
@@ -75,7 +77,7 @@ struct OutputOpenExrLayer {
|
||||
|
||||
/* Writes inputs into OpenEXR multilayer channels. */
|
||||
class OutputOpenExrMultiLayerOperation : public NodeOperation {
|
||||
private:
|
||||
protected:
|
||||
typedef std::vector<OutputOpenExrLayer> LayerList;
|
||||
|
||||
const RenderData *m_rd;
|
||||
@@ -84,9 +86,10 @@ private:
|
||||
char m_path[FILE_MAX];
|
||||
char m_exr_codec;
|
||||
LayerList m_layers;
|
||||
const char *m_viewName;
|
||||
|
||||
public:
|
||||
OutputOpenExrMultiLayerOperation(const RenderData *rd, const bNodeTree *tree, const char *path, char exr_codec);
|
||||
OutputOpenExrMultiLayerOperation(const RenderData *rd, const bNodeTree *tree, const char *path, char exr_codec, const char *viewName);
|
||||
|
||||
void add_layer(const char *name, DataType datatype, bool use_layer);
|
||||
|
||||
@@ -99,4 +102,8 @@ public:
|
||||
bool isFileOutputOperation() const { return true; }
|
||||
};
|
||||
|
||||
void add_exr_channels(void *exrhandle, const char *layerName, const DataType datatype, const char *viewName, const size_t width, float *buf);
|
||||
void free_exr_channels(void *exrhandle, const RenderData *rd, const char *layerName, const DataType datatype);
|
||||
int get_datatype_size(DataType datatype);
|
||||
|
||||
#endif
|
||||
|
@@ -23,6 +23,7 @@
|
||||
#include "COM_RenderLayersProg.h"
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
#include "BKE_scene.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
extern "C" {
|
||||
@@ -57,11 +58,10 @@ void RenderLayersBaseProg::initExecution()
|
||||
if (srl) {
|
||||
|
||||
RenderLayer *rl = RE_GetRenderLayer(rr, srl->name);
|
||||
if (rl && rl->rectf) {
|
||||
this->m_inputBuffer = RE_RenderLayerGetPass(rl, this->m_renderpass);
|
||||
|
||||
if (rl) {
|
||||
this->m_inputBuffer = RE_RenderLayerGetPass(rl, this->m_renderpass, this->m_viewName);
|
||||
if (this->m_inputBuffer == NULL && this->m_renderpass == SCE_PASS_COMBINED) {
|
||||
this->m_inputBuffer = rl->rectf;
|
||||
this->m_inputBuffer = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, this->m_viewName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -195,7 +195,7 @@ void RenderLayersBaseProg::determineResolution(unsigned int resolution[2], unsig
|
||||
SceneRenderLayer *srl = (SceneRenderLayer *)BLI_findlink(&sce->r.layers, getLayerId());
|
||||
if (srl) {
|
||||
RenderLayer *rl = RE_GetRenderLayer(rr, srl->name);
|
||||
if (rl && rl->rectf) {
|
||||
if (rl) {
|
||||
resolution[0] = rl->rectx;
|
||||
resolution[1] = rl->recty;
|
||||
}
|
||||
|
@@ -51,7 +51,12 @@ private:
|
||||
* layerId of the layer where this operation needs to get its data from
|
||||
*/
|
||||
short m_layerId;
|
||||
|
||||
|
||||
/**
|
||||
* viewName of the view to use (unless another view is specified by the node
|
||||
*/
|
||||
const char *m_viewName;
|
||||
|
||||
/**
|
||||
* cached instance to the float buffer inside the layer
|
||||
*/
|
||||
@@ -97,6 +102,8 @@ public:
|
||||
void setRenderData(const RenderData *rd) { this->m_rd = rd; }
|
||||
void setLayerId(short layerId) { this->m_layerId = layerId; }
|
||||
short getLayerId() { return this->m_layerId; }
|
||||
void setViewName(const char *viewName) { this->m_viewName = viewName; }
|
||||
const char *getViewName() { return this->m_viewName; }
|
||||
void initExecution();
|
||||
void deinitExecution();
|
||||
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
|
||||
|
@@ -23,6 +23,7 @@
|
||||
#include "COM_ViewerOperation.h"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BKE_image.h"
|
||||
#include "BKE_scene.h"
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
#include "PIL_time.h"
|
||||
@@ -57,6 +58,8 @@ ViewerOperation::ViewerOperation() : NodeOperation()
|
||||
this->m_imageInput = NULL;
|
||||
this->m_alphaInput = NULL;
|
||||
this->m_depthInput = NULL;
|
||||
this->m_rd = NULL;
|
||||
this->m_viewName = NULL;
|
||||
}
|
||||
|
||||
void ViewerOperation::initExecution()
|
||||
@@ -123,8 +126,18 @@ void ViewerOperation::executeRegion(rcti *rect, unsigned int /*tileNumber*/)
|
||||
void ViewerOperation::initImage()
|
||||
{
|
||||
Image *ima = this->m_image;
|
||||
ImageUser iuser = *this->m_imageUser;
|
||||
void *lock;
|
||||
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, this->m_imageUser, &lock);
|
||||
ImBuf *ibuf;
|
||||
|
||||
/* make sure the image has the correct number of views */
|
||||
if (ima && BKE_scene_multiview_is_render_view_first(this->m_rd, this->m_viewName)) {
|
||||
BKE_image_verify_viewer_views(this->m_rd, ima, this->m_imageUser);
|
||||
}
|
||||
|
||||
/* local changes to the original ImageUser */
|
||||
iuser.multi_index = BKE_scene_multiview_view_id_get(this->m_rd, this->m_viewName);
|
||||
ibuf = BKE_image_acquire_ibuf(ima, &iuser, &lock);
|
||||
|
||||
if (!ibuf) return;
|
||||
BLI_lock_thread(LOCK_DRAW_IMAGE);
|
||||
|
@@ -40,7 +40,9 @@ private:
|
||||
bool m_doDepthBuffer;
|
||||
ImBuf *m_ibuf;
|
||||
bool m_useAlphaInput;
|
||||
|
||||
const RenderData *m_rd;
|
||||
const char *m_viewName;
|
||||
|
||||
const ColorManagedViewSettings *m_viewSettings;
|
||||
const ColorManagedDisplaySettings *m_displaySettings;
|
||||
|
||||
@@ -67,6 +69,8 @@ public:
|
||||
const CompositorPriority getRenderPriority() const;
|
||||
bool isViewerOperation() const { return true; }
|
||||
void setUseAlphaInput(bool value) { this->m_useAlphaInput = value; }
|
||||
void setRenderData(const RenderData *rd) { this->m_rd = rd; }
|
||||
void setViewName(const char *viewName) { this->m_viewName = viewName; }
|
||||
|
||||
void setViewSettings(const ColorManagedViewSettings *viewSettings) { this->m_viewSettings = viewSettings; }
|
||||
void setDisplaySettings(const ColorManagedDisplaySettings *displaySettings) { this->m_displaySettings = displaySettings; }
|
||||
|
@@ -112,6 +112,7 @@ void ED_screen_full_prevspace(struct bContext *C, ScrArea *sa);
|
||||
void ED_screen_full_restore(struct bContext *C, ScrArea *sa);
|
||||
struct ScrArea *ED_screen_state_toggle(struct bContext *C, struct wmWindow *win, struct ScrArea *sa, const short state);
|
||||
void ED_screens_header_tools_menu_create(struct bContext *C, struct uiLayout *layout, void *arg);
|
||||
bool ED_screen_stereo3d_required(struct bScreen *screen);
|
||||
|
||||
/* anim */
|
||||
void ED_update_for_newframe(struct Main *bmain, struct Scene *scene, int mute);
|
||||
|
@@ -323,12 +323,13 @@ void ED_view3d_draw_offscreen(
|
||||
struct Scene *scene, struct View3D *v3d, struct ARegion *ar, int winx, int winy, float viewmat[4][4],
|
||||
float winmat[4][4], bool do_bgpic, bool do_sky, bool is_persp,
|
||||
struct GPUOffScreen *ofs,
|
||||
struct GPUFX *fx, struct GPUFXSettings *fx_settings);
|
||||
struct GPUFX *fx, struct GPUFXSettings *fx_settings,
|
||||
const char *viewname);
|
||||
|
||||
struct ImBuf *ED_view3d_draw_offscreen_imbuf(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, int sizex, int sizey, unsigned int flag,
|
||||
bool draw_background, int alpha_mode, char err_out[256]);
|
||||
bool draw_background, int alpha_mode, const char *viewname, char err_out[256]);
|
||||
struct ImBuf *ED_view3d_draw_offscreen_imbuf_simple(struct Scene *scene, struct Object *camera, int width, int height, unsigned int flag, int drawtype,
|
||||
bool use_solid_tex, bool use_gpencil, bool draw_background, int alpha_mode, char err_out[256]);
|
||||
bool use_solid_tex, bool use_gpencil, bool draw_background, int alpha_mode, const char *viewname, char err_out[256]);
|
||||
|
||||
struct Base *ED_view3d_give_base_under_cursor(struct bContext *C, const int mval[2]);
|
||||
void ED_view3d_quadview_update(struct ScrArea *sa, struct ARegion *ar, bool do_clip);
|
||||
|
@@ -889,6 +889,9 @@ void uiTemplateGameStates(uiLayout *layout, struct PointerRNA *ptr, const char *
|
||||
PointerRNA *used_ptr, const char *used_propname, int active_state);
|
||||
void uiTemplateImage(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname, struct PointerRNA *userptr, int compact);
|
||||
void uiTemplateImageSettings(uiLayout *layout, struct PointerRNA *imfptr, int color_management);
|
||||
void uiTemplateImageStereo3d(uiLayout *layout, struct PointerRNA *stereo3d_format_ptr);
|
||||
void uiTemplateImageViews(uiLayout *layout, struct PointerRNA *imaptr);
|
||||
void uiTemplateImageFormatViews(uiLayout *layout, PointerRNA *imfptr, PointerRNA *ptr);
|
||||
void uiTemplateImageLayers(uiLayout *layout, struct bContext *C, struct Image *ima, struct ImageUser *iuser);
|
||||
void uiTemplateImageInfo(uiLayout *layout, struct bContext *C, Image *ima, ImageUser *iuser);
|
||||
void uiTemplateRunningJobs(uiLayout *layout, struct bContext *C);
|
||||
|
@@ -613,6 +613,7 @@ static int editsource_exec(bContext *C, wmOperator *op)
|
||||
|
||||
/* redraw and get active button python info */
|
||||
ED_region_do_draw(C, ar);
|
||||
ar->do_draw = false;
|
||||
|
||||
for (BLI_ghashIterator_init(&ghi, ui_editsource_info->hash);
|
||||
BLI_ghashIterator_done(&ghi) == false;
|
||||
|
@@ -929,7 +929,7 @@ cage_cleanup:
|
||||
BakeData *bake = &scene->r.bake;
|
||||
char name[FILE_MAX];
|
||||
|
||||
BKE_image_path_from_imtype(name, filepath, bmain->name, 0, bake->im_format.imtype, true, false);
|
||||
BKE_image_path_from_imtype(name, filepath, bmain->name, 0, bake->im_format.imtype, true, false, NULL);
|
||||
|
||||
if (is_automatic_name) {
|
||||
BLI_path_suffix(name, FILE_MAX, ob_low->id.name + 2, "_");
|
||||
|
@@ -55,6 +55,9 @@ void MATERIAL_OT_paste(struct wmOperatorType *ot);
|
||||
void SCENE_OT_render_layer_add(struct wmOperatorType *ot);
|
||||
void SCENE_OT_render_layer_remove(struct wmOperatorType *ot);
|
||||
|
||||
void SCENE_OT_render_view_add(struct wmOperatorType *ot);
|
||||
void SCENE_OT_render_view_remove(struct wmOperatorType *ot);
|
||||
|
||||
#ifdef WITH_FREESTYLE
|
||||
void SCENE_OT_freestyle_module_add(struct wmOperatorType *ot);
|
||||
void SCENE_OT_freestyle_module_remove(struct wmOperatorType *ot);
|
||||
|
@@ -48,6 +48,7 @@
|
||||
#include "DNA_userdef_types.h"
|
||||
|
||||
#include "BKE_blender.h"
|
||||
#include "BKE_camera.h"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_colortools.h"
|
||||
#include "BKE_depsgraph.h"
|
||||
@@ -116,7 +117,7 @@ typedef struct RenderJob {
|
||||
} RenderJob;
|
||||
|
||||
/* called inside thread! */
|
||||
static void image_buffer_rect_update(RenderJob *rj, RenderResult *rr, ImBuf *ibuf, ImageUser *iuser, volatile rcti *renrect)
|
||||
static void image_buffer_rect_update(RenderJob *rj, RenderResult *rr, ImBuf *ibuf, ImageUser *iuser, volatile rcti *renrect, const char *viewname)
|
||||
{
|
||||
Scene *scene = rj->scene;
|
||||
const float *rectf = NULL;
|
||||
@@ -188,11 +189,11 @@ static void image_buffer_rect_update(RenderJob *rj, RenderResult *rr, ImBuf *ibu
|
||||
*/
|
||||
/* TODO(sergey): Need to check has_combined here? */
|
||||
if (iuser->pass == 0) {
|
||||
size_t view_id = BKE_scene_multiview_view_id_get(&scene->r, viewname);
|
||||
/* find current float rect for display, first case is after composite... still weak */
|
||||
if (rr->rectf)
|
||||
rectf = rr->rectf;
|
||||
else {
|
||||
if (rr->rect32) {
|
||||
rectf = RE_RenderViewGetRectf(rr, view_id);
|
||||
if (rectf == NULL) {
|
||||
if (RE_RenderViewGetRect32(rr, view_id)) {
|
||||
/* special case, currently only happens with sequencer rendering,
|
||||
* which updates the whole frame, so we can only mark display buffer
|
||||
* as invalid here (sergey)
|
||||
@@ -201,8 +202,8 @@ static void image_buffer_rect_update(RenderJob *rj, RenderResult *rr, ImBuf *ibu
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if (rr->renlay == NULL || rr->renlay->rectf == NULL) return;
|
||||
rectf = rr->renlay->rectf;
|
||||
if (rr->renlay == NULL) return;
|
||||
rectf = RE_RenderLayerGetPass(rr->renlay, SCE_PASS_COMBINED, viewname);
|
||||
}
|
||||
}
|
||||
if (rectf == NULL) return;
|
||||
@@ -531,6 +532,7 @@ static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrec
|
||||
Image *ima = rj->image;
|
||||
ImBuf *ibuf;
|
||||
void *lock;
|
||||
const char *viewname = RE_GetActiveRenderView(rj->re);
|
||||
|
||||
/* only update if we are displaying the slot being rendered */
|
||||
if (ima->render_slot != ima->last_render_slot) {
|
||||
@@ -563,7 +565,7 @@ static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrec
|
||||
ibuf->channels == 1 ||
|
||||
U.image_draw_method != IMAGE_DRAW_METHOD_GLSL)
|
||||
{
|
||||
image_buffer_rect_update(rj, rr, ibuf, &rj->iuser, renrect);
|
||||
image_buffer_rect_update(rj, rr, ibuf, &rj->iuser, renrect, viewname);
|
||||
}
|
||||
|
||||
/* make jobs timer to send notifier */
|
||||
@@ -1487,7 +1489,8 @@ void render_view3d_draw(RenderEngine *engine, const bContext *C)
|
||||
if (re == NULL) return;
|
||||
}
|
||||
|
||||
RE_AcquireResultImage(re, &rres);
|
||||
/* Viewport render preview doesn't support multiview, view hardcoded to 0 */
|
||||
RE_AcquireResultImage(re, &rres, 0);
|
||||
|
||||
if (rres.rectf) {
|
||||
RegionView3D *rv3d = CTX_wm_region_view3d(C);
|
||||
|
@@ -39,6 +39,7 @@
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_jitter.h"
|
||||
#include "BLI_threads.h"
|
||||
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
@@ -103,11 +104,17 @@ typedef struct OGLRender {
|
||||
bMovieHandle *mh;
|
||||
int cfrao, nfra;
|
||||
|
||||
size_t totvideos;
|
||||
|
||||
/* quick lookup */
|
||||
int view_id;
|
||||
|
||||
/* wm vars for timer and progress cursor */
|
||||
wmWindowManager *wm;
|
||||
wmWindow *win;
|
||||
|
||||
wmTimer *timer; /* use to check if running modal or not (invoke'd or exec'd)*/
|
||||
void **movie_ctx_arr;
|
||||
} OGLRender;
|
||||
|
||||
/* added because v3d is not always valid */
|
||||
@@ -121,16 +128,125 @@ static unsigned int screen_opengl_layers(OGLRender *oglrender)
|
||||
}
|
||||
}
|
||||
|
||||
static void screen_opengl_render_apply(OGLRender *oglrender)
|
||||
static bool screen_opengl_is_multiview(OGLRender *oglrender)
|
||||
{
|
||||
View3D *v3d = oglrender->v3d;
|
||||
RegionView3D *rv3d = oglrender->rv3d;
|
||||
RenderData *rd = &oglrender->scene->r;
|
||||
|
||||
if ((rd == NULL) || ((!oglrender->is_sequencer) && ((rv3d == NULL) || (v3d == NULL))))
|
||||
return false;
|
||||
|
||||
return (rd->scemode & R_MULTIVIEW) && ((oglrender->is_sequencer) || (rv3d->persp == RV3D_CAMOB && v3d->camera));
|
||||
}
|
||||
|
||||
static void screen_opengl_views_setup(OGLRender *oglrender)
|
||||
{
|
||||
RenderResult *rr;
|
||||
RenderView *rv;
|
||||
SceneRenderView *srv;
|
||||
bool is_multiview;
|
||||
View3D *v3d = oglrender->v3d;
|
||||
|
||||
RenderData *rd = &oglrender->scene->r;
|
||||
|
||||
rr = RE_AcquireResultWrite(oglrender->re);
|
||||
|
||||
is_multiview = screen_opengl_is_multiview(oglrender);
|
||||
|
||||
if (!is_multiview) {
|
||||
/* we only have one view when multiview is off */
|
||||
rv = rr->views.first;
|
||||
|
||||
if (rv == NULL) {
|
||||
rv = MEM_callocN(sizeof(RenderView), "new opengl render view");
|
||||
BLI_addtail(&rr->views, rv);
|
||||
}
|
||||
|
||||
while (rv->next) {
|
||||
RenderView *rv_del = rv->next;
|
||||
BLI_remlink(&rr->views, rv_del);
|
||||
|
||||
if (rv_del->rectf)
|
||||
MEM_freeN(rv_del->rectf);
|
||||
|
||||
if (rv_del->rectz)
|
||||
MEM_freeN(rv_del->rectz);
|
||||
|
||||
MEM_freeN(rv_del);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!oglrender->is_sequencer)
|
||||
RE_SetOverrideCamera(oglrender->re, V3D_CAMERA_SCENE(oglrender->scene, v3d));
|
||||
|
||||
/* remove all the views that are not needed */
|
||||
rv = rr->views.last;
|
||||
while (rv) {
|
||||
srv = BLI_findstring(&rd->views, rv->name, offsetof(SceneRenderView, name));
|
||||
if (BKE_scene_multiview_is_render_view_active(rd, srv)) {
|
||||
if (rv->rectf == NULL)
|
||||
rv->rectf = MEM_callocN(sizeof(float) * 4 * oglrender->sizex * oglrender->sizey, "screen_opengl_render_init rect");
|
||||
rv = rv->prev;
|
||||
}
|
||||
else {
|
||||
RenderView *rv_del = rv;
|
||||
rv = rv_del->prev;
|
||||
|
||||
BLI_remlink(&rr->views, rv_del);
|
||||
|
||||
if (rv_del->rectf)
|
||||
MEM_freeN(rv_del->rectf);
|
||||
|
||||
if (rv_del->rectz)
|
||||
MEM_freeN(rv_del->rectz);
|
||||
|
||||
MEM_freeN(rv_del);
|
||||
}
|
||||
}
|
||||
|
||||
/* create all the views that are needed */
|
||||
for (srv = rd->views.first; srv; srv = srv->next) {
|
||||
if (BKE_scene_multiview_is_render_view_active(rd, srv) == false)
|
||||
continue;
|
||||
|
||||
rv = BLI_findstring(&rr->views, srv->name, offsetof(SceneRenderView, name));
|
||||
|
||||
if (rv == NULL) {
|
||||
rv = MEM_callocN(sizeof(RenderView), "new opengl render view");
|
||||
BLI_strncpy(rv->name, srv->name, sizeof(rv->name));
|
||||
BLI_addtail(&rr->views, rv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (rv = rr->views.first; rv; rv = rv->next) {
|
||||
if (rv->rectf == NULL) {
|
||||
rv->rectf = MEM_callocN(sizeof(float) * 4 * oglrender->sizex * oglrender->sizey, "screen_opengl_render_init rect");
|
||||
}
|
||||
}
|
||||
|
||||
BLI_lock_thread(LOCK_DRAW_IMAGE);
|
||||
if (is_multiview && BKE_scene_multiview_is_stereo3d(rd)) {
|
||||
oglrender->ima->flag |= IMA_IS_STEREO;
|
||||
}
|
||||
else {
|
||||
oglrender->ima->flag &= ~IMA_IS_STEREO;
|
||||
oglrender->iuser.flag &= ~IMA_SHOW_STEREO;
|
||||
}
|
||||
BLI_unlock_thread(LOCK_DRAW_IMAGE);
|
||||
|
||||
RE_ReleaseResult(oglrender->re);
|
||||
}
|
||||
|
||||
static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr)
|
||||
{
|
||||
Scene *scene = oglrender->scene;
|
||||
ARegion *ar = oglrender->ar;
|
||||
View3D *v3d = oglrender->v3d;
|
||||
RegionView3D *rv3d = oglrender->rv3d;
|
||||
RenderResult *rr;
|
||||
Object *camera = NULL;
|
||||
ImBuf *ibuf;
|
||||
void *lock;
|
||||
float winmat[4][4];
|
||||
int sizex = oglrender->sizex;
|
||||
int sizey = oglrender->sizey;
|
||||
@@ -138,8 +254,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
|
||||
bool draw_bgpic = true;
|
||||
bool draw_sky = (scene->r.alphamode == R_ADDSKY);
|
||||
unsigned char *rect = NULL;
|
||||
|
||||
rr = RE_AcquireResultRead(oglrender->re);
|
||||
const char *viewname = RE_GetActiveRenderView(oglrender->re);
|
||||
|
||||
if (oglrender->is_sequencer) {
|
||||
SeqRenderData context;
|
||||
@@ -152,9 +267,11 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
|
||||
oglrender->sizex, oglrender->sizey, 100.0f,
|
||||
&context);
|
||||
|
||||
context.view_id = BKE_scene_multiview_view_id_get(&scene->r, viewname);
|
||||
ibuf = BKE_sequencer_give_ibuf(&context, CFRA, chanshown);
|
||||
|
||||
if (ibuf) {
|
||||
float *rectf;
|
||||
ImBuf *linear_ibuf;
|
||||
|
||||
BLI_assert((oglrender->sizex == ibuf->x) && (oglrender->sizey == ibuf->y));
|
||||
@@ -175,7 +292,8 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
|
||||
BKE_sequencer_imbuf_from_sequencer_space(scene, linear_ibuf);
|
||||
}
|
||||
|
||||
memcpy(rr->rectf, linear_ibuf->rect_float, sizeof(float) * 4 * oglrender->sizex * oglrender->sizey);
|
||||
rectf = RE_RenderViewGetRectf(rr, oglrender->view_id);
|
||||
memcpy(rectf, linear_ibuf->rect_float, sizeof(float) * 4 * oglrender->sizex * oglrender->sizey);
|
||||
|
||||
IMB_freeImBuf(linear_ibuf);
|
||||
}
|
||||
@@ -221,7 +339,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
|
||||
/* render 3d view */
|
||||
if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
|
||||
/*int is_ortho = scene->r.mode & R_ORTHO;*/
|
||||
camera = v3d->camera;
|
||||
camera = BKE_camera_multiview_render(oglrender->scene, v3d->camera, viewname);
|
||||
RE_GetCameraWindow(oglrender->re, camera, scene->r.cfra, winmat);
|
||||
if (camera->type == OB_CAMERA) {
|
||||
Camera *cam = camera->data;
|
||||
@@ -248,7 +366,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
|
||||
ED_view3d_draw_offscreen(
|
||||
scene, v3d, ar, sizex, sizey, NULL, winmat,
|
||||
draw_bgpic, draw_sky, is_persp,
|
||||
oglrender->ofs, oglrender->fx, &fx_settings);
|
||||
oglrender->ofs, oglrender->fx, &fx_settings, viewname);
|
||||
GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect);
|
||||
}
|
||||
else {
|
||||
@@ -264,7 +382,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
|
||||
ED_view3d_draw_offscreen(
|
||||
scene, v3d, ar, sizex, sizey, NULL, winmat,
|
||||
draw_bgpic, draw_sky, is_persp,
|
||||
oglrender->ofs, oglrender->fx, &fx_settings);
|
||||
oglrender->ofs, oglrender->fx, &fx_settings, viewname);
|
||||
GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect);
|
||||
|
||||
for (i = 0; i < sizex * sizey * 4; i++)
|
||||
@@ -280,7 +398,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
|
||||
ED_view3d_draw_offscreen(
|
||||
scene, v3d, ar, sizex, sizey, NULL, winmat_jitter,
|
||||
draw_bgpic, draw_sky, is_persp,
|
||||
oglrender->ofs, oglrender->fx, &fx_settings);
|
||||
oglrender->ofs, oglrender->fx, &fx_settings, viewname);
|
||||
GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect);
|
||||
|
||||
for (i = 0; i < sizex * sizey * 4; i++)
|
||||
@@ -300,7 +418,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
|
||||
char err_out[256] = "unknown";
|
||||
ImBuf *ibuf_view = ED_view3d_draw_offscreen_imbuf_simple(scene, scene->camera, oglrender->sizex, oglrender->sizey,
|
||||
IB_rect, OB_SOLID, false, true, true,
|
||||
(draw_sky) ? R_ADDSKY : R_ALPHAPREMUL, err_out);
|
||||
(draw_sky) ? R_ADDSKY : R_ALPHAPREMUL, viewname, err_out);
|
||||
camera = scene->camera;
|
||||
|
||||
if (ibuf_view) {
|
||||
@@ -325,6 +443,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
|
||||
|
||||
if (rect) {
|
||||
int profile_to;
|
||||
float *rectf = RE_RenderViewGetRectf(rr, oglrender->view_id);
|
||||
|
||||
if (BKE_scene_check_color_management_enabled(scene))
|
||||
profile_to = IB_PROFILE_LINEAR_RGB;
|
||||
@@ -333,47 +452,60 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
|
||||
|
||||
/* sequencer has got trickier conversion happened above
|
||||
* also assume opengl's space matches byte buffer color space */
|
||||
IMB_buffer_float_from_byte(rr->rectf, rect,
|
||||
IMB_buffer_float_from_byte(rectf, rect,
|
||||
profile_to, IB_PROFILE_SRGB, true,
|
||||
oglrender->sizex, oglrender->sizey, oglrender->sizex, oglrender->sizex);
|
||||
|
||||
/* rr->rectf is now filled with image data */
|
||||
|
||||
if ((scene->r.stamp & R_STAMP_ALL) && (scene->r.stamp & R_STAMP_DRAW))
|
||||
BKE_image_stamp_buf(scene, camera, rect, rectf, rr->rectx, rr->recty, 4);
|
||||
|
||||
MEM_freeN(rect);
|
||||
}
|
||||
}
|
||||
|
||||
/* rr->rectf is now filled with image data */
|
||||
static void screen_opengl_render_write(OGLRender *oglrender)
|
||||
{
|
||||
Scene *scene = oglrender->scene;
|
||||
RenderResult *rr;
|
||||
bool ok;
|
||||
char name[FILE_MAX];
|
||||
Object *camera = RE_GetCamera(oglrender->re);
|
||||
|
||||
if ((scene->r.stamp & R_STAMP_ALL) && (scene->r.stamp & R_STAMP_DRAW)) {
|
||||
BKE_image_stamp_buf(scene, camera, rect, rr->rectf, rr->rectx, rr->recty, 4);
|
||||
rr = RE_AcquireResultRead(oglrender->re);
|
||||
|
||||
BKE_image_path_from_imformat(
|
||||
name, scene->r.pic, oglrender->bmain->name, scene->r.cfra,
|
||||
&scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, false, NULL);
|
||||
|
||||
/* write images as individual images or stereo */
|
||||
ok = RE_WriteRenderViewsImage(oglrender->reports, rr, scene, camera, false, name);
|
||||
|
||||
RE_ReleaseResultImage(oglrender->re);
|
||||
|
||||
if (ok) printf("OpenGL Render written to '%s'\n", name);
|
||||
else printf("OpenGL Render failed to write '%s'\n", name);
|
||||
}
|
||||
|
||||
static void screen_opengl_render_apply(OGLRender *oglrender)
|
||||
{
|
||||
RenderResult *rr;
|
||||
RenderView *rv;
|
||||
int view_id;
|
||||
|
||||
rr = RE_AcquireResultRead(oglrender->re);
|
||||
for (rv = rr->views.first, view_id = 0; rv; rv = rv->next, view_id++) {
|
||||
RE_SetActiveRenderView(oglrender->re, rv->name);
|
||||
oglrender->view_id = view_id;
|
||||
screen_opengl_render_doit(oglrender, rr);
|
||||
}
|
||||
|
||||
RE_ReleaseResult(oglrender->re);
|
||||
|
||||
/* update byte from float buffer */
|
||||
ibuf = BKE_image_acquire_ibuf(oglrender->ima, &oglrender->iuser, &lock);
|
||||
|
||||
if (ibuf) {
|
||||
ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
|
||||
|
||||
/* write file for animation */
|
||||
if (oglrender->write_still) {
|
||||
char name[FILE_MAX];
|
||||
int ok;
|
||||
|
||||
if (scene->r.im_format.planes == R_IMF_CHAN_DEPTH_8) {
|
||||
IMB_color_to_bw(ibuf);
|
||||
}
|
||||
|
||||
BKE_image_path_from_imformat(
|
||||
name, scene->r.pic, oglrender->bmain->name, scene->r.cfra,
|
||||
&scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, false);
|
||||
ok = BKE_imbuf_write_as(ibuf, name, &scene->r.im_format, true); /* no need to stamp here */
|
||||
if (ok) printf("OpenGL Render written to '%s'\n", name);
|
||||
else printf("OpenGL Render failed to write '%s'\n", name);
|
||||
}
|
||||
if (oglrender->write_still) {
|
||||
screen_opengl_render_write(oglrender);
|
||||
}
|
||||
|
||||
BKE_image_release_ibuf(oglrender->ima, ibuf, lock);
|
||||
|
||||
if (rect)
|
||||
MEM_freeN(rect);
|
||||
}
|
||||
|
||||
static bool screen_opengl_render_init(bContext *C, wmOperator *op)
|
||||
@@ -385,7 +517,6 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
ScrArea *prevsa = CTX_wm_area(C);
|
||||
ARegion *prevar = CTX_wm_region(C);
|
||||
RenderResult *rr;
|
||||
GPUOffScreen *ofs;
|
||||
OGLRender *oglrender;
|
||||
int sizex, sizey;
|
||||
@@ -458,7 +589,6 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
|
||||
oglrender->sseq = CTX_wm_space_seq(C);
|
||||
}
|
||||
|
||||
|
||||
oglrender->prevsa = prevsa;
|
||||
oglrender->prevar = prevar;
|
||||
|
||||
@@ -492,15 +622,17 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
|
||||
/* create render result */
|
||||
RE_InitState(oglrender->re, NULL, &scene->r, NULL, sizex, sizey, NULL);
|
||||
|
||||
rr = RE_AcquireResultWrite(oglrender->re);
|
||||
if (rr->rectf == NULL)
|
||||
rr->rectf = MEM_callocN(sizeof(float) * 4 * sizex * sizey, "screen_opengl_render_init rect");
|
||||
RE_ReleaseResult(oglrender->re);
|
||||
/* create render views */
|
||||
screen_opengl_views_setup(oglrender);
|
||||
|
||||
/* wm vars */
|
||||
oglrender->wm = wm;
|
||||
oglrender->win = win;
|
||||
|
||||
oglrender->totvideos = 0;
|
||||
oglrender->mh = NULL;
|
||||
oglrender->movie_ctx_arr = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -508,10 +640,19 @@ static void screen_opengl_render_end(bContext *C, OGLRender *oglrender)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Scene *scene = oglrender->scene;
|
||||
size_t i;
|
||||
|
||||
if (oglrender->mh) {
|
||||
if (BKE_imtype_is_movie(scene->r.im_format.imtype))
|
||||
oglrender->mh->end_movie();
|
||||
if (BKE_imtype_is_movie(scene->r.im_format.imtype)) {
|
||||
for (i = 0; i < oglrender->totvideos; i++) {
|
||||
oglrender->mh->end_movie(oglrender->movie_ctx_arr[i]);
|
||||
oglrender->mh->context_free(oglrender->movie_ctx_arr[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (oglrender->movie_ctx_arr) {
|
||||
MEM_freeN(oglrender->movie_ctx_arr);
|
||||
}
|
||||
}
|
||||
|
||||
if (oglrender->timer) { /* exec will not have a timer */
|
||||
@@ -552,13 +693,27 @@ static int screen_opengl_render_anim_initialize(bContext *C, wmOperator *op)
|
||||
|
||||
oglrender = op->customdata;
|
||||
scene = oglrender->scene;
|
||||
oglrender->totvideos = BKE_scene_multiview_num_videos_get(&scene->r);
|
||||
|
||||
oglrender->reports = op->reports;
|
||||
oglrender->mh = BKE_movie_handle_get(scene->r.im_format.imtype);
|
||||
|
||||
if (BKE_imtype_is_movie(scene->r.im_format.imtype)) {
|
||||
if (!oglrender->mh->start_movie(scene, &scene->r, oglrender->sizex, oglrender->sizey, oglrender->reports, PRVRANGEON != 0)) {
|
||||
screen_opengl_render_end(C, oglrender);
|
||||
return 0;
|
||||
size_t i, width, height;
|
||||
|
||||
BKE_scene_multiview_videos_dimensions_get(&scene->r, oglrender->sizex, oglrender->sizey, &width, &height);
|
||||
oglrender->movie_ctx_arr = MEM_mallocN(sizeof(void *) * oglrender->totvideos, "Movies");
|
||||
oglrender->mh = BKE_movie_handle_get(scene->r.im_format.imtype);
|
||||
|
||||
for (i = 0; i < oglrender->totvideos; i++) {
|
||||
const char *suffix = BKE_scene_multiview_view_id_suffix_get(&scene->r, i);
|
||||
|
||||
oglrender->movie_ctx_arr[i] = oglrender->mh->context_create();
|
||||
if (!oglrender->mh->start_movie(oglrender->movie_ctx_arr[i], scene, &scene->r, oglrender->sizex,
|
||||
oglrender->sizey, oglrender->reports, PRVRANGEON != 0, suffix))
|
||||
{
|
||||
screen_opengl_render_end(C, oglrender);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -568,18 +723,17 @@ static int screen_opengl_render_anim_initialize(bContext *C, wmOperator *op)
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
OGLRender *oglrender = op->customdata;
|
||||
Scene *scene = oglrender->scene;
|
||||
ImBuf *ibuf, *ibuf_save = NULL;
|
||||
void *lock;
|
||||
char name[FILE_MAX];
|
||||
bool ok = false;
|
||||
const bool view_context = (oglrender->v3d != NULL);
|
||||
Object *camera = NULL;
|
||||
bool is_movie;
|
||||
RenderResult *rr;
|
||||
|
||||
/* go to next frame */
|
||||
if (CFRA < oglrender->nfra)
|
||||
@@ -599,7 +753,7 @@ static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op)
|
||||
if (!is_movie) {
|
||||
BKE_image_path_from_imformat(
|
||||
name, scene->r.pic, oglrender->bmain->name, scene->r.cfra,
|
||||
&scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, true);
|
||||
&scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, true, NULL);
|
||||
|
||||
if ((scene->r.mode & R_NO_OVERWRITE) && BLI_exists(name)) {
|
||||
BKE_reportf(op->reports, RPT_INFO, "Skipping existing frame \"%s\"", name);
|
||||
@@ -619,89 +773,40 @@ static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op)
|
||||
if (BKE_scene_camera_switch_update(scene)) {
|
||||
oglrender->v3d->camera = scene->camera;
|
||||
}
|
||||
|
||||
camera = oglrender->v3d->camera;
|
||||
}
|
||||
}
|
||||
else {
|
||||
BKE_scene_camera_switch_update(scene);
|
||||
|
||||
camera = scene->camera;
|
||||
}
|
||||
|
||||
/* render into offscreen buffer */
|
||||
screen_opengl_render_apply(oglrender);
|
||||
|
||||
/* save to disk */
|
||||
ibuf = BKE_image_acquire_ibuf(oglrender->ima, &oglrender->iuser, &lock);
|
||||
rr = RE_AcquireResultRead(oglrender->re);
|
||||
|
||||
if (ibuf) {
|
||||
bool needs_free = false;
|
||||
|
||||
ibuf_save = ibuf;
|
||||
|
||||
if (is_movie || !BKE_imtype_requires_linear_float(scene->r.im_format.imtype)) {
|
||||
ibuf_save = IMB_colormanagement_imbuf_for_write(ibuf, true, true, &scene->view_settings,
|
||||
&scene->display_settings, &scene->r.im_format);
|
||||
|
||||
needs_free = true;
|
||||
if (is_movie) {
|
||||
ok = RE_WriteRenderViewsMovie(oglrender->reports, rr, scene, &scene->r, oglrender->mh, oglrender->sizex,
|
||||
oglrender->sizey, oglrender->movie_ctx_arr, oglrender->totvideos);
|
||||
if (ok) {
|
||||
printf("Append frame %d", scene->r.cfra);
|
||||
BKE_reportf(op->reports, RPT_INFO, "Appended frame: %d", scene->r.cfra);
|
||||
}
|
||||
|
||||
/* color -> grayscale */
|
||||
/* editing directly would alter the render view */
|
||||
if (scene->r.im_format.planes == R_IMF_PLANES_BW) {
|
||||
ImBuf *ibuf_bw = IMB_dupImBuf(ibuf_save);
|
||||
IMB_color_to_bw(ibuf_bw);
|
||||
|
||||
if (needs_free)
|
||||
IMB_freeImBuf(ibuf_save);
|
||||
|
||||
ibuf_save = ibuf_bw;
|
||||
}
|
||||
else {
|
||||
ok = RE_WriteRenderViewsImage(op->reports, rr, scene, scene->camera, true, name);
|
||||
if (ok) {
|
||||
printf("Saved: %s", name);
|
||||
BKE_reportf(op->reports, RPT_INFO, "Saved file: %s", name);
|
||||
}
|
||||
else {
|
||||
/* this is lightweight & doesnt re-alloc the buffers, only do this
|
||||
* to save the correct bit depth since the image is always RGBA */
|
||||
ImBuf *ibuf_cpy = IMB_allocImBuf(ibuf_save->x, ibuf_save->y, scene->r.im_format.planes, 0);
|
||||
|
||||
ibuf_cpy->rect = ibuf_save->rect;
|
||||
ibuf_cpy->rect_float = ibuf_save->rect_float;
|
||||
ibuf_cpy->zbuf_float = ibuf_save->zbuf_float;
|
||||
|
||||
if (needs_free) {
|
||||
ibuf_cpy->mall = ibuf_save->mall;
|
||||
ibuf_save->mall = 0;
|
||||
IMB_freeImBuf(ibuf_save);
|
||||
}
|
||||
|
||||
ibuf_save = ibuf_cpy;
|
||||
printf("Write error: cannot save %s\n", name);
|
||||
BKE_reportf(op->reports, RPT_ERROR, "Write error: cannot save %s", name);
|
||||
}
|
||||
|
||||
if (is_movie) {
|
||||
ok = oglrender->mh->append_movie(&scene->r, PSFRA, CFRA, (int *)ibuf_save->rect,
|
||||
oglrender->sizex, oglrender->sizey, oglrender->reports);
|
||||
if (ok) {
|
||||
printf("Append frame %d", scene->r.cfra);
|
||||
BKE_reportf(op->reports, RPT_INFO, "Appended frame: %d", scene->r.cfra);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ok = BKE_imbuf_write_stamp(scene, camera, ibuf_save, name, &scene->r.im_format);
|
||||
|
||||
if (ok == 0) {
|
||||
printf("Write error: cannot save %s\n", name);
|
||||
BKE_reportf(op->reports, RPT_ERROR, "Write error: cannot save %s", name);
|
||||
}
|
||||
else {
|
||||
printf("Saved: %s", name);
|
||||
BKE_reportf(op->reports, RPT_INFO, "Saved file: %s", name);
|
||||
}
|
||||
}
|
||||
|
||||
if (needs_free)
|
||||
IMB_freeImBuf(ibuf_save);
|
||||
}
|
||||
|
||||
BKE_image_release_ibuf(oglrender->ima, ibuf, lock);
|
||||
RE_ReleaseResult(oglrender->re);
|
||||
|
||||
|
||||
/* movie stats prints have no line break */
|
||||
printf("\n");
|
||||
|
@@ -58,6 +58,9 @@ void ED_operatortypes_render(void)
|
||||
WM_operatortype_append(SCENE_OT_render_layer_add);
|
||||
WM_operatortype_append(SCENE_OT_render_layer_remove);
|
||||
|
||||
WM_operatortype_append(SCENE_OT_render_view_add);
|
||||
WM_operatortype_append(SCENE_OT_render_view_remove);
|
||||
|
||||
#ifdef WITH_FREESTYLE
|
||||
WM_operatortype_append(SCENE_OT_freestyle_module_add);
|
||||
WM_operatortype_append(SCENE_OT_freestyle_module_remove);
|
||||
|
@@ -548,7 +548,9 @@ static bool ed_preview_draw_rect(ScrArea *sa, int split, int first, rcti *rect,
|
||||
|
||||
/* test if something rendered ok */
|
||||
re = RE_GetRender(name);
|
||||
RE_AcquireResultImage(re, &rres);
|
||||
|
||||
/* material preview only needs monoscopy (view 0) */
|
||||
RE_AcquireResultImage(re, &rres, 0);
|
||||
|
||||
if (rres.rectf) {
|
||||
|
||||
@@ -561,9 +563,11 @@ static bool ed_preview_draw_rect(ScrArea *sa, int split, int first, rcti *rect,
|
||||
unsigned char *rect_byte = MEM_mallocN(rres.rectx * rres.recty * sizeof(int), "ed_preview_draw_rect");
|
||||
float fx = rect->xmin + offx;
|
||||
float fy = rect->ymin;
|
||||
|
||||
/* material preview only needs monoscopy (view 0) */
|
||||
if (re)
|
||||
RE_AcquiredResultGet32(re, &rres, (unsigned int *)rect_byte);
|
||||
|
||||
RE_AcquiredResultGet32(re, &rres, (unsigned int *)rect_byte, 0);
|
||||
|
||||
glaDrawPixelsSafe(fx, fy, rres.rectx, rres.recty, rres.rectx, GL_RGBA, GL_UNSIGNED_BYTE, rect_byte);
|
||||
|
||||
MEM_freeN(rect_byte);
|
||||
|
@@ -605,6 +605,70 @@ void SCENE_OT_render_layer_remove(wmOperatorType *ot)
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
|
||||
}
|
||||
|
||||
/********************** render view operators *********************/
|
||||
|
||||
static int render_view_remove_poll(bContext *C)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
|
||||
/* don't allow user to remove "left" and "right" views */
|
||||
return scene->r.actview > 1;
|
||||
}
|
||||
|
||||
static int render_view_add_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
|
||||
BKE_scene_add_render_view(scene, NULL);
|
||||
scene->r.actview = BLI_listbase_count(&scene->r.views) - 1;
|
||||
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void SCENE_OT_render_view_add(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Add Render View";
|
||||
ot->idname = "SCENE_OT_render_view_add";
|
||||
ot->description = "Add a render view";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec = render_view_add_exec;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
static int render_view_remove_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
SceneRenderView *rv = BLI_findlink(&scene->r.views, scene->r.actview);
|
||||
|
||||
if (!BKE_scene_remove_render_view(scene, rv))
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void SCENE_OT_render_view_remove(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Remove Render View";
|
||||
ot->idname = "SCENE_OT_render_view_remove";
|
||||
ot->description = "Remove the selected render view";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec = render_view_remove_exec;
|
||||
ot->poll = render_view_remove_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
#ifdef WITH_FREESTYLE
|
||||
|
||||
static bool freestyle_linestyle_check_report(FreestyleLineSet *lineset, ReportList *reports)
|
||||
|
@@ -493,7 +493,6 @@ void ED_region_do_draw(bContext *C, ARegion *ar)
|
||||
glDisable(GL_BLEND);
|
||||
#endif
|
||||
|
||||
ar->do_draw = 0;
|
||||
memset(&ar->drawrct, 0, sizeof(ar->drawrct));
|
||||
|
||||
UI_blocklist_free_inactive(C, &ar->uiblocks);
|
||||
|
@@ -59,6 +59,7 @@
|
||||
#include "ED_screen.h"
|
||||
#include "ED_screen_types.h"
|
||||
#include "ED_clip.h"
|
||||
#include "ED_node.h"
|
||||
#include "ED_render.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
@@ -2122,4 +2123,85 @@ void ED_update_for_newframe(Main *bmain, Scene *scene, int UNUSED(mute))
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* return true if any active area requires to see in 3D
|
||||
*/
|
||||
bool ED_screen_stereo3d_required(bScreen *screen)
|
||||
{
|
||||
ScrArea *sa;
|
||||
Scene *sce = screen->scene;
|
||||
const bool is_multiview = (sce->r.scemode & R_MULTIVIEW) != 0;
|
||||
|
||||
for (sa = screen->areabase.first; sa; sa = sa->next) {
|
||||
switch (sa->spacetype) {
|
||||
case SPACE_VIEW3D:
|
||||
{
|
||||
View3D *v3d;
|
||||
|
||||
if (!is_multiview)
|
||||
continue;
|
||||
|
||||
v3d = sa->spacedata.first;
|
||||
if (v3d->camera && v3d->stereo3d_camera == STEREO_3D_ID) {
|
||||
ARegion *ar;
|
||||
for (ar = sa->regionbase.first; ar; ar = ar->next) {
|
||||
if (ar->regiondata && ar->regiontype == RGN_TYPE_WINDOW) {
|
||||
RegionView3D *rv3d = ar->regiondata;
|
||||
if (rv3d->persp == RV3D_CAMOB) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SPACE_IMAGE:
|
||||
{
|
||||
SpaceImage *sima;
|
||||
|
||||
/* images should always show in stereo, even if
|
||||
* the file doesn't have views enabled */
|
||||
sima = sa->spacedata.first;
|
||||
if (sima->image && (sima->image->flag & IMA_IS_STEREO) &&
|
||||
(sima->iuser.flag & IMA_SHOW_STEREO))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SPACE_NODE:
|
||||
{
|
||||
SpaceNode *snode;
|
||||
|
||||
if (!is_multiview)
|
||||
continue;
|
||||
|
||||
snode = sa->spacedata.first;
|
||||
if ((snode->flag & SNODE_BACKDRAW) && ED_node_is_compositor(snode)) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SPACE_SEQ:
|
||||
{
|
||||
SpaceSeq *sseq;
|
||||
|
||||
if (!is_multiview)
|
||||
continue;
|
||||
|
||||
sseq = sa->spacedata.first;
|
||||
if (ELEM(sseq->view, SEQ_VIEW_PREVIEW, SEQ_VIEW_SEQUENCE_PREVIEW)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (sseq->draw_flag & SEQ_DRAW_BACKDROP) {
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@@ -990,6 +990,7 @@ static int area_dupli_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
rect.ymax = rect.ymin + BLI_rcti_size_y(&rect) / U.pixelsize;
|
||||
|
||||
newwin = WM_window_open(C, &rect);
|
||||
*newwin->stereo3d_format = *win->stereo3d_format;
|
||||
|
||||
/* allocs new screen and adds to newly created window, using window size */
|
||||
newsc = ED_screen_add(newwin, CTX_data_scene(C), sc->id.name + 2);
|
||||
|
@@ -303,6 +303,7 @@ typedef struct ScreenshotJob {
|
||||
const short *stop;
|
||||
const short *do_update;
|
||||
ReportList reports;
|
||||
void *movie_ctx;
|
||||
} ScreenshotJob;
|
||||
|
||||
|
||||
@@ -312,7 +313,10 @@ static void screenshot_freejob(void *sjv)
|
||||
|
||||
if (sj->dumprect)
|
||||
MEM_freeN(sj->dumprect);
|
||||
|
||||
|
||||
if (sj->movie_ctx)
|
||||
MEM_freeN(sj->movie_ctx);
|
||||
|
||||
MEM_freeN(sj);
|
||||
}
|
||||
|
||||
@@ -337,20 +341,21 @@ static void screenshot_startjob(void *sjv, short *stop, short *do_update, float
|
||||
{
|
||||
ScreenshotJob *sj = sjv;
|
||||
RenderData rd = sj->scene->r;
|
||||
bMovieHandle *mh = BKE_movie_handle_get(sj->scene->r.im_format.imtype);
|
||||
|
||||
bMovieHandle *mh = NULL;
|
||||
|
||||
/* we need this as local variables for renderdata */
|
||||
rd.frs_sec = U.scrcastfps;
|
||||
rd.frs_sec_base = 1.0f;
|
||||
|
||||
if (BKE_imtype_is_movie(rd.im_format.imtype)) {
|
||||
if (!mh->start_movie(sj->scene, &rd, sj->dumpsx, sj->dumpsy, &sj->reports, false)) {
|
||||
mh = BKE_movie_handle_get(sj->scene->r.im_format.imtype);
|
||||
sj->movie_ctx = mh->context_create();
|
||||
|
||||
if (!mh->start_movie(sj->movie_ctx, sj->scene, &rd, sj->dumpsx, sj->dumpsy, &sj->reports, false, "")) {
|
||||
printf("screencast job stopped\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
mh = NULL;
|
||||
|
||||
sj->stop = stop;
|
||||
sj->do_update = do_update;
|
||||
@@ -362,8 +367,8 @@ static void screenshot_startjob(void *sjv, short *stop, short *do_update, float
|
||||
if (sj->dumprect) {
|
||||
|
||||
if (mh) {
|
||||
if (mh->append_movie(&rd, rd.sfra, rd.cfra, (int *)sj->dumprect,
|
||||
sj->dumpsx, sj->dumpsy, &sj->reports))
|
||||
if (mh->append_movie(sj->movie_ctx, &rd, rd.sfra, rd.cfra, (int *)sj->dumprect,
|
||||
sj->dumpsx, sj->dumpsy, "", &sj->reports))
|
||||
{
|
||||
BKE_reportf(&sj->reports, RPT_INFO, "Appended frame: %d", rd.cfra);
|
||||
printf("Appended frame %d\n", rd.cfra);
|
||||
@@ -379,7 +384,7 @@ static void screenshot_startjob(void *sjv, short *stop, short *do_update, float
|
||||
|
||||
BKE_image_path_from_imformat(
|
||||
name, rd.pic, sj->bmain->name, rd.cfra,
|
||||
&rd.im_format, (rd.scemode & R_EXTENSION) != 0, true);
|
||||
&rd.im_format, (rd.scemode & R_EXTENSION) != 0, true, NULL);
|
||||
|
||||
ibuf->rect = sj->dumprect;
|
||||
ok = BKE_imbuf_write(ibuf, name, &rd.im_format);
|
||||
@@ -410,8 +415,10 @@ static void screenshot_startjob(void *sjv, short *stop, short *do_update, float
|
||||
PIL_sleep_ms(U.scrcastwait);
|
||||
}
|
||||
|
||||
if (mh)
|
||||
mh->end_movie();
|
||||
if (mh) {
|
||||
mh->end_movie(sj->movie_ctx);
|
||||
mh->context_free(sj->movie_ctx);
|
||||
}
|
||||
|
||||
BKE_report(&sj->reports, RPT_INFO, "Screencast job stopped");
|
||||
}
|
||||
|
@@ -499,7 +499,7 @@ void imapaint_image_update(SpaceImage *sima, Image *image, ImBuf *ibuf, short te
|
||||
int w = imapaintpartial.x2 - imapaintpartial.x1;
|
||||
int h = imapaintpartial.y2 - imapaintpartial.y1;
|
||||
/* Testing with partial update in uv editor too */
|
||||
GPU_paint_update_image(image, imapaintpartial.x1, imapaintpartial.y1, w, h); //!texpaint);
|
||||
GPU_paint_update_image(image, (sima ? &sima->iuser : NULL), imapaintpartial.x1, imapaintpartial.y1, w, h); //!texpaint);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1109,7 +1109,7 @@ static int paint_2d_canvas_set(ImagePaintState *s, Image *ima)
|
||||
if (ima == NULL) {
|
||||
return 0;
|
||||
}
|
||||
else if (ima->packedfile && ima->rr) {
|
||||
else if (BKE_image_has_packedfile(ima) && ima->rr) {
|
||||
s->warnpackedfile = ima->id.name + 2;
|
||||
return 0;
|
||||
}
|
||||
|
@@ -5233,7 +5233,7 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op)
|
||||
if (w > maxsize) w = maxsize;
|
||||
if (h > maxsize) h = maxsize;
|
||||
|
||||
ibuf = ED_view3d_draw_offscreen_imbuf(scene, CTX_wm_view3d(C), CTX_wm_region(C), w, h, IB_rect, false, R_ALPHAPREMUL, err_out);
|
||||
ibuf = ED_view3d_draw_offscreen_imbuf(scene, CTX_wm_view3d(C), CTX_wm_region(C), w, h, IB_rect, false, R_ALPHAPREMUL, NULL, err_out);
|
||||
if (!ibuf) {
|
||||
/* Mostly happens when OpenGL offscreen buffer was failed to create, */
|
||||
/* but could be other reasons. Should be handled in the future. nazgul */
|
||||
@@ -5444,7 +5444,7 @@ static Image *proj_paint_image_create(wmOperator *op, Main *bmain)
|
||||
RNA_string_get(op->ptr, "name", imagename);
|
||||
}
|
||||
ima = BKE_image_add_generated(bmain, width, height, imagename, alpha ? 32 : 24, use_float,
|
||||
gen_type, color);
|
||||
gen_type, color, false);
|
||||
|
||||
return ima;
|
||||
}
|
||||
|
@@ -44,6 +44,7 @@
|
||||
#include "BKE_image.h"
|
||||
#include "BKE_node.h"
|
||||
#include "BKE_screen.h"
|
||||
#include "BKE_scene.h"
|
||||
|
||||
#include "RE_pipeline.h"
|
||||
|
||||
@@ -82,9 +83,9 @@ static void image_info(Scene *scene, ImageUser *iuser, Image *ima, ImBuf *ibuf,
|
||||
else {
|
||||
if (ima->source == IMA_SRC_MOVIE) {
|
||||
ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Movie"), len - ofs);
|
||||
if (ima->anim)
|
||||
if (BKE_image_has_anim(ima))
|
||||
ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_(" %d frs"),
|
||||
IMB_anim_get_duration(ima->anim, IMB_TC_RECORD_RUN));
|
||||
IMB_anim_get_duration(((ImageAnim *)ima->anims.first)->anim, IMB_TC_RECORD_RUN));
|
||||
}
|
||||
else {
|
||||
ofs += BLI_strncpy_rlen(str, IFACE_("Image"), len - ofs);
|
||||
@@ -311,10 +312,10 @@ static void ui_imageuser_slot_menu(bContext *UNUSED(C), uiLayout *layout, void *
|
||||
|
||||
static const char *ui_imageuser_layer_fake_name(RenderResult *rr)
|
||||
{
|
||||
if (rr->rectf) {
|
||||
if (RE_RenderViewGetRectf(rr, 0)) {
|
||||
return IFACE_("Composite");
|
||||
}
|
||||
else if (rr->rect32) {
|
||||
else if (RE_RenderViewGetRect32(rr, 0)) {
|
||||
return IFACE_("Sequence");
|
||||
}
|
||||
else {
|
||||
@@ -375,7 +376,7 @@ final:
|
||||
|
||||
static const char *ui_imageuser_pass_fake_name(RenderLayer *rl)
|
||||
{
|
||||
if (rl == NULL || rl->rectf) {
|
||||
if (rl == NULL) {
|
||||
return IFACE_("Combined");
|
||||
}
|
||||
else {
|
||||
@@ -383,9 +384,9 @@ static const char *ui_imageuser_pass_fake_name(RenderLayer *rl)
|
||||
}
|
||||
}
|
||||
|
||||
static void ui_imageuser_pass_menu(bContext *UNUSED(C), uiLayout *layout, void *ptrpair_p)
|
||||
static void ui_imageuser_pass_menu(bContext *UNUSED(C), uiLayout *layout, void *rnd_pt)
|
||||
{
|
||||
void **rnd_data = ptrpair_p;
|
||||
void **rnd_data = rnd_pt;
|
||||
uiBlock *block = uiLayoutGetBlock(layout);
|
||||
Image *image = rnd_data[0];
|
||||
ImageUser *iuser = rnd_data[1];
|
||||
@@ -398,6 +399,7 @@ static void ui_imageuser_pass_menu(bContext *UNUSED(C), uiLayout *layout, void *
|
||||
RenderPass *rpass;
|
||||
const char *fake_name;
|
||||
int nr;
|
||||
int passflag = 0;
|
||||
|
||||
/* may have been freed since drawing */
|
||||
rr = BKE_image_acquire_renderresult(scene, image);
|
||||
@@ -419,15 +421,22 @@ static void ui_imageuser_pass_menu(bContext *UNUSED(C), uiLayout *layout, void *
|
||||
fake_name = ui_imageuser_pass_fake_name(rl);
|
||||
|
||||
if (fake_name) {
|
||||
BLI_strncpy(rpass_fake.name, fake_name, sizeof(rpass_fake.name));
|
||||
BLI_strncpy(rpass_fake.internal_name, fake_name, sizeof(rpass_fake.internal_name));
|
||||
nr += 1;
|
||||
}
|
||||
|
||||
/* rendered results don't have a Combined pass */
|
||||
for (rpass = rl ? rl->passes.last : NULL; rpass; rpass = rpass->prev, nr--) {
|
||||
|
||||
/* just show one pass of each kind */
|
||||
if (passflag & rpass->passtype)
|
||||
continue;
|
||||
|
||||
passflag |= rpass->passtype;
|
||||
|
||||
final:
|
||||
uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, IFACE_(rpass->name), 0, 0,
|
||||
UI_UNIT_X * 5, UI_UNIT_X, &iuser->pass, (float) nr, 0.0, 0, -1, "");
|
||||
uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, IFACE_(rpass->internal_name), 0, 0,
|
||||
UI_UNIT_X * 5, UI_UNIT_X, &iuser->passtype, (float) rpass->passtype, 0.0, 0, -1, "");
|
||||
}
|
||||
|
||||
if (fake_name) {
|
||||
@@ -441,21 +450,81 @@ final:
|
||||
BKE_image_release_renderresult(scene, image);
|
||||
}
|
||||
|
||||
/**************************** view menus *****************************/
|
||||
static void ui_imageuser_view_menu_rr(bContext *UNUSED(C), uiLayout *layout, void *rnd_pt)
|
||||
{
|
||||
void **rnd_data = rnd_pt;
|
||||
uiBlock *block = uiLayoutGetBlock(layout);
|
||||
Image *image = rnd_data[0];
|
||||
ImageUser *iuser = rnd_data[1];
|
||||
RenderResult *rr;
|
||||
RenderView *rview;
|
||||
int nr;
|
||||
Scene *scene = iuser->scene;
|
||||
|
||||
/* may have been freed since drawing */
|
||||
rr = BKE_image_acquire_renderresult(scene, image);
|
||||
if (UNLIKELY(rr == NULL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
UI_block_layout_set_current(block, layout);
|
||||
uiLayoutColumn(layout, false);
|
||||
|
||||
uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("View"),
|
||||
0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
uiItemS(layout);
|
||||
|
||||
nr = (rr ? BLI_listbase_count(&rr->views) : 0) - 1;
|
||||
for (rview = rr ? rr->views.last : NULL; rview; rview = rview->prev, nr--) {
|
||||
uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, IFACE_(rview->name), 0, 0,
|
||||
UI_UNIT_X * 5, UI_UNIT_X, &iuser->view, (float) nr, 0.0, 0, -1, "");
|
||||
}
|
||||
|
||||
BKE_image_release_renderresult(scene, image);
|
||||
}
|
||||
|
||||
static void ui_imageuser_view_menu_multiview(bContext *UNUSED(C), uiLayout *layout, void *rnd_pt)
|
||||
{
|
||||
void **rnd_data = rnd_pt;
|
||||
uiBlock *block = uiLayoutGetBlock(layout);
|
||||
Image *image = rnd_data[0];
|
||||
ImageUser *iuser = rnd_data[1];
|
||||
int nr;
|
||||
ImageView *iv;
|
||||
|
||||
UI_block_layout_set_current(block, layout);
|
||||
uiLayoutColumn(layout, false);
|
||||
|
||||
uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("View"),
|
||||
0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
uiItemS(layout);
|
||||
|
||||
nr = BLI_listbase_count(&image->views) - 1;
|
||||
for (iv = image->views.last; iv; iv = iv->prev, nr--) {
|
||||
uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, IFACE_(iv->name), 0, 0,
|
||||
UI_UNIT_X * 5, UI_UNIT_X, &iuser->view, (float) nr, 0.0, 0, -1, "");
|
||||
}
|
||||
}
|
||||
|
||||
/* 5 layer button callbacks... */
|
||||
static void image_multi_cb(bContext *C, void *rr_v, void *iuser_v)
|
||||
{
|
||||
ImageUser *iuser = iuser_v;
|
||||
|
||||
BKE_image_multilayer_index(rr_v, iuser);
|
||||
BKE_image_multilayer_index(rr_v, iuser);
|
||||
WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
|
||||
}
|
||||
|
||||
static void image_multi_inclay_cb(bContext *C, void *rr_v, void *iuser_v)
|
||||
{
|
||||
RenderResult *rr = rr_v;
|
||||
ImageUser *iuser = iuser_v;
|
||||
int tot = BLI_listbase_count(&rr->layers);
|
||||
|
||||
if (rr->rectf || rr->rect32)
|
||||
if (RE_HasFakeLayer(rr))
|
||||
tot++; /* fake compo/sequencer layer */
|
||||
|
||||
if (iuser->layer < tot - 1) {
|
||||
@@ -483,7 +552,7 @@ static void image_multi_incpass_cb(bContext *C, void *rr_v, void *iuser_v)
|
||||
if (rl) {
|
||||
int tot = BLI_listbase_count(&rl->passes);
|
||||
|
||||
if (rr->rectf || rr->rect32)
|
||||
if (RE_HasFakeLayer(rr))
|
||||
tot++; /* fake compo/sequencer layer */
|
||||
|
||||
if (iuser->pass < tot - 1) {
|
||||
@@ -504,6 +573,16 @@ static void image_multi_decpass_cb(bContext *C, void *rr_v, void *iuser_v)
|
||||
}
|
||||
}
|
||||
|
||||
/* 5 view button callbacks... */
|
||||
static void image_multiview_cb(bContext *C, void *ima_v, void *iuser_v)
|
||||
{
|
||||
Image *ima = ima_v;
|
||||
ImageUser *iuser = iuser_v;
|
||||
|
||||
BKE_image_multiview_index(ima, iuser);
|
||||
WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void image_freecache_cb(bContext *C, void *ima_v, void *unused)
|
||||
{
|
||||
@@ -523,13 +602,14 @@ static void image_user_change(bContext *C, void *iuser_v, void *unused)
|
||||
|
||||
static void uiblock_layer_pass_buttons(uiLayout *layout, Image *image, RenderResult *rr, ImageUser *iuser, int w, short *render_slot)
|
||||
{
|
||||
static void *rnd_pt[3]; /* XXX, workaround */
|
||||
static void *rnd_pt[4]; /* XXX, workaround */
|
||||
uiBlock *block = uiLayoutGetBlock(layout);
|
||||
uiBut *but;
|
||||
RenderLayer *rl = NULL;
|
||||
int wmenu1, wmenu2, wmenu3;
|
||||
int wmenu1, wmenu2, wmenu3, wmenu4;
|
||||
const char *fake_name;
|
||||
const char *display_name;
|
||||
const char *display_name = "";
|
||||
const bool show_stereo = (iuser->flag & IMA_SHOW_STEREO);
|
||||
|
||||
uiLayoutRow(layout, true);
|
||||
|
||||
@@ -537,6 +617,7 @@ static void uiblock_layer_pass_buttons(uiLayout *layout, Image *image, RenderRes
|
||||
wmenu1 = (2 * w) / 5;
|
||||
wmenu2 = (3 * w) / 5;
|
||||
wmenu3 = (3 * w) / 6;
|
||||
wmenu4 = (3 * w) / 6;
|
||||
|
||||
rnd_pt[0] = image;
|
||||
rnd_pt[1] = iuser;
|
||||
@@ -558,6 +639,7 @@ static void uiblock_layer_pass_buttons(uiLayout *layout, Image *image, RenderRes
|
||||
|
||||
if (rr) {
|
||||
RenderPass *rpass;
|
||||
RenderView *rview;
|
||||
int rpass_index;
|
||||
|
||||
/* layer */
|
||||
@@ -566,20 +648,50 @@ static void uiblock_layer_pass_buttons(uiLayout *layout, Image *image, RenderRes
|
||||
rl = BLI_findlink(&rr->layers, rpass_index);
|
||||
rnd_pt[2] = SET_INT_IN_POINTER(rpass_index);
|
||||
|
||||
display_name = rl ? rl->name : (fake_name ? fake_name : "");
|
||||
but = uiDefMenuBut(block, ui_imageuser_layer_menu, rnd_pt, display_name, 0, 0, wmenu2, UI_UNIT_Y, TIP_("Select Layer"));
|
||||
UI_but_func_set(but, image_multi_cb, rr, iuser);
|
||||
UI_but_type_set_menu_from_pulldown(but);
|
||||
|
||||
if (RE_layers_have_name(rr)) {
|
||||
display_name = rl ? rl->name : (fake_name ? fake_name : "");
|
||||
but = uiDefMenuBut(block, ui_imageuser_layer_menu, rnd_pt, display_name, 0, 0, wmenu2, UI_UNIT_Y, TIP_("Select Layer"));
|
||||
UI_but_func_set(but, image_multi_cb, rr, iuser);
|
||||
UI_but_type_set_menu_from_pulldown(but);
|
||||
}
|
||||
|
||||
/* pass */
|
||||
fake_name = ui_imageuser_pass_fake_name(rl);
|
||||
rpass = (rl ? BLI_findlink(&rl->passes, iuser->pass - (fake_name ? 1 : 0)) : NULL);
|
||||
|
||||
display_name = rpass ? rpass->name : (fake_name ? fake_name : "");
|
||||
display_name = rpass ? rpass->internal_name : (fake_name ? fake_name : "");
|
||||
but = uiDefMenuBut(block, ui_imageuser_pass_menu, rnd_pt, display_name, 0, 0, wmenu3, UI_UNIT_Y, TIP_("Select Pass"));
|
||||
UI_but_func_set(but, image_multi_cb, rr, iuser);
|
||||
UI_but_type_set_menu_from_pulldown(but);
|
||||
|
||||
/* view */
|
||||
if (BLI_listbase_count_ex(&rr->views, 2) > 1 && !show_stereo) {
|
||||
rview = BLI_findlink(&rr->views, iuser->view);
|
||||
display_name = rview ? rview->name : "";
|
||||
|
||||
but = uiDefMenuBut(block, ui_imageuser_view_menu_rr, rnd_pt, display_name, 0, 0, wmenu4, UI_UNIT_Y, TIP_("Select View"));
|
||||
UI_but_func_set(but, image_multi_cb, rr, iuser);
|
||||
UI_but_type_set_menu_from_pulldown(but);
|
||||
}
|
||||
}
|
||||
|
||||
/* stereo image */
|
||||
else if (((image->flag & IMA_IS_STEREO) && (!show_stereo)) ||
|
||||
((image->flag & IMA_IS_MULTIVIEW) && ((image->flag & IMA_IS_STEREO) == 0)))
|
||||
{
|
||||
ImageView *iv;
|
||||
int nr = 0;
|
||||
|
||||
for (iv = image->views.first; iv; iv = iv->next) {
|
||||
if (nr++ == iuser->view) {
|
||||
display_name = iv->name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
but = uiDefMenuBut(block, ui_imageuser_view_menu_multiview, rnd_pt, display_name, 0, 0, wmenu1, UI_UNIT_Y, TIP_("Select View"));
|
||||
UI_but_func_set(but, image_multiview_cb, image, iuser);
|
||||
UI_but_type_set_menu_from_pulldown(but);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -734,13 +846,13 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
|
||||
|
||||
if (ima->source != IMA_SRC_GENERATED) {
|
||||
row = uiLayoutRow(layout, true);
|
||||
if (ima->packedfile)
|
||||
if (BKE_image_has_packedfile(ima))
|
||||
uiItemO(row, "", ICON_PACKAGE, "image.unpack");
|
||||
else
|
||||
uiItemO(row, "", ICON_UGLYPACKAGE, "image.pack");
|
||||
|
||||
row = uiLayoutRow(row, true);
|
||||
uiLayoutSetEnabled(row, ima->packedfile == NULL);
|
||||
uiLayoutSetEnabled(row, BKE_image_has_packedfile(ima) == false);
|
||||
uiItemR(row, &imaptr, "filepath", 0, "", ICON_NONE);
|
||||
uiItemO(row, "", ICON_FILE_REFRESH, "image.reload");
|
||||
}
|
||||
@@ -792,6 +904,17 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
|
||||
uiItemR(row, &imaptr, "alpha_mode", 0, IFACE_("Alpha"), ICON_NONE);
|
||||
}
|
||||
|
||||
if ((scene->r.scemode & R_MULTIVIEW) != 0) {
|
||||
uiItemS(layout);
|
||||
|
||||
col = uiLayoutColumn(layout, false);
|
||||
uiItemR(col, &imaptr, "use_multiview", 0, NULL, ICON_NONE);
|
||||
|
||||
col = uiLayoutColumn(layout, false);
|
||||
uiLayoutSetActive(col, RNA_boolean_get(&imaptr, "use_multiview"));
|
||||
uiTemplateImageViews(col, &imaptr);
|
||||
}
|
||||
|
||||
if (ima->source == IMA_SRC_MOVIE) {
|
||||
col = uiLayoutColumn(layout, false);
|
||||
uiItemR(col, &imaptr, "use_deinterlace", 0, IFACE_("Deinterlace"), ICON_NONE);
|
||||
@@ -962,6 +1085,101 @@ void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, int color_man
|
||||
}
|
||||
}
|
||||
|
||||
void uiTemplateImageStereo3d(uiLayout *layout, PointerRNA *stereo3d_format_ptr)
|
||||
{
|
||||
Stereo3dFormat *stereo3d_format = stereo3d_format_ptr->data;
|
||||
uiLayout *col;
|
||||
|
||||
col = uiLayoutColumn(layout, false);
|
||||
uiItemR(col, stereo3d_format_ptr, "display_mode", 0, NULL, ICON_NONE);
|
||||
|
||||
switch (stereo3d_format->display_mode) {
|
||||
case S3D_DISPLAY_ANAGLYPH:
|
||||
{
|
||||
uiItemR(col, stereo3d_format_ptr, "anaglyph_type", 0, NULL, ICON_NONE);
|
||||
break;
|
||||
}
|
||||
case S3D_DISPLAY_INTERLACE:
|
||||
{
|
||||
uiItemR(col, stereo3d_format_ptr, "interlace_type", 0, NULL, ICON_NONE);
|
||||
uiItemR(col, stereo3d_format_ptr, "use_interlace_swap", 0, NULL, ICON_NONE);
|
||||
break;
|
||||
}
|
||||
case S3D_DISPLAY_SIDEBYSIDE:
|
||||
{
|
||||
uiItemR(col, stereo3d_format_ptr, "use_sidebyside_crosseyed", 0, NULL, ICON_NONE);
|
||||
/* fall-through */
|
||||
}
|
||||
case S3D_DISPLAY_TOPBOTTOM:
|
||||
{
|
||||
uiItemR(col, stereo3d_format_ptr, "use_squeezed_frame", 0, NULL, ICON_NONE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void uiTemplateViewsFormat(uiLayout *layout, PointerRNA *ptr, PointerRNA *stereo3d_format_ptr)
|
||||
{
|
||||
uiLayout *col, *box;
|
||||
|
||||
col = uiLayoutColumn(layout, false);
|
||||
|
||||
uiItemL(col, IFACE_("Views Format:"), ICON_NONE);
|
||||
uiItemR(uiLayoutRow(col, false), ptr, "views_format", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
|
||||
|
||||
if (stereo3d_format_ptr) {
|
||||
box = uiLayoutBox(col);
|
||||
uiLayoutSetActive(box, RNA_enum_get(ptr, "views_format") == R_IMF_VIEWS_STEREO_3D);
|
||||
uiTemplateImageStereo3d(box, stereo3d_format_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void uiTemplateImageViews(uiLayout *layout, PointerRNA *imaptr)
|
||||
{
|
||||
Image *ima = imaptr->data;
|
||||
|
||||
if (ima->type != IMA_TYPE_MULTILAYER) {
|
||||
PropertyRNA *prop;
|
||||
PointerRNA stereo3d_format_ptr;
|
||||
|
||||
prop = RNA_struct_find_property(imaptr, "stereo_3d_format");
|
||||
stereo3d_format_ptr = RNA_property_pointer_get(imaptr, prop);
|
||||
|
||||
uiTemplateViewsFormat(layout, imaptr, &stereo3d_format_ptr);
|
||||
}
|
||||
else {
|
||||
uiTemplateViewsFormat(layout, imaptr, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void uiTemplateImageFormatViews(uiLayout *layout, PointerRNA *imfptr, PointerRNA *ptr)
|
||||
{
|
||||
ImageFormatData *imf = imfptr->data;
|
||||
uiLayout *col;
|
||||
|
||||
if (ptr) {
|
||||
uiItemR(layout, ptr, "use_multiview", 0, NULL, ICON_NONE);
|
||||
col = uiLayoutColumn(layout, false);
|
||||
uiLayoutSetActive(col, RNA_boolean_get(ptr, "use_multiview"));
|
||||
}
|
||||
else {
|
||||
col = uiLayoutColumn(layout, false);
|
||||
}
|
||||
|
||||
if (imf->imtype != R_IMF_IMTYPE_MULTILAYER) {
|
||||
PropertyRNA *prop;
|
||||
PointerRNA stereo3d_format_ptr;
|
||||
|
||||
prop = RNA_struct_find_property(imfptr, "stereo_3d_format");
|
||||
stereo3d_format_ptr = RNA_property_pointer_get(imfptr, prop);
|
||||
|
||||
uiTemplateViewsFormat(col, imfptr, &stereo3d_format_ptr);
|
||||
}
|
||||
else {
|
||||
uiTemplateViewsFormat(col, imfptr, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void uiTemplateImageLayers(uiLayout *layout, bContext *C, Image *ima, ImageUser *iuser)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
|
@@ -783,7 +783,7 @@ void draw_image_main(const bContext *C, ARegion *ar)
|
||||
Image *ima;
|
||||
ImBuf *ibuf;
|
||||
float zoomx, zoomy;
|
||||
bool show_viewer, show_render, show_paint;
|
||||
bool show_viewer, show_render, show_paint, show_stereo3d, show_multilayer;
|
||||
void *lock;
|
||||
|
||||
/* XXX can we do this in refresh? */
|
||||
@@ -813,6 +813,8 @@ void draw_image_main(const bContext *C, ARegion *ar)
|
||||
show_viewer = (ima && ima->source == IMA_SRC_VIEWER) != 0;
|
||||
show_render = (show_viewer && ima->type == IMA_TYPE_R_RESULT) != 0;
|
||||
show_paint = (ima && (sima->mode == SI_MODE_PAINT) && (show_viewer == false) && (show_render == false));
|
||||
show_stereo3d = (ima && (ima->flag & IMA_IS_STEREO) && (sima->iuser.flag & IMA_SHOW_STEREO));
|
||||
show_multilayer = ima && BKE_image_is_multilayer(ima);
|
||||
|
||||
if (show_viewer) {
|
||||
/* use locked draw for drawing viewer image buffer since the compositor
|
||||
@@ -823,6 +825,14 @@ void draw_image_main(const bContext *C, ARegion *ar)
|
||||
BLI_lock_thread(LOCK_DRAW_IMAGE);
|
||||
}
|
||||
|
||||
if (show_stereo3d) {
|
||||
if (show_multilayer)
|
||||
/* update multiindex and pass for the current eye */
|
||||
BKE_image_multilayer_index(ima->rr, &sima->iuser);
|
||||
else
|
||||
BKE_image_multiview_index(ima, &sima->iuser);
|
||||
}
|
||||
|
||||
ibuf = ED_space_image_acquire_buffer(sima, &lock);
|
||||
|
||||
/* draw the image or grid */
|
||||
|
@@ -30,14 +30,21 @@
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#ifndef WIN32
|
||||
# include <unistd.h>
|
||||
#else
|
||||
# include <io.h>
|
||||
#endif
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_string_utf8.h"
|
||||
|
||||
#include "BLF_translation.h"
|
||||
|
||||
@@ -60,6 +67,7 @@
|
||||
#include "BKE_report.h"
|
||||
#include "BKE_screen.h"
|
||||
#include "BKE_sound.h"
|
||||
#include "BKE_scene.h"
|
||||
|
||||
#include "GPU_draw.h"
|
||||
#include "GPU_buffers.h"
|
||||
@@ -68,6 +76,7 @@
|
||||
#include "IMB_imbuf.h"
|
||||
#include "IMB_imbuf_types.h"
|
||||
#include "IMB_moviecache.h"
|
||||
#include "intern/openexr/openexr_multi.h"
|
||||
|
||||
#include "RE_pipeline.h"
|
||||
|
||||
@@ -936,6 +945,7 @@ static void image_filesel(bContext *C, wmOperator *op, const char *path)
|
||||
typedef struct ImageOpenData {
|
||||
PropertyPointerRNA pprop;
|
||||
ImageUser *iuser;
|
||||
ImageFormatData im_format;
|
||||
} ImageOpenData;
|
||||
|
||||
typedef struct ImageFrame {
|
||||
@@ -946,7 +956,6 @@ typedef struct ImageFrame {
|
||||
static void image_open_init(bContext *C, wmOperator *op)
|
||||
{
|
||||
ImageOpenData *iod;
|
||||
|
||||
op->customdata = iod = MEM_callocN(sizeof(ImageOpenData), __func__);
|
||||
iod->iuser = CTX_data_pointer_get_type(C, "image_user", &RNA_ImageUser).data;
|
||||
UI_context_active_but_prop_get_templateID(C, &iod->pprop.ptr, &iod->pprop.prop);
|
||||
@@ -1048,7 +1057,7 @@ static int image_open_exec(bContext *C, wmOperator *op)
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Object *obedit = CTX_data_edit_object(C);
|
||||
ImageUser *iuser = NULL;
|
||||
ImageOpenData *iod;
|
||||
ImageOpenData *iod = op->customdata;
|
||||
PointerRNA idptr;
|
||||
Image *ima = NULL;
|
||||
char path[FILE_MAX];
|
||||
@@ -1085,6 +1094,21 @@ static int image_open_exec(bContext *C, wmOperator *op)
|
||||
if (!op->customdata)
|
||||
image_open_init(C, op);
|
||||
|
||||
/* handle multiview images */
|
||||
if (RNA_boolean_get(op->ptr, "use_multiview")) {
|
||||
ImageFormatData *imf = &iod->im_format;
|
||||
|
||||
ima->flag |= IMA_USE_VIEWS;
|
||||
ima->views_format = imf->views_format;
|
||||
*ima->stereo3d_format = imf->stereo3d_format;
|
||||
}
|
||||
else {
|
||||
ima->flag &= ~IMA_USE_VIEWS;
|
||||
ima->flag &= ~IMA_IS_STEREO;
|
||||
ima->flag &= ~IMA_IS_MULTIVIEW;
|
||||
BKE_image_free_views(ima);
|
||||
}
|
||||
|
||||
/* only image path after save, never ibuf */
|
||||
if (is_relative_path) {
|
||||
if (!exists) {
|
||||
@@ -1128,6 +1152,8 @@ static int image_open_exec(bContext *C, wmOperator *op)
|
||||
iuser->framenr = 1;
|
||||
iuser->offset = frame_ofs - 1;
|
||||
iuser->fie_ima = 2;
|
||||
iuser->scene = scene;
|
||||
BKE_image_init_imageuser(ima, iuser);
|
||||
}
|
||||
|
||||
/* XXX unpackImage frees image buffers */
|
||||
@@ -1146,7 +1172,8 @@ static int image_open_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(
|
||||
SpaceImage *sima = CTX_wm_space_image(C); /* XXX other space types can call */
|
||||
const char *path = U.textudir;
|
||||
Image *ima = NULL;
|
||||
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
PropertyRNA *prop;
|
||||
if (sima) {
|
||||
ima = sima->image;
|
||||
}
|
||||
@@ -1185,11 +1212,44 @@ static int image_open_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(
|
||||
|
||||
image_open_init(C, op);
|
||||
|
||||
/* show multiview save options only if scene has multiviews */
|
||||
prop = RNA_struct_find_property(op->ptr, "show_multiview");
|
||||
RNA_property_boolean_set(op->ptr, prop, (scene->r.scemode & R_MULTIVIEW) != 0);
|
||||
|
||||
image_filesel(C, op, path);
|
||||
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
|
||||
static bool image_open_draw_check_prop(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
|
||||
{
|
||||
const char *prop_id = RNA_property_identifier(prop);
|
||||
|
||||
return !(STREQ(prop_id, "filepath") ||
|
||||
STREQ(prop_id, "directory") ||
|
||||
STREQ(prop_id, "filename")
|
||||
);
|
||||
}
|
||||
|
||||
static void image_open_draw(bContext *UNUSED(C), wmOperator *op)
|
||||
{
|
||||
uiLayout *layout = op->layout;
|
||||
ImageOpenData *iod = op->customdata;
|
||||
ImageFormatData *imf = &iod->im_format;
|
||||
PointerRNA imf_ptr, ptr;
|
||||
|
||||
/* main draw call */
|
||||
RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
|
||||
uiDefAutoButsRNA(layout, &ptr, image_open_draw_check_prop, '\0');
|
||||
|
||||
/* image template */
|
||||
RNA_pointer_create(NULL, &RNA_ImageFormatSettings, imf, &imf_ptr);
|
||||
|
||||
/* multiview template */
|
||||
if (RNA_boolean_get(op->ptr, "show_multiview"))
|
||||
uiTemplateImageFormatViews(layout, &imf_ptr, op->ptr);
|
||||
}
|
||||
|
||||
/* called by other space types too */
|
||||
void IMAGE_OT_open(wmOperatorType *ot)
|
||||
{
|
||||
@@ -1202,6 +1262,7 @@ void IMAGE_OT_open(wmOperatorType *ot)
|
||||
ot->exec = image_open_exec;
|
||||
ot->invoke = image_open_invoke;
|
||||
ot->cancel = image_open_cancel;
|
||||
ot->ui = image_open_draw;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
@@ -1233,10 +1294,10 @@ static int image_match_len_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
|
||||
}
|
||||
|
||||
if (!ima || !iuser || !ima->anim)
|
||||
if (!ima || !iuser || !BKE_image_has_anim(ima))
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
iuser->frames = IMB_anim_get_duration(ima->anim, IMB_TC_RECORD_RUN);
|
||||
iuser->frames = IMB_anim_get_duration(((ImageAnim *) ima->anims.first)->anim, IMB_TC_RECORD_RUN);
|
||||
BKE_image_user_frame_calc(iuser, scene->r.cfra, 0);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
@@ -1433,6 +1494,10 @@ static int save_image_options_init(SaveImageOptions *simopts, SpaceImage *sima,
|
||||
}
|
||||
}
|
||||
|
||||
/* use the multiview image settings as the default */
|
||||
simopts->im_format.stereo3d_format = *ima->stereo3d_format;
|
||||
simopts->im_format.views_format = ima->views_format;
|
||||
|
||||
/* color management */
|
||||
BKE_color_managed_display_settings_copy(&simopts->im_format.display_settings, &scene->display_settings);
|
||||
BKE_color_managed_view_settings_copy(&simopts->im_format.view_settings, &scene->view_settings);
|
||||
@@ -1468,30 +1533,131 @@ static void save_image_options_to_op(SaveImageOptions *simopts, wmOperator *op)
|
||||
RNA_string_set(op->ptr, "filepath", simopts->filepath);
|
||||
}
|
||||
|
||||
/* returns the pass index for the view_id */
|
||||
static int get_multiview_pass_id(RenderResult *rr, ImageUser *iuser, const int view_id)
|
||||
{
|
||||
RenderLayer *rl;
|
||||
RenderPass *rpass;
|
||||
int passtype;
|
||||
short rl_index = 0, rp_index;
|
||||
|
||||
if (rr == NULL || iuser == NULL)
|
||||
return 0;
|
||||
|
||||
if (BLI_listbase_count_ex(&rr->views, 2) < 2)
|
||||
return iuser->pass;
|
||||
|
||||
if (RE_HasFakeLayer(rr))
|
||||
rl_index ++; /* fake compo/sequencer layer */
|
||||
|
||||
rl = BLI_findlink(&rr->layers, rl_index);
|
||||
if (!rl) return iuser->pass;
|
||||
|
||||
rpass = BLI_findlink(&rl->passes, iuser->pass);
|
||||
passtype = rpass->passtype;
|
||||
|
||||
rp_index = 0;
|
||||
for (rpass = rl->passes.first; rpass; rpass = rpass->next, rp_index++) {
|
||||
if (rpass->passtype == passtype &&
|
||||
rpass->view_id == view_id)
|
||||
{
|
||||
return rp_index;
|
||||
}
|
||||
}
|
||||
|
||||
return iuser->pass;
|
||||
}
|
||||
|
||||
static void save_image_post(wmOperator *op, ImBuf *ibuf, Image *ima, int ok, int save_copy, const char *relbase, int relative, int do_newpath, const char *filepath)
|
||||
{
|
||||
if (ok) {
|
||||
if (!save_copy) {
|
||||
if (do_newpath) {
|
||||
BLI_strncpy(ibuf->name, filepath, sizeof(ibuf->name));
|
||||
BLI_strncpy(ima->name, filepath, sizeof(ima->name));
|
||||
}
|
||||
|
||||
ibuf->userflags &= ~IB_BITMAPDIRTY;
|
||||
|
||||
/* change type? */
|
||||
if (ima->type == IMA_TYPE_R_RESULT) {
|
||||
ima->type = IMA_TYPE_IMAGE;
|
||||
|
||||
/* workaround to ensure the render result buffer is no longer used
|
||||
* by this image, otherwise can crash when a new render result is
|
||||
* created. */
|
||||
if (ibuf->rect && !(ibuf->mall & IB_rect))
|
||||
imb_freerectImBuf(ibuf);
|
||||
if (ibuf->rect_float && !(ibuf->mall & IB_rectfloat))
|
||||
imb_freerectfloatImBuf(ibuf);
|
||||
if (ibuf->zbuf && !(ibuf->mall & IB_zbuf))
|
||||
IMB_freezbufImBuf(ibuf);
|
||||
if (ibuf->zbuf_float && !(ibuf->mall & IB_zbuffloat))
|
||||
IMB_freezbuffloatImBuf(ibuf);
|
||||
}
|
||||
if (ELEM(ima->source, IMA_SRC_GENERATED, IMA_SRC_VIEWER)) {
|
||||
ima->source = IMA_SRC_FILE;
|
||||
ima->type = IMA_TYPE_IMAGE;
|
||||
}
|
||||
|
||||
/* only image path, never ibuf */
|
||||
if (relative) {
|
||||
BLI_path_rel(ima->name, relbase); /* only after saving */
|
||||
}
|
||||
|
||||
IMB_colormanagment_colorspace_from_ibuf_ftype(&ima->colorspace_settings, ibuf);
|
||||
|
||||
}
|
||||
}
|
||||
else {
|
||||
BKE_reportf(op->reports, RPT_ERROR, "Could not write image %s", filepath);
|
||||
}
|
||||
}
|
||||
|
||||
static void save_imbuf_post(ImBuf *ibuf, ImBuf *colormanaged_ibuf)
|
||||
{
|
||||
if (colormanaged_ibuf != ibuf) {
|
||||
/* This guys might be modified by image buffer write functions,
|
||||
* need to copy them back from color managed image buffer to an
|
||||
* original one, so file type of image is being properly updated.
|
||||
*/
|
||||
ibuf->ftype = colormanaged_ibuf->ftype;
|
||||
ibuf->planes = colormanaged_ibuf->planes;
|
||||
|
||||
IMB_freeImBuf(colormanaged_ibuf);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \return success.
|
||||
* \note ``ima->name`` and ``ibuf->name`` should end up the same.
|
||||
* \note for multiview the first ``ibuf`` is important to get the settings.
|
||||
*/
|
||||
static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveImageOptions *simopts, bool do_newpath)
|
||||
{
|
||||
Image *ima = ED_space_image(sima);
|
||||
void *lock;
|
||||
ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock);
|
||||
Scene *scene;
|
||||
RenderResult *rr = NULL;
|
||||
bool ok = false;
|
||||
|
||||
WM_cursor_wait(1);
|
||||
|
||||
if (ibuf) {
|
||||
ImBuf *colormanaged_ibuf;
|
||||
ImBuf *colormanaged_ibuf = NULL;
|
||||
const char *relbase = ID_BLEND_PATH(CTX_data_main(C), &ima->id);
|
||||
const bool relative = (RNA_struct_find_property(op->ptr, "relative_path") && RNA_boolean_get(op->ptr, "relative_path"));
|
||||
const bool save_copy = (RNA_struct_find_property(op->ptr, "copy") && RNA_boolean_get(op->ptr, "copy"));
|
||||
const bool save_as_render = (RNA_struct_find_property(op->ptr, "save_as_render") && RNA_boolean_get(op->ptr, "save_as_render"));
|
||||
ImageFormatData *imf = &simopts->im_format;
|
||||
|
||||
const bool is_multilayer = imf->imtype == R_IMF_IMTYPE_MULTILAYER;
|
||||
bool is_mono;
|
||||
|
||||
/* old global to ensure a 2nd save goes to same dir */
|
||||
BLI_strncpy(G.ima, simopts->filepath, sizeof(G.ima));
|
||||
|
||||
WM_cursor_wait(1);
|
||||
|
||||
if (ima->type == IMA_TYPE_R_RESULT) {
|
||||
/* enforce user setting for RGB or RGBA, but skip BW */
|
||||
if (simopts->im_format.planes == R_IMF_PLANES_RGBA) {
|
||||
@@ -1512,83 +1678,197 @@ static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI
|
||||
}
|
||||
}
|
||||
|
||||
colormanaged_ibuf = IMB_colormanagement_imbuf_for_write(ibuf, save_as_render, true, &imf->view_settings, &imf->display_settings, imf);
|
||||
/* we need renderresult for exr and rendered multiview */
|
||||
scene = CTX_data_scene(C);
|
||||
rr = BKE_image_acquire_renderresult(scene, ima);
|
||||
is_mono = rr ? BLI_listbase_count_ex(&rr->views, 2) < 2 : (ima->flag & IMA_IS_MULTIVIEW) == 0;
|
||||
|
||||
if (simopts->im_format.imtype == R_IMF_IMTYPE_MULTILAYER) {
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
RenderResult *rr = BKE_image_acquire_renderresult(scene, ima);
|
||||
if (rr) {
|
||||
ok = RE_WriteRenderResult(op->reports, rr, simopts->filepath, simopts->im_format.exr_codec);
|
||||
/* error handling */
|
||||
if (!rr) {
|
||||
if (imf->imtype == R_IMF_IMTYPE_MULTILAYER) {
|
||||
BKE_report(op->reports, RPT_ERROR, "Did not write, no Multilayer Image");
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (imf->views_format == R_IMF_VIEWS_STEREO_3D) {
|
||||
if ((ima->flag & IMA_IS_STEREO) == 0) {
|
||||
BKE_reportf(op->reports, RPT_ERROR, "Did not write, the image doesn't have a \"%s\" and \"%s\" views",
|
||||
STEREO_LEFT_NAME, STEREO_RIGHT_NAME);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* it shouldn't ever happen*/
|
||||
if ((BLI_findstring(&rr->views, STEREO_LEFT_NAME, offsetof(RenderView, name)) == NULL) ||
|
||||
(BLI_findstring(&rr->views, STEREO_RIGHT_NAME, offsetof(RenderView, name)) == NULL))
|
||||
{
|
||||
BKE_reportf(op->reports, RPT_ERROR, "Did not write, the image doesn't have a \"%s\" and \"%s\" views",
|
||||
STEREO_LEFT_NAME, STEREO_RIGHT_NAME);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* fancy multiview OpenEXR */
|
||||
if ((imf->imtype == R_IMF_IMTYPE_MULTILAYER) && (imf->views_format == R_IMF_VIEWS_MULTIVIEW)) {
|
||||
ok = RE_WriteRenderResult(op->reports, rr, simopts->filepath, imf, true, NULL);
|
||||
save_image_post(op, ibuf, ima, ok, true, relbase, relative, do_newpath, simopts->filepath);
|
||||
ED_space_image_release_buffer(sima, ibuf, lock);
|
||||
}
|
||||
else if ((imf->imtype == R_IMF_IMTYPE_OPENEXR) && (imf->views_format == R_IMF_VIEWS_MULTIVIEW)) {
|
||||
/* treat special Openexr case separetely (this is the singlelayer multiview OpenEXR */
|
||||
BKE_imbuf_write_prepare(ibuf, imf);
|
||||
ok = BKE_image_save_openexr_multiview(ima, ibuf, simopts->filepath, (IB_rect | IB_zbuf | IB_zbuffloat | IB_multiview));
|
||||
ED_space_image_release_buffer(sima, ibuf, lock);
|
||||
}
|
||||
/* regular mono pipeline */
|
||||
else if (is_mono) {
|
||||
if (is_multilayer) {
|
||||
ok = RE_WriteRenderResult(op->reports, rr, simopts->filepath, imf, false, NULL);
|
||||
}
|
||||
else {
|
||||
BKE_report(op->reports, RPT_ERROR, "Did not write, no Multilayer Image");
|
||||
colormanaged_ibuf = IMB_colormanagement_imbuf_for_write(ibuf, save_as_render, true, &imf->view_settings, &imf->display_settings, imf);
|
||||
ok = BKE_imbuf_write_as(colormanaged_ibuf, simopts->filepath, imf, save_copy);
|
||||
save_imbuf_post(ibuf, colormanaged_ibuf);
|
||||
}
|
||||
BKE_image_release_renderresult(scene, ima);
|
||||
}
|
||||
else {
|
||||
ok = BKE_imbuf_write_as(colormanaged_ibuf, simopts->filepath, &simopts->im_format, save_copy);
|
||||
save_image_post(op, ibuf, ima, ok, (is_multilayer ? true : save_copy), relbase, relative, do_newpath, simopts->filepath);
|
||||
ED_space_image_release_buffer(sima, ibuf, lock);
|
||||
}
|
||||
/* individual multiview images */
|
||||
else if (imf->views_format == R_IMF_VIEWS_INDIVIDUAL) {
|
||||
size_t i;
|
||||
unsigned char planes = ibuf->planes;
|
||||
const size_t totviews = (rr ? BLI_listbase_count(&rr->views) : BLI_listbase_count(&ima->views));
|
||||
|
||||
if (ok) {
|
||||
if (!save_copy) {
|
||||
if (do_newpath) {
|
||||
BLI_strncpy(ibuf->name, simopts->filepath, sizeof(ibuf->name));
|
||||
BLI_strncpy(ima->name, simopts->filepath, sizeof(ima->name));
|
||||
if (!is_multilayer) {
|
||||
ED_space_image_release_buffer(sima, ibuf, lock);
|
||||
}
|
||||
|
||||
for (i = 0; i < totviews; i++) {
|
||||
char filepath[FILE_MAX];
|
||||
bool ok_view = false;
|
||||
const char *view = rr ? ((RenderView *) BLI_findlink(&rr->views, i))->name :
|
||||
((ImageView *) BLI_findlink(&ima->views, i))->name;
|
||||
|
||||
if (is_multilayer) {
|
||||
BKE_scene_multiview_view_filepath_get(&scene->r, simopts->filepath, view, filepath);
|
||||
ok_view = RE_WriteRenderResult(op->reports, rr, filepath, imf, false, view);
|
||||
save_image_post(op, ibuf, ima, ok_view, true, relbase, relative, do_newpath, filepath);
|
||||
}
|
||||
else {
|
||||
/* copy iuser to get the correct ibuf for this view */
|
||||
ImageUser iuser = sima->iuser;
|
||||
iuser.view = i;
|
||||
iuser.flag &= ~IMA_SHOW_STEREO;
|
||||
|
||||
ibuf->userflags &= ~IB_BITMAPDIRTY;
|
||||
if (rr) {
|
||||
iuser.pass = get_multiview_pass_id(rr, &sima->iuser, i);
|
||||
BKE_image_multilayer_index(rr, &iuser);
|
||||
}
|
||||
else {
|
||||
BKE_image_multiview_index(ima, &iuser);
|
||||
}
|
||||
|
||||
/* change type? */
|
||||
if (ima->type == IMA_TYPE_R_RESULT) {
|
||||
ima->type = IMA_TYPE_IMAGE;
|
||||
ibuf = BKE_image_acquire_ibuf(sima->image, &iuser, &lock);
|
||||
ibuf->planes = planes;
|
||||
|
||||
/* workaround to ensure the render result buffer is no longer used
|
||||
* by this image, otherwise can crash when a new render result is
|
||||
* created. */
|
||||
if (ibuf->rect && !(ibuf->mall & IB_rect))
|
||||
imb_freerectImBuf(ibuf);
|
||||
if (ibuf->rect_float && !(ibuf->mall & IB_rectfloat))
|
||||
imb_freerectfloatImBuf(ibuf);
|
||||
if (ibuf->zbuf && !(ibuf->mall & IB_zbuf))
|
||||
IMB_freezbufImBuf(ibuf);
|
||||
if (ibuf->zbuf_float && !(ibuf->mall & IB_zbuffloat))
|
||||
IMB_freezbuffloatImBuf(ibuf);
|
||||
}
|
||||
if (ELEM(ima->source, IMA_SRC_GENERATED, IMA_SRC_VIEWER)) {
|
||||
ima->source = IMA_SRC_FILE;
|
||||
ima->type = IMA_TYPE_IMAGE;
|
||||
BKE_scene_multiview_view_filepath_get(&scene->r, simopts->filepath, view, filepath);
|
||||
|
||||
colormanaged_ibuf = IMB_colormanagement_imbuf_for_write(ibuf, save_as_render, true, &imf->view_settings, &imf->display_settings, imf);
|
||||
ok_view = BKE_imbuf_write_as(colormanaged_ibuf, filepath, &simopts->im_format, save_copy);
|
||||
save_imbuf_post(ibuf, colormanaged_ibuf);
|
||||
save_image_post(op, ibuf, ima, ok_view, true, relbase, relative, do_newpath, filepath);
|
||||
BKE_image_release_ibuf(sima->image, ibuf, lock);
|
||||
}
|
||||
ok &= ok_view;
|
||||
}
|
||||
|
||||
/* only image path, never ibuf */
|
||||
if (relative) {
|
||||
BLI_path_rel(ima->name, relbase); /* only after saving */
|
||||
}
|
||||
|
||||
IMB_colormanagment_colorspace_from_ibuf_ftype(&ima->colorspace_settings, ibuf);
|
||||
if (is_multilayer) {
|
||||
ED_space_image_release_buffer(sima, ibuf, lock);
|
||||
}
|
||||
}
|
||||
else {
|
||||
BKE_reportf(op->reports, RPT_ERROR, "Could not write image %s", simopts->filepath);
|
||||
}
|
||||
/* stereo (multiview) images */
|
||||
else if (simopts->im_format.views_format == R_IMF_VIEWS_STEREO_3D) {
|
||||
if (imf->imtype == R_IMF_IMTYPE_MULTILAYER) {
|
||||
ok = RE_WriteRenderResult(op->reports, rr, simopts->filepath, imf, false, NULL);
|
||||
save_image_post(op, ibuf, ima, ok, true, relbase, relative, do_newpath, simopts->filepath);
|
||||
ED_space_image_release_buffer(sima, ibuf, lock);
|
||||
}
|
||||
else {
|
||||
ImBuf *ibuf_stereo[2] = {NULL};
|
||||
|
||||
unsigned char planes = ibuf->planes;
|
||||
const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
|
||||
int i;
|
||||
|
||||
/* we need to get the specific per-view buffers */
|
||||
ED_space_image_release_buffer(sima, ibuf, lock);
|
||||
|
||||
for (i = 0; i < 2; i ++) {
|
||||
ImageUser iuser = sima->iuser;
|
||||
iuser.flag &= ~IMA_SHOW_STEREO;
|
||||
|
||||
if (rr) {
|
||||
int id = BLI_findstringindex(&rr->views, names[i], offsetof(RenderView, name));
|
||||
iuser.pass = get_multiview_pass_id(rr, &sima->iuser, id);
|
||||
iuser.view = id;
|
||||
|
||||
BKE_image_multilayer_index(rr, &iuser);
|
||||
}
|
||||
else {
|
||||
iuser.view = i;
|
||||
BKE_image_multiview_index(ima, &iuser);
|
||||
}
|
||||
|
||||
ibuf = BKE_image_acquire_ibuf(sima->image, &iuser, &lock);
|
||||
|
||||
if (ibuf == NULL) {
|
||||
BKE_report(op->reports, RPT_ERROR, "Did not write, unexpected error when saving stereo image");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ibuf->planes = planes;
|
||||
|
||||
/* color manage the ImBuf leaving it ready for saving */
|
||||
colormanaged_ibuf = IMB_colormanagement_imbuf_for_write(ibuf, save_as_render, true,
|
||||
&imf->view_settings, &imf->display_settings, imf);
|
||||
|
||||
BKE_imbuf_write_prepare(colormanaged_ibuf, imf);
|
||||
IMB_prepare_write_ImBuf(IMB_isfloat(colormanaged_ibuf), colormanaged_ibuf);
|
||||
|
||||
/* duplicate buffer to prevent locker issue when using render result */
|
||||
ibuf_stereo[i] = IMB_dupImBuf(colormanaged_ibuf);
|
||||
|
||||
save_imbuf_post(ibuf, colormanaged_ibuf);
|
||||
BKE_image_release_ibuf(sima->image, ibuf, lock);
|
||||
}
|
||||
|
||||
ibuf = IMB_stereo3d_ImBuf(imf, ibuf_stereo[0], ibuf_stereo[1]);
|
||||
|
||||
/* save via traditional path */
|
||||
ok = BKE_imbuf_write_as(ibuf, simopts->filepath, imf, save_copy);
|
||||
|
||||
IMB_freeImBuf(ibuf);
|
||||
|
||||
for (i = 0; i < 2; i ++) {
|
||||
IMB_freeImBuf(ibuf_stereo[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, sima->image);
|
||||
|
||||
WM_cursor_wait(0);
|
||||
|
||||
if (colormanaged_ibuf != ibuf) {
|
||||
/* This guys might be modified by image buffer write functions,
|
||||
* need to copy them back from color managed image buffer to an
|
||||
* original one, so file type of image is being properly updated.
|
||||
*/
|
||||
ibuf->ftype = colormanaged_ibuf->ftype;
|
||||
ibuf->planes = colormanaged_ibuf->planes;
|
||||
|
||||
IMB_freeImBuf(colormanaged_ibuf);
|
||||
}
|
||||
}
|
||||
else {
|
||||
cleanup:
|
||||
ED_space_image_release_buffer(sima, ibuf, lock);
|
||||
}
|
||||
|
||||
ED_space_image_release_buffer(sima, ibuf, lock);
|
||||
if (rr) {
|
||||
BKE_image_release_renderresult(scene, ima);
|
||||
}
|
||||
|
||||
WM_cursor_wait(0);
|
||||
|
||||
return ok;
|
||||
}
|
||||
@@ -1636,6 +1916,7 @@ static int image_save_as_invoke(bContext *C, wmOperator *op, const wmEvent *UNUS
|
||||
Image *ima = ED_space_image(sima);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
SaveImageOptions simopts;
|
||||
PropertyRNA *prop;
|
||||
const bool save_as_render = ((ima->source == IMA_SRC_VIEWER) || (ima->flag & IMA_VIEW_AS_RENDER));
|
||||
|
||||
if (RNA_struct_property_is_set(op->ptr, "filepath"))
|
||||
@@ -1657,6 +1938,12 @@ static int image_save_as_invoke(bContext *C, wmOperator *op, const wmEvent *UNUS
|
||||
op->customdata = MEM_mallocN(sizeof(simopts.im_format), __func__);
|
||||
memcpy(op->customdata, &simopts.im_format, sizeof(simopts.im_format));
|
||||
|
||||
/* show multiview save options only if image has multiviews */
|
||||
prop = RNA_struct_find_property(op->ptr, "show_multiview");
|
||||
RNA_property_boolean_set(op->ptr, prop, (ima->flag & IMA_IS_MULTIVIEW) != 0);
|
||||
prop = RNA_struct_find_property(op->ptr, "use_multiview");
|
||||
RNA_property_boolean_set(op->ptr, prop, (ima->flag & IMA_IS_MULTIVIEW) != 0);
|
||||
|
||||
image_filesel(C, op, simopts.filepath);
|
||||
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
@@ -1683,15 +1970,20 @@ static void image_save_as_draw(bContext *UNUSED(C), wmOperator *op)
|
||||
{
|
||||
uiLayout *layout = op->layout;
|
||||
ImageFormatData *imf = op->customdata;
|
||||
PointerRNA ptr;
|
||||
PointerRNA imf_ptr, ptr;
|
||||
const bool is_multiview = RNA_boolean_get(op->ptr, "use_multiview");
|
||||
|
||||
/* image template */
|
||||
RNA_pointer_create(NULL, &RNA_ImageFormatSettings, imf, &ptr);
|
||||
uiTemplateImageSettings(layout, &ptr, false);
|
||||
RNA_pointer_create(NULL, &RNA_ImageFormatSettings, imf, &imf_ptr);
|
||||
uiTemplateImageSettings(layout, &imf_ptr, false);
|
||||
|
||||
/* main draw call */
|
||||
RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
|
||||
uiDefAutoButsRNA(layout, &ptr, image_save_as_draw_check_prop, '\0');
|
||||
|
||||
/* multiview template */
|
||||
if (is_multiview)
|
||||
uiTemplateImageFormatViews(layout, &imf_ptr, NULL);
|
||||
}
|
||||
|
||||
static int image_save_as_poll(bContext *C)
|
||||
@@ -1714,8 +2006,6 @@ static int image_save_as_poll(bContext *C)
|
||||
|
||||
void IMAGE_OT_save_as(wmOperatorType *ot)
|
||||
{
|
||||
// PropertyRNA *prop;
|
||||
|
||||
/* identifiers */
|
||||
ot->name = "Save As Image";
|
||||
ot->idname = "IMAGE_OT_save_as";
|
||||
@@ -1932,6 +2222,7 @@ static int image_new_exec(bContext *C, wmOperator *op)
|
||||
float color[4];
|
||||
int width, height, floatbuf, gen_type, alpha;
|
||||
int gen_context;
|
||||
int stereo3d;
|
||||
|
||||
/* retrieve state */
|
||||
sima = CTX_wm_space_image(C);
|
||||
@@ -1952,11 +2243,12 @@ static int image_new_exec(bContext *C, wmOperator *op)
|
||||
RNA_float_get_array(op->ptr, "color", color);
|
||||
alpha = RNA_boolean_get(op->ptr, "alpha");
|
||||
gen_context = RNA_enum_get(op->ptr, "gen_context");
|
||||
stereo3d = RNA_boolean_get(op->ptr, "use_stereo_3d");
|
||||
|
||||
if (!alpha)
|
||||
color[3] = 1.0f;
|
||||
|
||||
ima = BKE_image_add_generated(bmain, width, height, name, alpha ? 32 : 24, floatbuf, gen_type, color);
|
||||
ima = BKE_image_add_generated(bmain, width, height, name, alpha ? 32 : 24, floatbuf, gen_type, color, stereo3d);
|
||||
|
||||
if (!ima)
|
||||
return OPERATOR_CANCELLED;
|
||||
@@ -2036,6 +2328,53 @@ static int image_new_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(e
|
||||
return WM_operator_props_dialog_popup(C, op, 15 * UI_UNIT_X, 5 * UI_UNIT_Y);
|
||||
}
|
||||
|
||||
static void image_new_draw(bContext *UNUSED(C), wmOperator *op)
|
||||
{
|
||||
uiLayout *split, *col[2];
|
||||
uiLayout *layout = op->layout;
|
||||
PointerRNA ptr;
|
||||
#if 0
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
const bool is_multiview = (scene->r.scemode & R_MULTIVIEW) != 0;
|
||||
#endif
|
||||
|
||||
RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
|
||||
|
||||
/* copy of WM_operator_props_dialog_popup() layout */
|
||||
|
||||
split = uiLayoutSplit(layout, 0.5f, false);
|
||||
col[0] = uiLayoutColumn(split, false);
|
||||
col[1] = uiLayoutColumn(split, false);
|
||||
|
||||
uiItemL(col[0], IFACE_("Name"), ICON_NONE);
|
||||
uiItemR(col[1], &ptr, "name", 0, "", ICON_NONE);
|
||||
|
||||
uiItemL(col[0], IFACE_("Width"), ICON_NONE);
|
||||
uiItemR(col[1], &ptr, "width", 0, "", ICON_NONE);
|
||||
|
||||
uiItemL(col[0], IFACE_("Height"), ICON_NONE);
|
||||
uiItemR(col[1], &ptr, "height", 0, "", ICON_NONE);
|
||||
|
||||
uiItemL(col[0], IFACE_("Color"), ICON_NONE);
|
||||
uiItemR(col[1], &ptr, "color", 0, "", ICON_NONE);
|
||||
|
||||
uiItemL(col[0], "", ICON_NONE);
|
||||
uiItemR(col[1], &ptr, "alpha", 0, NULL, ICON_NONE);
|
||||
|
||||
uiItemL(col[0], IFACE_("Generated Type"), ICON_NONE);
|
||||
uiItemR(col[1], &ptr, "generated_type", 0, "", ICON_NONE);
|
||||
|
||||
uiItemL(col[0], "", ICON_NONE);
|
||||
uiItemR(col[1], &ptr, "float", 0, NULL, ICON_NONE);
|
||||
|
||||
#if 0
|
||||
if (is_multiview) {
|
||||
uiItemL(col[0], "", ICON_NONE);
|
||||
uiItemR(col[1], &ptr, "use_stereo_3d", 0, NULL, ICON_NONE);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void IMAGE_OT_new(wmOperatorType *ot)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
@@ -2056,6 +2395,7 @@ void IMAGE_OT_new(wmOperatorType *ot)
|
||||
/* api callbacks */
|
||||
ot->exec = image_new_exec;
|
||||
ot->invoke = image_new_invoke;
|
||||
ot->ui = image_new_draw;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_UNDO;
|
||||
@@ -2075,7 +2415,8 @@ void IMAGE_OT_new(wmOperatorType *ot)
|
||||
RNA_def_boolean(ot->srna, "float", 0, "32 bit Float", "Create image with 32 bit floating point bit depth");
|
||||
prop = RNA_def_enum(ot->srna, "gen_context", gen_context_items, 0, "Gen Context", "Generation context");
|
||||
RNA_def_property_flag(prop, PROP_HIDDEN);
|
||||
|
||||
prop = RNA_def_boolean(ot->srna, "use_stereo_3d", 0, "Stereo 3D", "Create an image with left and right views");
|
||||
RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
|
||||
}
|
||||
|
||||
#undef IMA_DEF_NAME
|
||||
@@ -2200,7 +2541,7 @@ static bool image_pack_test(bContext *C, wmOperator *op)
|
||||
|
||||
if (!ima)
|
||||
return 0;
|
||||
if (!as_png && ima->packedfile)
|
||||
if (!as_png && BKE_image_has_packedfile(ima))
|
||||
return 0;
|
||||
|
||||
if (ima->source == IMA_SRC_SEQUENCE || ima->source == IMA_SRC_MOVIE) {
|
||||
@@ -2229,7 +2570,7 @@ static int image_pack_exec(bContext *C, wmOperator *op)
|
||||
if (as_png)
|
||||
BKE_image_memorypack(ima);
|
||||
else
|
||||
ima->packedfile = newPackedFile(op->reports, ima->name, ID_BLEND_PATH(bmain, &ima->id));
|
||||
BKE_image_packfiles(op->reports, ima, ID_BLEND_PATH(bmain, &ima->id));
|
||||
|
||||
WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
|
||||
|
||||
@@ -2301,7 +2642,7 @@ static int image_unpack_exec(bContext *C, wmOperator *op)
|
||||
if (!ima) ima = CTX_data_edit_image(C);
|
||||
}
|
||||
|
||||
if (!ima || !ima->packedfile)
|
||||
if (!ima || !BKE_image_has_packedfile(ima))
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
if (ima->source == IMA_SRC_SEQUENCE || ima->source == IMA_SRC_MOVIE) {
|
||||
@@ -2329,7 +2670,7 @@ static int image_unpack_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE
|
||||
if (RNA_struct_property_is_set(op->ptr, "id"))
|
||||
return image_unpack_exec(C, op);
|
||||
|
||||
if (!ima || !ima->packedfile)
|
||||
if (!ima || !BKE_image_has_packedfile(ima))
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
if (ima->source == IMA_SRC_SEQUENCE || ima->source == IMA_SRC_MOVIE) {
|
||||
@@ -2340,7 +2681,7 @@ static int image_unpack_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE
|
||||
if (G.fileflags & G_AUTOPACK)
|
||||
BKE_report(op->reports, RPT_WARNING, "AutoPack is enabled, so image will be packed again on file save");
|
||||
|
||||
unpack_menu(C, "IMAGE_OT_unpack", ima->id.name + 2, ima->name, "textures", ima->packedfile);
|
||||
unpack_menu(C, "IMAGE_OT_unpack", ima->id.name + 2, ima->name, "textures", BKE_image_has_packedfile(ima) ? ((ImagePackedFile *)ima->packedfiles.first)->packedfile : NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
@@ -156,7 +156,8 @@ static SpaceLink *image_new(const bContext *UNUSED(C))
|
||||
simage->iuser.ok = true;
|
||||
simage->iuser.fie_ima = 2;
|
||||
simage->iuser.frames = 100;
|
||||
|
||||
simage->iuser.flag = IMA_SHOW_STEREO;
|
||||
|
||||
scopes_new(&simage->scopes);
|
||||
simage->sample_line_hist.height = 100;
|
||||
|
||||
|
@@ -703,7 +703,9 @@ static void node_buts_image_user(uiLayout *layout, bContext *C, PointerRNA *ptr,
|
||||
uiItemR(col, ptr, "use_auto_refresh", 0, NULL, ICON_NONE);
|
||||
}
|
||||
|
||||
if (RNA_enum_get(imaptr, "type") == IMA_TYPE_MULTILAYER) {
|
||||
if (RNA_enum_get(imaptr, "type") == IMA_TYPE_MULTILAYER &&
|
||||
RNA_boolean_get(ptr, "has_layers"))
|
||||
{
|
||||
col = uiLayoutColumn(layout, false);
|
||||
uiItemR(col, ptr, "layer", 0, NULL, ICON_NONE);
|
||||
}
|
||||
@@ -1214,6 +1216,24 @@ static void node_shader_set_butfunc(bNodeType *ntype)
|
||||
|
||||
/* ****************** BUTTON CALLBACKS FOR COMPOSITE NODES ***************** */
|
||||
|
||||
static void node_buts_image_views(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr,
|
||||
PointerRNA *imaptr)
|
||||
{
|
||||
uiLayout *col;
|
||||
|
||||
if (!imaptr->data)
|
||||
return;
|
||||
|
||||
col = uiLayoutColumn(layout, false);
|
||||
|
||||
if (RNA_boolean_get(ptr, "has_views")) {
|
||||
if (RNA_enum_get(ptr, "view") == 0)
|
||||
uiItemR(col, ptr, "view", 0, NULL, ICON_CAMERA_STEREO);
|
||||
else
|
||||
uiItemR(col, ptr, "view", 0, NULL, ICON_SCENE);
|
||||
}
|
||||
}
|
||||
|
||||
static void node_composit_buts_image(uiLayout *layout, bContext *C, PointerRNA *ptr)
|
||||
{
|
||||
bNode *node = ptr->data;
|
||||
@@ -1227,6 +1247,8 @@ static void node_composit_buts_image(uiLayout *layout, bContext *C, PointerRNA *
|
||||
imaptr = RNA_pointer_get(ptr, "image");
|
||||
|
||||
node_buts_image_user(layout, C, ptr, &imaptr, &iuserptr);
|
||||
|
||||
node_buts_image_views(layout, C, ptr, &imaptr);
|
||||
}
|
||||
|
||||
static void node_composit_buts_image_ex(uiLayout *layout, bContext *C, PointerRNA *ptr)
|
||||
@@ -1717,8 +1739,8 @@ static void node_composit_buts_id_mask(uiLayout *layout, bContext *UNUSED(C), Po
|
||||
static void node_composit_buts_file_output(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
|
||||
{
|
||||
PointerRNA imfptr = RNA_pointer_get(ptr, "format");
|
||||
int multilayer = (RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_MULTILAYER);
|
||||
|
||||
const bool multilayer = RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_MULTILAYER;
|
||||
|
||||
if (multilayer)
|
||||
uiItemL(layout, IFACE_("Path:"), ICON_NONE);
|
||||
else
|
||||
@@ -1727,15 +1749,22 @@ static void node_composit_buts_file_output(uiLayout *layout, bContext *UNUSED(C)
|
||||
}
|
||||
static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, PointerRNA *ptr)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
PointerRNA imfptr = RNA_pointer_get(ptr, "format");
|
||||
PointerRNA active_input_ptr, op_ptr;
|
||||
uiLayout *row, *col;
|
||||
int active_index;
|
||||
int multilayer = (RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_MULTILAYER);
|
||||
const bool multilayer = RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_MULTILAYER;
|
||||
const bool is_multiview = (scene->r.scemode & R_MULTIVIEW) != 0;
|
||||
|
||||
node_composit_buts_file_output(layout, C, ptr);
|
||||
uiTemplateImageSettings(layout, &imfptr, false);
|
||||
|
||||
/* disable stereo output for multilayer, too much work for something that no one will use */
|
||||
/* if someone asks for that we can implement it */
|
||||
if (is_multiview)
|
||||
uiTemplateImageFormatViews(layout, &imfptr, NULL);
|
||||
|
||||
uiItemS(layout);
|
||||
|
||||
uiItemO(layout, IFACE_("Add Input"), ICON_ZOOMIN, "NODE_OT_output_file_add_socket");
|
||||
@@ -1797,6 +1826,9 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi
|
||||
col = uiLayoutColumn(layout, false);
|
||||
uiLayoutSetActive(col, RNA_boolean_get(&active_input_ptr, "use_node_format") == false);
|
||||
uiTemplateImageSettings(col, &imfptr, false);
|
||||
|
||||
if (is_multiview)
|
||||
uiTemplateImageFormatViews(layout, &imfptr, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2090,6 +2122,18 @@ static void node_composit_buts_switch(uiLayout *layout, bContext *UNUSED(C), Poi
|
||||
uiItemR(layout, ptr, "check", 0, NULL, ICON_NONE);
|
||||
}
|
||||
|
||||
static void node_composit_buts_switch_view_ex(uiLayout *layout, bContext *UNUSED(C), PointerRNA *UNUSED(ptr))
|
||||
{
|
||||
PointerRNA op_ptr;
|
||||
wmOperatorType *ot = WM_operatortype_find("NODE_OT_switch_view_update", 1);
|
||||
|
||||
BLI_assert(ot != 0);
|
||||
|
||||
WM_operator_properties_create_ptr(&op_ptr, ot);
|
||||
|
||||
uiItemFullO_ptr(layout, ot, "Update Views", ICON_FILE_REFRESH, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0);
|
||||
}
|
||||
|
||||
static void node_composit_buts_boxmask(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
|
||||
{
|
||||
uiLayout *row;
|
||||
@@ -2587,6 +2631,9 @@ static void node_composit_set_butfunc(bNodeType *ntype)
|
||||
case CMP_NODE_SWITCH:
|
||||
ntype->draw_buttons = node_composit_buts_switch;
|
||||
break;
|
||||
case CMP_NODE_SWITCH_VIEW:
|
||||
ntype->draw_buttons_ex = node_composit_buts_switch_view_ex;
|
||||
break;
|
||||
case CMP_NODE_MASK_BOX:
|
||||
ntype->draw_buttons = node_composit_buts_boxmask;
|
||||
ntype->draw_backdrop = node_composit_backdrop_boxmask;
|
||||
@@ -2959,6 +3006,7 @@ static void node_file_output_socket_draw(bContext *C, uiLayout *layout, PointerR
|
||||
|
||||
imfptr = RNA_pointer_get(node_ptr, "format");
|
||||
imtype = RNA_enum_get(&imfptr, "file_format");
|
||||
|
||||
if (imtype == R_IMF_IMTYPE_MULTILAYER) {
|
||||
NodeImageMultiFileSocket *input = sock->storage;
|
||||
RNA_pointer_create(&ntree->id, &RNA_NodeOutputFileSlotLayer, input, &inputptr);
|
||||
|
@@ -212,13 +212,13 @@ static void compo_progressjob(void *cjv, float progress)
|
||||
*(cj->progress) = progress;
|
||||
}
|
||||
|
||||
|
||||
/* only this runs inside thread */
|
||||
static void compo_startjob(void *cjv, short *stop, short *do_update, float *progress)
|
||||
{
|
||||
CompoJob *cj = cjv;
|
||||
bNodeTree *ntree = cj->localtree;
|
||||
Scene *scene = cj->scene;
|
||||
SceneRenderView *srv;
|
||||
|
||||
if (scene->use_nodes == false)
|
||||
return;
|
||||
@@ -238,7 +238,11 @@ static void compo_startjob(void *cjv, short *stop, short *do_update, float *prog
|
||||
|
||||
// XXX BIF_store_spare();
|
||||
/* 1 is do_previews */
|
||||
ntreeCompositExecTree(cj->scene, ntree, &cj->scene->r, false, true, &scene->view_settings, &scene->display_settings);
|
||||
|
||||
for (srv = scene->r.views.first; srv; srv = srv->next) {
|
||||
if (BKE_scene_multiview_is_render_view_active(&scene->r, srv) == false) continue;
|
||||
ntreeCompositExecTree(cj->scene, ntree, &cj->scene->r, false, true, &scene->view_settings, &scene->display_settings, srv->name);
|
||||
}
|
||||
|
||||
ntree->test_break = NULL;
|
||||
ntree->stats_draw = NULL;
|
||||
@@ -1660,6 +1664,54 @@ void NODE_OT_delete(wmOperatorType *ot)
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/* ****************** Switch View ******************* */
|
||||
|
||||
static int node_switch_view_poll(bContext *C)
|
||||
{
|
||||
SpaceNode *snode = CTX_wm_space_node(C);
|
||||
|
||||
if (snode && snode->edittree)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int node_switch_view_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
{
|
||||
SpaceNode *snode = CTX_wm_space_node(C);
|
||||
bNode *node, *next;
|
||||
|
||||
for (node = snode->edittree->nodes.first; node; node = next) {
|
||||
next = node->next;
|
||||
if (node->flag & SELECT) {
|
||||
/* call the update function from the Switch View node */
|
||||
node->update = NODE_UPDATE_OPERATOR;
|
||||
}
|
||||
}
|
||||
|
||||
ntreeUpdateTree(CTX_data_main(C), snode->edittree);
|
||||
|
||||
snode_notify(C, snode);
|
||||
snode_dag_update(C, snode);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void NODE_OT_switch_view_update(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Update Views";
|
||||
ot->description = "Update views of selected node";
|
||||
ot->idname = "NODE_OT_switch_view_update";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec = node_switch_view_exec;
|
||||
ot->poll = node_switch_view_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/* ****************** Delete with reconnect ******************* */
|
||||
static int node_delete_reconnect_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
{
|
||||
|
@@ -200,6 +200,8 @@ void NODE_OT_output_file_add_socket(struct wmOperatorType *ot);
|
||||
void NODE_OT_output_file_remove_active_socket(struct wmOperatorType *ot);
|
||||
void NODE_OT_output_file_move_active_socket(struct wmOperatorType *ot);
|
||||
|
||||
void NODE_OT_switch_view_update (struct wmOperatorType *ot);
|
||||
|
||||
/* Note: clipboard_cut is a simple macro of copy + delete */
|
||||
void NODE_OT_clipboard_copy(struct wmOperatorType *ot);
|
||||
void NODE_OT_clipboard_paste(struct wmOperatorType *ot);
|
||||
|
@@ -123,6 +123,8 @@ void node_operatortypes(void)
|
||||
WM_operatortype_append(NODE_OT_viewer_border);
|
||||
WM_operatortype_append(NODE_OT_clear_viewer_border);
|
||||
|
||||
WM_operatortype_append(NODE_OT_switch_view_update);
|
||||
|
||||
WM_operatortype_append(NODE_OT_tree_socket_add);
|
||||
WM_operatortype_append(NODE_OT_tree_socket_remove);
|
||||
WM_operatortype_append(NODE_OT_tree_socket_move);
|
||||
|
@@ -60,6 +60,7 @@
|
||||
#include "ED_screen.h"
|
||||
#include "ED_sequencer.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
|
||||
#include "BKE_sound.h"
|
||||
|
||||
@@ -70,6 +71,10 @@
|
||||
/* own include */
|
||||
#include "sequencer_intern.h"
|
||||
|
||||
typedef struct SequencerAddData {
|
||||
ImageFormatData im_format;
|
||||
} SequencerAddData;
|
||||
|
||||
/* Generic functions, reused by add strip operators */
|
||||
|
||||
/* avoid passing multiple args and be more verbose */
|
||||
@@ -222,6 +227,19 @@ static void seq_load_operator_info(SeqLoadInfo *seq_load, wmOperator *op)
|
||||
}
|
||||
RNA_PROP_END;
|
||||
}
|
||||
|
||||
if ((prop = RNA_struct_find_property(op->ptr, "use_multiview")) && RNA_property_boolean_get(op->ptr, prop)) {
|
||||
if (op->customdata) {
|
||||
SequencerAddData *sad = op->customdata;
|
||||
ImageFormatData *imf = &sad->im_format;
|
||||
|
||||
seq_load->views_format = imf->views_format;
|
||||
seq_load->flag |= SEQ_USE_VIEWS;
|
||||
|
||||
/* operator custom data is always released after the SeqLoadInfo, no need to handle the memory here */
|
||||
seq_load->stereo3d_format = &imf->stereo3d_format;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -573,6 +591,9 @@ static int sequencer_add_generic_strip_exec(bContext *C, wmOperator *op, SeqLoad
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
if (op->customdata)
|
||||
MEM_freeN(op->customdata);
|
||||
|
||||
BKE_sequencer_sort(scene);
|
||||
BKE_sequencer_update_muting(ed);
|
||||
|
||||
@@ -581,15 +602,40 @@ static int sequencer_add_generic_strip_exec(bContext *C, wmOperator *op, SeqLoad
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
/* add sequencer operators */
|
||||
static void sequencer_add_init(bContext *UNUSED(C), wmOperator *op)
|
||||
{
|
||||
op->customdata = MEM_callocN(sizeof(SequencerAddData), __func__);
|
||||
}
|
||||
|
||||
static void sequencer_add_cancel(bContext *UNUSED(C), wmOperator *op)
|
||||
{
|
||||
if (op->customdata)
|
||||
MEM_freeN(op->customdata);
|
||||
op->customdata = NULL;
|
||||
}
|
||||
|
||||
static bool sequencer_add_draw_check_prop(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
|
||||
{
|
||||
const char *prop_id = RNA_property_identifier(prop);
|
||||
|
||||
return !(STREQ(prop_id, "filepath") ||
|
||||
STREQ(prop_id, "directory") ||
|
||||
STREQ(prop_id, "filename")
|
||||
);
|
||||
}
|
||||
|
||||
/* add movie operator */
|
||||
static int sequencer_add_movie_strip_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
return sequencer_add_generic_strip_exec(C, op, BKE_sequencer_add_movie_strip);
|
||||
}
|
||||
|
||||
|
||||
static int sequencer_add_movie_strip_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
|
||||
/* This is for drag and drop */
|
||||
if ((RNA_struct_property_is_set(op->ptr, "files") && RNA_collection_length(op->ptr, "files")) ||
|
||||
RNA_struct_property_is_set(op->ptr, "filepath"))
|
||||
@@ -599,13 +645,37 @@ static int sequencer_add_movie_strip_invoke(bContext *C, wmOperator *op, const w
|
||||
}
|
||||
|
||||
sequencer_generic_invoke_xy__internal(C, op, 0, SEQ_TYPE_MOVIE);
|
||||
|
||||
|
||||
sequencer_add_init(C, op);
|
||||
|
||||
/* show multiview save options only if scene has multiviews */
|
||||
prop = RNA_struct_find_property(op->ptr, "show_multiview");
|
||||
RNA_property_boolean_set(op->ptr, prop, (scene->r.scemode & R_MULTIVIEW) != 0);
|
||||
|
||||
WM_event_add_fileselect(C, op);
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
|
||||
//return sequencer_add_movie_strip_exec(C, op);
|
||||
}
|
||||
|
||||
static void sequencer_add_draw(bContext *UNUSED(C), wmOperator *op)
|
||||
{
|
||||
uiLayout *layout = op->layout;
|
||||
SequencerAddData *sad = op->customdata;
|
||||
ImageFormatData *imf = &sad->im_format;
|
||||
PointerRNA imf_ptr, ptr;
|
||||
|
||||
/* main draw call */
|
||||
RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
|
||||
uiDefAutoButsRNA(layout, &ptr, sequencer_add_draw_check_prop, '\0');
|
||||
|
||||
/* image template */
|
||||
RNA_pointer_create(NULL, &RNA_ImageFormatSettings, imf, &imf_ptr);
|
||||
|
||||
/* multiview template */
|
||||
if (RNA_boolean_get(op->ptr, "show_multiview"))
|
||||
uiTemplateImageFormatViews(layout, &imf_ptr, op->ptr);
|
||||
}
|
||||
|
||||
void SEQUENCER_OT_movie_strip_add(struct wmOperatorType *ot)
|
||||
{
|
||||
@@ -618,9 +688,11 @@ void SEQUENCER_OT_movie_strip_add(struct wmOperatorType *ot)
|
||||
/* api callbacks */
|
||||
ot->invoke = sequencer_add_movie_strip_invoke;
|
||||
ot->exec = sequencer_add_movie_strip_exec;
|
||||
ot->cancel = sequencer_add_cancel;
|
||||
ot->ui = sequencer_add_draw;
|
||||
|
||||
ot->poll = ED_operator_sequencer_active_editable;
|
||||
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
@@ -735,6 +807,9 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op)
|
||||
|
||||
sequencer_add_apply_overlap(C, op, seq);
|
||||
|
||||
if (op->customdata)
|
||||
MEM_freeN(op->customdata);
|
||||
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
@@ -742,6 +817,9 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op)
|
||||
|
||||
static int sequencer_add_image_strip_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
|
||||
/* drag drop has set the names */
|
||||
if (RNA_struct_property_is_set(op->ptr, "files") && RNA_collection_length(op->ptr, "files")) {
|
||||
sequencer_generic_invoke_xy__internal(C, op, SEQPROP_ENDFRAME | SEQPROP_NOPATHS, SEQ_TYPE_IMAGE);
|
||||
@@ -750,6 +828,12 @@ static int sequencer_add_image_strip_invoke(bContext *C, wmOperator *op, const w
|
||||
|
||||
sequencer_generic_invoke_xy__internal(C, op, SEQPROP_ENDFRAME, SEQ_TYPE_IMAGE);
|
||||
|
||||
sequencer_add_init(C, op);
|
||||
|
||||
/* show multiview save options only if scene has multiviews */
|
||||
prop = RNA_struct_find_property(op->ptr, "show_multiview");
|
||||
RNA_property_boolean_set(op->ptr, prop, (scene->r.scemode & R_MULTIVIEW) != 0);
|
||||
|
||||
WM_event_add_fileselect(C, op);
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
@@ -766,6 +850,8 @@ void SEQUENCER_OT_image_strip_add(struct wmOperatorType *ot)
|
||||
/* api callbacks */
|
||||
ot->invoke = sequencer_add_image_strip_invoke;
|
||||
ot->exec = sequencer_add_image_strip_exec;
|
||||
ot->cancel = sequencer_add_cancel;
|
||||
ot->ui = sequencer_add_draw;
|
||||
|
||||
ot->poll = ED_operator_sequencer_active_editable;
|
||||
|
||||
|
@@ -50,6 +50,7 @@
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_sequencer.h"
|
||||
#include "BKE_sound.h"
|
||||
#include "BKE_scene.h"
|
||||
|
||||
#include "IMB_colormanagement.h"
|
||||
#include "IMB_imbuf.h"
|
||||
@@ -860,7 +861,7 @@ void ED_sequencer_special_preview_clear(void)
|
||||
sequencer_special_update_set(NULL);
|
||||
}
|
||||
|
||||
ImBuf *sequencer_ibuf_get(struct Main *bmain, Scene *scene, SpaceSeq *sseq, int cfra, int frame_ofs)
|
||||
ImBuf *sequencer_ibuf_get(struct Main *bmain, Scene *scene, SpaceSeq *sseq, int cfra, int frame_ofs, const char *viewname)
|
||||
{
|
||||
SeqRenderData context;
|
||||
ImBuf *ibuf;
|
||||
@@ -888,6 +889,7 @@ ImBuf *sequencer_ibuf_get(struct Main *bmain, Scene *scene, SpaceSeq *sseq, int
|
||||
bmain->eval_ctx, bmain, scene,
|
||||
rectx, recty, proxy_size,
|
||||
&context);
|
||||
context.view_id = BKE_scene_multiview_view_id_get(&scene->r, viewname);
|
||||
|
||||
/* sequencer could start rendering, in this case we need to be sure it wouldn't be canceled
|
||||
* by Esc pressed somewhere in the past
|
||||
@@ -994,6 +996,7 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
|
||||
const bool is_imbuf = ED_space_sequencer_check_show_imbuf(sseq);
|
||||
int format, type;
|
||||
bool glsl_used = false;
|
||||
const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
|
||||
|
||||
if (G.is_rendering == false && (scene->r.seq_flag & R_SEQ_GL_PREV) == 0) {
|
||||
/* stop all running jobs, except screen one. currently previews frustrate Render
|
||||
@@ -1023,8 +1026,9 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
|
||||
return;
|
||||
}
|
||||
|
||||
ibuf = sequencer_ibuf_get(bmain, scene, sseq, cfra, frame_ofs);
|
||||
|
||||
/* for now we only support Left/Right */
|
||||
ibuf = sequencer_ibuf_get(bmain, scene, sseq, cfra, frame_ofs, names[sseq->multiview_eye]);
|
||||
|
||||
if (ibuf == NULL)
|
||||
return;
|
||||
|
||||
|
@@ -180,8 +180,6 @@ static void seq_proxy_build_job(const bContext *C)
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Editing *ed = BKE_sequencer_editing_get(scene, false);
|
||||
ScrArea *sa = CTX_wm_area(C);
|
||||
struct SeqIndexBuildContext *context;
|
||||
LinkData *link;
|
||||
Sequence *seq;
|
||||
GSet *file_list;
|
||||
|
||||
@@ -209,9 +207,7 @@ static void seq_proxy_build_job(const bContext *C)
|
||||
SEQP_BEGIN (ed, seq)
|
||||
{
|
||||
if ((seq->flag & SELECT)) {
|
||||
context = BKE_sequencer_proxy_rebuild_context(pj->main, pj->scene, seq, file_list);
|
||||
link = BLI_genericNodeN(context);
|
||||
BLI_addtail(&pj->queue, link);
|
||||
BKE_sequencer_proxy_rebuild_context(pj->main, pj->scene, seq, file_list, &pj->queue);
|
||||
}
|
||||
}
|
||||
SEQ_END
|
||||
@@ -3442,12 +3438,18 @@ static int sequencer_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
SEQP_BEGIN(ed, seq)
|
||||
{
|
||||
if ((seq->flag & SELECT)) {
|
||||
struct SeqIndexBuildContext *context;
|
||||
ListBase queue = {NULL, NULL};
|
||||
LinkData *link;
|
||||
short stop = 0, do_update;
|
||||
float progress;
|
||||
context = BKE_sequencer_proxy_rebuild_context(bmain, scene, seq, file_list);
|
||||
BKE_sequencer_proxy_rebuild(context, &stop, &do_update, &progress);
|
||||
BKE_sequencer_proxy_rebuild_finish(context, 0);
|
||||
|
||||
BKE_sequencer_proxy_rebuild_context(bmain, scene, seq, file_list, &queue);
|
||||
|
||||
for (link = queue.first; link; link = link->next) {
|
||||
struct SeqIndexBuildContext *context = link->data;
|
||||
BKE_sequencer_proxy_rebuild(context, &stop, &do_update, &progress);
|
||||
BKE_sequencer_proxy_rebuild_finish(context, 0);
|
||||
}
|
||||
BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
|
||||
}
|
||||
}
|
||||
|
@@ -62,7 +62,7 @@ void sequencer_special_update_set(Sequence *seq);
|
||||
/* UNUSED */
|
||||
// void seq_reset_imageofs(struct SpaceSeq *sseq);
|
||||
|
||||
struct ImBuf *sequencer_ibuf_get(struct Main *bmain, struct Scene *scene, struct SpaceSeq *sseq, int cfra, int frame_ofs);
|
||||
struct ImBuf *sequencer_ibuf_get(struct Main *bmain, struct Scene *scene, struct SpaceSeq *sseq, int cfra, int frame_ofs, const char *viewname);
|
||||
|
||||
/* sequencer_edit.c */
|
||||
struct View2D;
|
||||
|
@@ -94,7 +94,7 @@ static void sample_apply(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
SpaceSeq *sseq = (SpaceSeq *) CTX_wm_space_data(C);
|
||||
ARegion *ar = CTX_wm_region(C);
|
||||
ImBuf *ibuf = sequencer_ibuf_get(bmain, scene, sseq, CFRA, 0);
|
||||
ImBuf *ibuf = sequencer_ibuf_get(bmain, scene, sseq, CFRA, 0, NULL);
|
||||
ImageSampleInfo *info = op->customdata;
|
||||
float fx, fy;
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user