Merged changes in the trunk up to revision 50257.

Conflicts resolved:
source/blender/blenkernel/CMakeLists.txt
This commit is contained in:
Tamito Kajiyama 2012-08-29 00:53:29 +00:00
commit 141dd5233e
472 changed files with 9322 additions and 4789 deletions

@ -132,6 +132,7 @@ option(WITH_BULLET "Enable Bullet (Physics Engine)" ON)
option(WITH_GAMEENGINE "Enable Game Engine" ON)
option(WITH_PLAYER "Build Player" OFF)
option(WITH_COMPOSITOR "Enable the tile based nodal compositor" ON)
option(WITH_COMPOSITOR_LEGACY "Enable legacy compositor" ON)
# GHOST Windowing Library Options
option(WITH_GHOST_DEBUG "Enable debugging output for the GHOST library" OFF)
@ -1042,6 +1043,8 @@ elseif(WIN32)
set(PLATFORM_LINKLIBS "${PLATFORM_LINKLIBS} -lpthread")
add_definitions(-DFREE_WINDOWS64 -DMS_WIN64)
#Turn off OpenMP since it causes crashes on render for subsurfed/multiresolution meshes
set(WITH_OPENMP OFF)
endif()
add_definitions(-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE)
@ -1796,6 +1799,7 @@ if(FIRST_RUN)
info_cfg_option(WITH_GAMEENGINE)
info_cfg_option(WITH_PLAYER)
info_cfg_option(WITH_BULLET)
info_cfg_option(WITH_IK_SOLVER)
info_cfg_option(WITH_IK_ITASC)
info_cfg_option(WITH_OPENCOLLADA)
info_cfg_option(WITH_FFTW3)

@ -170,7 +170,7 @@ WITH_BF_RAYOPTIMIZATION = True
BF_RAYOPTIMIZATION_SSE_FLAGS = ['-mmmx', '-msse', '-msse2']
#May produce errors with unsupported MinGW-w64 builds
WITH_BF_OPENMP = True
WITH_BF_OPENMP = False
##
CC = 'gcc'

@ -845,6 +845,8 @@ class BlenderEnvironment(SConsEnvironment):
print bc.HEADER+'Configuring program '+bc.ENDC+bc.OKGREEN+progname+bc.ENDC
lenv = self.Clone()
lenv.Append(LINKFLAGS = lenv['PLATFORM_LINKFLAGS'])
if lenv['OURPLATFORM'] in ('win32-mingw', 'win64-mingw', 'linuxcross', 'cygwin', 'linux'):
lenv.Replace(LINK = '$CXX')
if lenv['OURPLATFORM'] in ('win32-vc', 'cygwin', 'win64-vc'):
if lenv['BF_DEBUG']:
lenv.Prepend(LINKFLAGS = ['/DEBUG','/PDB:'+progname+'.pdb','/NODEFAULTLIB:libcmt'])

@ -108,7 +108,7 @@ def validate_arguments(args, bc):
'WITH_BF_STATICFFMPEG', 'BF_FFMPEG_LIB_STATIC',
'WITH_BF_OGG', 'BF_OGG', 'BF_OGG_LIB',
'WITH_BF_FRAMESERVER',
'WITH_BF_COMPOSITOR',
'WITH_BF_COMPOSITOR', 'WITH_BF_COMPOSITOR_LEGACY',
'WITH_BF_JPEG', 'BF_JPEG', 'BF_JPEG_INC', 'BF_JPEG_LIB', 'BF_JPEG_LIBPATH',
'WITH_BF_OPENJPEG', 'BF_OPENJPEG', 'BF_OPENJPEG_INC', 'BF_OPENJPEG_LIB', 'BF_OPENJPEG_LIBPATH',
'WITH_BF_REDCODE', 'BF_REDCODE', 'BF_REDCODE_INC', 'BF_REDCODE_LIB', 'BF_REDCODE_LIBPATH',
@ -583,7 +583,8 @@ def read_opts(env, cfg, args):
('BF_BOOST_LIBPATH', 'Boost library path', ''),
('BF_BOOST_LIB_STATIC', 'Boost static library', ''),
(BoolVariable('WITH_GHOST_XDND', 'Build with drag-n-drop support on Linux platforms using XDND protocol', True))
(BoolVariable('WITH_GHOST_XDND', 'Build with drag-n-drop support on Linux platforms using XDND protocol', True)),
(BoolVariable('WITH_BF_COMPOSITOR_LEGACY', 'Enable the legacy compositor', True))
) # end of opts.AddOptions()
return localopts

@ -75,7 +75,7 @@ Example layouts:
* layout.row()
Use row(), when you want more than 1 propertey in one line.
Use row(), when you want more than 1 property in one line.
.. code-block:: python
@ -145,7 +145,7 @@ Even though you're not looping on the list data **python is**, so you need to be
Modifying Lists
^^^^^^^^^^^^^^^
In python we can add and remove from a list, This is slower when the list length is modified, especially at the start of the list, since all the data after the index of modification needs to be moved up or down 1 place.
In python we can add and remove from a list, this is slower when the list length is modified, especially at the start of the list, since all the data after the index of modification needs to be moved up or down 1 place.
The most simple way to add onto the end of the list is to use ``my_list.append(list_item)`` or ``my_list.extend(some_list)`` and the fastest way to remove an item is ``my_list.pop()`` or ``del my_list[-1]``.
@ -154,13 +154,13 @@ To use an index you can use ``my_list.insert(index, list_item)`` or ``list.pop(i
Sometimes its faster (but more memory hungry) to just rebuild the list.
Say you want to remove all triangle faces in a list.
Say you want to remove all triangular faces in a list.
Rather than...
.. code-block:: python
faces = mesh.faces[:] # make a list copy of the meshes faces
faces = mesh.tessfaces[:] # make a list copy of the meshes faces
f_idx = len(faces) # Loop backwards
while f_idx: # while the value is not 0
f_idx -= 1
@ -173,13 +173,13 @@ It's faster to build a new list with list comprehension.
.. code-block:: python
faces = [f for f in mesh.faces if len(f.vertices) != 3]
faces = [f for f in mesh.tessfaces if len(f.vertices) != 3]
Adding List Items
^^^^^^^^^^^^^^^^^
If you have a list that you want to add onto another list, rather then...
If you have a list that you want to add onto another list, rather than...
.. code-block:: python
@ -205,6 +205,14 @@ This example shows a very sub-optimal way of making a reversed list.
reverse_list.insert(0, list_item)
Python provides more convenient ways to reverse a list using the slice method, but you may want to time this before relying on it too much:
.. code-block:: python
some_reversed_list = some_list[::-1]
Removing List Items
^^^^^^^^^^^^^^^^^^^
@ -224,7 +232,7 @@ Here is an example of how to remove items in 1 loop, removing the last items fir
my_list.pop(list_index)
This example shows a fast way of removing items, for use in cases were where you can alter the list order without breaking the scripts functionality. This works by swapping 2 list items, so the item you remove is always last.
This example shows a fast way of removing items, for use in cases where you can alter the list order without breaking the scripts functionality. This works by swapping 2 list items, so the item you remove is always last.
.. code-block:: python
@ -243,9 +251,9 @@ When removing many items in a large list this can provide a good speedup.
Avoid Copying Lists
^^^^^^^^^^^^^^^^^^^
When passing a list/dictionary to a function, it is faster to have the function modify the list rather then returning a new list so python doesn't have to duplicate the list in memory.
When passing a list/dictionary to a function, it is faster to have the function modify the list rather than returning a new list so python doesn't have to duplicate the list in memory.
Functions that modify a list in-place are more efficient then functions that create new lists.
Functions that modify a list in-place are more efficient than functions that create new lists.
This is generally slower so only use for functions when it makes sense not to modify the list in place.
@ -273,22 +281,22 @@ Here are 3 ways of joining multiple strings into 1 string for writing
This really applies to any area of your code that involves a lot of string joining.
Pythons string addition, *don't use if you can help it, especially when writing data in a loop.*
Pythons string addition, *don't use if you can help it, especially when writing data in a loop.*
>>> file.write(str1 + " " + str2 + " " + str3 + "\n")
String formatting. Use this when you're writing string data from floats and int's
String formatting. Use this when you're writing string data from floats and ints
>>> file.write("%s %s %s\n" % (str1, str2, str3))
Pythons string joining function. To join a list of strings
Pythons string joining function. To join a list of strings
>>> file.write(" ".join([str1, str2, str3, "\n"]))
join is fastest on many strings, string formatting is quite fast too (better for converting data types). String arithmetic is slowest.
join is fastest on many strings, `string formatting <http://docs.python.org/py3k/library/string.html#string-formatting>`_ is quite fast too (better for converting data types). String arithmetic is slowest.
Parsing Strings (Import/Exporting)
@ -296,12 +304,12 @@ Parsing Strings (Import/Exporting)
Since many file formats are ASCII, the way you parse/export strings can make a large difference in how fast your script runs.
When importing strings to make into blender there are a few ways to parse the string.
There are a few ways to parse strings when importing them into Blender.
Parsing Numbers
^^^^^^^^^^^^^^^
Use ``float(string)`` rather than ``eval(string)``, if you know the value will be an int then ``int(string)``, float() will work for an int too but its faster to read ints with int().
Use ``float(string)`` rather than ``eval(string)``, if you know the value will be an int then ``int(string)``, float() will work for an int too but it's faster to read ints with int().
Checking String Start/End
^^^^^^^^^^^^^^^^^^^^^^^^^
@ -318,7 +326,7 @@ Using ``startswith()`` is slightly faster (approx 5%) and also avoids a possible
my_string.endswith("foo_bar") can be used for line endings too.
if your unsure whether the text is upper or lower case use lower or upper string function.
If you are unsure whether the text is upper or lower case use ``lower()`` or ``upper()`` string function.
>>> if line.lower().startswith("vert ")
@ -328,7 +336,7 @@ Use try/except Sparingly
The **try** statement is useful to save time writing error checking code.
However **try** is significantly slower then an **if** since an exception has to be set each time, so avoid using **try** in areas of your code that execute in a loop and runs many times.
However **try** is significantly slower than an **if** since an exception has to be set each time, so avoid using **try** in areas of your code that execute in a loop and runs many times.
There are cases where using **try** is faster than checking whether the condition will raise an error, so it is worth experimenting.
@ -336,7 +344,7 @@ There are cases where using **try** is faster than checking whether the conditio
Value Comparison
----------------
Python has two ways to compare values ``a == b`` and ``a is b``, The difference is that ``==`` may run the objects comparison function ``__cmp__()`` where as ``is`` compares identity, that both variables reference the same item in memory.
Python has two ways to compare values ``a == b`` and ``a is b``, the difference is that ``==`` may run the objects comparison function ``__cmp__()`` whereas ``is`` compares identity, that both variables reference the same item in memory.
In cases where you know you are checking for the same value which is referenced from multiple places, ``is`` is faster.
@ -344,7 +352,7 @@ In cases where you know you are checking for the same value which is referenced
Time Your Code
--------------
While developing a script its good to time it to be aware of any changes in performance, this can be done simply.
While developing a script it's good to time it to be aware of any changes in performance, this can be done simply.
.. code-block:: python

@ -137,11 +137,11 @@ For the time being this limitation just has to be worked around but we're aware
NGons and Tessellation Faces
============================
Since 2.63 NGons are supported, this adds some complexity since in some cases you need to access triangles still (some exporters for example).
Since 2.63 NGons are supported, this adds some complexity since in some cases you need to access triangles/quads still (some exporters for example).
There are now 3 ways to access faces:
* :class:`bpy.types.MeshPolygon` - this is the data stricture which now stores faces in object mode (access as ``mesh.polygons`` rather then ``mesh.faces``).
* :class:`bpy.types.MeshPolygon` - this is the data structure which now stores faces in object mode (access as ``mesh.polygons`` rather then ``mesh.faces``).
* :class:`bpy.types.MeshTessFace` - the result of triangulating (tessellated) polygons, the main method of face access in 2.62 or older (access as ``mesh.tessfaces``).
* :class:`bmesh.types.BMFace` - the polygons as used in editmode.

@ -128,7 +128,7 @@ void rcFilterLedgeSpans(rcContext* ctx, const int walkableHeight, const int walk
rcSpan* ns = solid.spans[dx + dy*w];
int nbot = -walkableClimb;
int ntop = ns ? (int)ns->smin : MAX_HEIGHT;
// Skip neightbour if the gap between the spans is too small.
// Skip neighbor if the gap between the spans is too small.
if (rcMin(top,ntop) - rcMax(bot,nbot) > walkableHeight)
minh = rcMin(minh, nbot - bot);
@ -137,7 +137,7 @@ void rcFilterLedgeSpans(rcContext* ctx, const int walkableHeight, const int walk
{
nbot = (int)ns->smax;
ntop = ns->next ? (int)ns->next->smin : MAX_HEIGHT;
// Skip neightbour if the gap between the spans is too small.
// Skip neighbor if the gap between the spans is too small.
if (rcMin(top,ntop) - rcMax(bot,nbot) > walkableHeight)
{
minh = rcMin(minh, nbot - bot);

@ -63,7 +63,6 @@ include_directories(
# Subdirectories
if(WITH_CYCLES_BLENDER)
add_definitions(-DBLENDER_PLUGIN)
add_subdirectory(blender)
endif()

@ -411,7 +411,7 @@ void BVH::pack_instances(size_t nodes_size)
size_t nsize_bbox = (use_qbvh)? nsize-2: nsize-1;
int4 *bvh_nodes = &bvh->pack.nodes[0];
size_t bvh_nodes_size = bvh->pack.nodes.size();
int *bvh_is_leaf = &bvh->pack.is_leaf[0];
int *bvh_is_leaf = (bvh->pack.is_leaf.size() != 0) ? &bvh->pack.is_leaf[0] : NULL;
for(size_t i = 0, j = 0; i < bvh_nodes_size; i+=nsize, j++) {
memcpy(pack_nodes + pack_nodes_offset, bvh_nodes + i, nsize_bbox*sizeof(int4));
@ -419,7 +419,7 @@ void BVH::pack_instances(size_t nodes_size)
/* modify offsets into arrays */
int4 data = bvh_nodes[i + nsize_bbox];
if(bvh_is_leaf[j]) {
if(bvh_is_leaf && bvh_is_leaf[j]) {
data.x += tri_offset;
data.y += tri_offset;
}

@ -1150,7 +1150,7 @@ GHOST_TSuccess GHOST_WindowCocoa::installDrawingContext(GHOST_TDrawingContextTyp
/******* Multithreaded opengl code : uncomment for enabling
cglCtx = (CGLContextObj)[tmpOpenGLContext CGLContextObj];
if (CGLEnable(cglCtx, kCGLCEMPEngine) == kCGLNoError)
printf("\nSwitched openGL to multithreaded mode");
printf("\nSwitched openGL to multithreaded mode\n");
*/
if (!s_firstOpenGLcontext) s_firstOpenGLcontext = tmpOpenGLContext;

@ -92,7 +92,7 @@ extern "C" {
/**
* Duplicates a block of memory, and returns a pointer to the
* newly allocated block. */
void *MEM_dupallocN(void *vmemh)
void *MEM_dupallocN(const void *vmemh)
#if MEM_GNU_ATTRIBUTES
__attribute__((warn_unused_result))
#endif

@ -248,12 +248,12 @@ size_t MEM_allocN_len(const void *vmemh)
}
}
void *MEM_dupallocN(void *vmemh)
void *MEM_dupallocN(const void *vmemh)
{
void *newp = NULL;
if (vmemh) {
MemHead *memh = vmemh;
const MemHead *memh = vmemh;
memh--;
#ifndef DEBUG_MEMDUPLINAME

@ -275,6 +275,7 @@ def enable(module_name, default_set=True, persistent=False):
try:
mod.register()
except:
print("Exception in module register(): %r" % getattr(mod, "__file__", module_name))
handle_error()
del sys.modules[module_name]
return None
@ -316,6 +317,7 @@ def disable(module_name, default_set=True):
try:
mod.unregister()
except:
print("Exception in module unregister(): %r" % getattr(mod, "__file__", module_name))
import traceback
traceback.print_exc()
else:

@ -329,6 +329,7 @@ dict_uimsgs = {
"bweight",
"colorband",
"datablock", "datablocks",
"despeckle",
"dopesheet",
"dupliface", "duplifaces",
"dupliframe", "dupliframes",

@ -86,6 +86,8 @@ def read_blend_rend_chunk(path):
scenes.append((start_frame, end_frame, scene_name))
blendfile.close()
return scenes

@ -33,6 +33,9 @@ __all__ = (
"refresh_script_paths",
"register_class",
"register_module",
"register_manual_map",
"unregister_manual_map",
"manual_map",
"resource_path",
"script_path_user",
"script_path_pref",
@ -56,7 +59,6 @@ import addon_utils as _addon_utils
_script_module_dirs = "startup", "modules"
def _test_import(module_name, loaded_modules):
use_time = _bpy.app.debug_python
@ -595,3 +597,40 @@ def unregister_module(module, verbose=False):
traceback.print_exc()
if verbose:
print("done.\n")
# -----------------------------------------------------------------------------
# Manual lookups, each function has to return a basepath and a sequence
# of...
# we start with the built-in default mapping
def _blender_default_map():
import sys
import rna_wiki_reference as ref_mod
ret = (ref_mod.url_manual_prefix, ref_mod.url_manual_mapping)
# avoid storing in memory
del sys.modules["rna_wiki_reference"]
return ret
# hooks for doc lookups
_manual_map = [_blender_default_map]
def register_manual_map(manual_hook):
_manual_map.append(manual_hook)
def unregister_manual_map(manual_hook):
_manual_map.remove(manual_hook)
def manual_map():
# reverse so default is called last
for cb in reversed(_manual_map):
try:
prefix, url_manual_mapping = cb()
except:
print("Error calling %r" % cb)
import traceback
traceback.print_exc()
continue
yield prefix, url_manual_mapping

@ -181,6 +181,9 @@ def bake_action(frame_start,
while pbone.constraints:
pbone.constraints.remove(pbone.constraints[0])
# create compatible eulers
euler_prev = None
for f in frame_range:
f_step = (f - frame_start) // frame_step
matrix = pose_info[f_step][name]["matrix_key"]
@ -198,8 +201,19 @@ def bake_action(frame_start,
elif rotation_mode == 'AXIS_ANGLE':
pbone.keyframe_insert("rotation_axis_angle", -1, f, name)
else: # euler, XYZ, ZXY etc
if euler_prev is not None:
euler = pbone.rotation_euler.copy()
euler.make_compatible(euler_prev)
pbone.rotation_euler = euler
euler_prev = euler
del euler
pbone.keyframe_insert("rotation_euler", -1, f, name)
if euler_prev is None:
euler_prev = pbone.rotation_euler.copy()
pbone.keyframe_insert("scale", -1, f, name)
# object. TODO. multiple objects
@ -208,6 +222,9 @@ def bake_action(frame_start,
while obj.constraints:
obj.constraints.remove(obj.constraints[0])
# create compatible eulers
euler_prev = None
for f in frame_range:
matrix = obj_info[(f - frame_start) // frame_step]["matrix_key"]
obj.matrix_local = matrix
@ -221,8 +238,18 @@ def bake_action(frame_start,
elif rotation_mode == 'AXIS_ANGLE':
obj.keyframe_insert("rotation_axis_angle", -1, f)
else: # euler, XYZ, ZXY etc
if euler_prev is not None:
euler = obj.rotation_euler.copy()
euler.make_compatible(euler_prev)
obj.rotation_euler = euler
euler_prev = euler
del euler
obj.keyframe_insert("rotation_euler", -1, f)
if euler_prev is None:
euler_prev = obj.rotation_euler.copy()
obj.keyframe_insert("scale", -1, f)
scene.frame_set(frame_back)

@ -290,6 +290,40 @@ def autocomplete(context):
return {'FINISHED'}
def copy_as_script(context):
sc = context.space_data
lines = [
"import bpy",
"import bpy.context as C",
"import bpy.data as D",
"from mathutils import *",
"from math import *",
"",
]
for line in sc.scrollback:
text = line.body
type = line.type
if type == 'INFO': # ignore autocomp.
continue
if type == 'INPUT':
if text.startswith(PROMPT):
text = text[len(PROMPT):]
elif text.startswith(PROMPT_MULTI):
text = text[len(PROMPT_MULTI):]
elif type == 'OUTPUT':
text = "#~ " + text
elif type == 'ERROR':
text = "#! " + text
lines.append(text)
context.window_manager.clipboard = "\n".join(lines)
return {'FINISHED'}
def banner(context):
sc = context.space_data
version_string = sys.version.strip().replace('\n', ' ')

@ -99,11 +99,11 @@ def rna2xml(fw=print_ln,
subvalue = getattr(value, prop)
subvalue_type = type(subvalue)
if subvalue_type in (int, bool, float):
if subvalue_type in {int, bool, float}:
node_attrs.append("%s=\"%s\"" % (prop, number_to_str(subvalue, subvalue_type)))
elif subvalue_type is str:
node_attrs.append("%s=%s" % (prop, quoteattr(subvalue)))
elif subvalue_type == set:
elif subvalue_type is set:
node_attrs.append("%s=%s" % (prop, quoteattr("{" + ",".join(list(subvalue)) + "}")))
elif subvalue is None:
node_attrs.append("%s=\"NONE\"" % prop)
@ -137,7 +137,7 @@ def rna2xml(fw=print_ln,
# default
def str_recursive(s):
subsubvalue_type = type(s)
if subsubvalue_type in (int, float, bool):
if subsubvalue_type in {int, float, bool}:
return number_to_str(s, subsubvalue_type)
else:
return " ".join([str_recursive(si) for si in s])

@ -67,6 +67,25 @@ class ConsoleAutocomplete(Operator):
return {'FINISHED'}
class ConsoleCopyAsScript(Operator):
"""Copy the console contents for use in a script"""
bl_idname = "console.copy_as_script"
bl_label = "Copy to Clipboard (as script)"
def execute(self, context):
sc = context.space_data
module = _lang_module_get(sc)
copy_as_script = getattr(module, "copy_as_script", None)
if copy_as_script:
return copy_as_script(context)
else:
print("Error: copy_as_script - not found for %r" %
sc.language)
return {'FINISHED'}
class ConsoleBanner(Operator):
"""Print a message when the terminal initializes"""
bl_idname = "console.banner"

@ -790,7 +790,7 @@ class WM_OT_path_open(Operator):
return {'CANCELLED'}
if sys.platform[:3] == "win":
subprocess.Popen(["start", filepath], shell=True)
os.startfile(filepath)
elif sys.platform == "darwin":
subprocess.Popen(["open", filepath])
else:
@ -862,26 +862,24 @@ class WM_OT_doc_view_manual(Operator):
if rna_id is None:
return {'PASS_THROUGH'}
import rna_wiki_reference
rna_ref = self._find_reference(rna_id, rna_wiki_reference.url_manual_mapping)
url = None
if rna_ref is None:
self.report({'WARNING'}, "No reference available '%s', "
"Update info in %r" %
(self.doc_id, rna_wiki_reference.__file__))
for prefix, url_manual_mapping in bpy.utils.manual_map():
rna_ref = self._find_reference(rna_id, url_manual_mapping)
if rna_ref is not None:
url = prefix + rna_ref
break
import sys
del sys.modules["rna_wiki_reference"]
if rna_ref is None:
if url is None:
self.report({'WARNING'}, "No reference available %r, "
"Update info in 'rna_wiki_reference.py' "
" or callback to bpy.utils.manual_map()" %
self.doc_id)
return {'CANCELLED'}
else:
url = rna_wiki_reference.url_manual_prefix + rna_ref
import webbrowser
webbrowser.open(url)
return {'FINISHED'}
import webbrowser
webbrowser.open(url)
return {'FINISHED'}
class WM_OT_doc_view(Operator):

@ -121,6 +121,7 @@ class MASK_PT_spline():
spline = mask.layers.active.splines.active
col = layout.column()
col.prop(spline, "offset_mode")
col.prop(spline, "weight_interpolation")
row = col.row()

@ -849,6 +849,7 @@ class PARTICLE_PT_render(ParticleButtonsPanel, Panel):
sub = col.row()
sub.prop(part, "use_global_dupli")
sub.prop(part, "use_rotation_dupli")
sub.prop(part, "use_scale_dupli")
elif part.render_type == 'GROUP':
col.prop(part, "dupli_group")
split = layout.split()
@ -865,6 +866,7 @@ class PARTICLE_PT_render(ParticleButtonsPanel, Panel):
sub.active = (part.use_whole_group is False)
sub.prop(part, "use_global_dupli")
sub.prop(part, "use_rotation_dupli")
sub.prop(part, "use_scale_dupli")
if part.use_group_count and not part.use_whole_group:
row = layout.row()

@ -51,6 +51,7 @@ class CONSOLE_MT_console(Menu):
layout.separator()
layout.operator("console.copy_as_script")
layout.operator("console.copy")
layout.operator("console.paste")
layout.menu("CONSOLE_MT_language")

@ -774,7 +774,7 @@ class IMAGE_PT_paint_curve(BrushButtonsPanel, Panel):
toolsettings = context.tool_settings.image_paint
brush = toolsettings.brush
layout.template_curve_mapping(brush, "curve")
layout.template_curve_mapping(brush, "curve", type='COLOR')
row = layout.row(align=True)
row.operator("brush.curve_preset", icon='SMOOTHCURVE', text="").shape = 'SMOOTH'

@ -28,6 +28,29 @@ def act_strip(context):
return None
def draw_color_balance(layout, color_balance):
col = layout.column()
col.label(text="Lift:")
col.template_color_wheel(color_balance, "lift", value_slider=True, cubic=True)
row = col.row()
row.prop(color_balance, "lift", text="")
row.prop(color_balance, "invert_lift", text="Inverse")
col = layout.column()
col.label(text="Gamma:")
col.template_color_wheel(color_balance, "gamma", value_slider=True, lock_luminosity=True, cubic=True)
row = col.row()
row.prop(color_balance, "gamma", text="")
row.prop(color_balance, "invert_gamma", text="Inverse")
col = layout.column()
col.label(text="Gain:")
col.template_color_wheel(color_balance, "gain", value_slider=True, lock_luminosity=True, cubic=True)
row = col.row()
row.prop(color_balance, "gain", text="")
row.prop(color_balance, "invert_gain", text="Inverse")
class SEQUENCER_HT_header(Header):
bl_space_type = 'SEQUENCE_EDITOR'
@ -442,7 +465,7 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel):
if strip.is_supports_mask:
col = layout.column()
col.prop_search(strip, "input_mask", sequencer, "sequences")
col.prop_search(strip, "input_mask_strip", sequencer, "sequences", text="Mask")
if strip.type == 'COLOR':
layout.prop(strip, "color")
@ -772,26 +795,7 @@ class SEQUENCER_PT_filter(SequencerButtonsPanel, Panel):
layout.prop(strip, "use_color_balance")
if strip.use_color_balance and strip.color_balance: # TODO - need to add this somehow
col = layout.column()
col.label(text="Lift:")
col.template_color_wheel(strip.color_balance, "lift", value_slider=True, cubic=True)
row = col.row()
row.prop(strip.color_balance, "lift", text="")
row.prop(strip.color_balance, "invert_lift", text="Inverse")
col = layout.column()
col.label(text="Gamma:")
col.template_color_wheel(strip.color_balance, "gamma", value_slider=True, lock_luminosity=True, cubic=True)
row = col.row()
row.prop(strip.color_balance, "gamma", text="")
row.prop(strip.color_balance, "invert_gamma", text="Inverse")
col = layout.column()
col.label(text="Gain:")
col.template_color_wheel(strip.color_balance, "gain", value_slider=True, lock_luminosity=True, cubic=True)
row = col.row()
row.prop(strip.color_balance, "gain", text="")
row.prop(strip.color_balance, "invert_gain", text="Inverse")
draw_color_balance(layout, strip.color_balance)
class SEQUENCER_PT_proxy(SequencerButtonsPanel, Panel):
@ -878,5 +882,59 @@ class SEQUENCER_PT_view(SequencerButtonsPanel_Output, Panel):
col.prop(st, "show_separate_color")
col.prop(st, "proxy_render_size")
class SEQUENCER_PT_modifiers(SequencerButtonsPanel, Panel):
bl_label = "Modifiers"
def draw(self, context):
layout = self.layout
strip = act_strip(context)
sequencer = context.scene.sequence_editor
layout.operator_menu_enum("sequencer.strip_modifier_add", "type")
for mod in strip.modifiers:
box = layout.box()
row = box.row()
row.prop(mod, "show_expanded", text="", emboss=False)
row.prop(mod, "name", text="")
row.prop(mod, "mute", text="")
sub = row.row(align=True)
props = sub.operator("sequencer.strip_modifier_move", text="", icon='TRIA_UP')
props.name = mod.name
props.direction = 'UP'
props = sub.operator("sequencer.strip_modifier_move", text="", icon='TRIA_DOWN')
props.name = mod.name
props.direction = 'DOWN'
props = row.operator("sequencer.strip_modifier_remove", text="", icon='X', emboss=False)
props.name = mod.name
if mod.show_expanded:
row = box.row()
row.prop(mod, "input_mask_type", expand=True)
if mod.input_mask_type == 'STRIP':
box.prop_search(mod, "input_mask_strip", sequencer, "sequences", text="Mask")
else:
box.prop(mod, "input_mask_id")
if mod.type == 'COLOR_BALANCE':
box.prop(mod, "color_multiply")
draw_color_balance(box, mod.color_balance)
elif mod.type == 'CURVES':
box.template_curve_mapping(mod, "curve_mapping", type='COLOR')
elif mod.type == 'HUE_CORRECT':
box.template_curve_mapping(mod, "curve_mapping", type='HUE')
elif mod.type == 'BRIGHT_CONTRAST':
col = box.column()
col.prop(mod, "bright")
col.prop(mod, "contrast")
if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)

@ -858,6 +858,7 @@ class USERPREF_MT_ndof_settings(Menu):
layout.separator()
layout.prop(input_prefs, "ndof_sensitivity")
layout.prop(input_prefs, "ndof_orbit_sensitivity")
if context.space_data.type == 'VIEW_3D':
layout.separator()
@ -865,11 +866,10 @@ class USERPREF_MT_ndof_settings(Menu):
layout.separator()
layout.label(text="Orbit options")
if input_prefs.view_rotate_method == 'TRACKBALL':
layout.prop(input_prefs, "ndof_roll_invert_axis")
layout.prop(input_prefs, "ndof_turntable")
layout.prop(input_prefs, "ndof_roll_invert_axis")
layout.prop(input_prefs, "ndof_tilt_invert_axis")
layout.prop(input_prefs, "ndof_rotate_invert_axis")
layout.prop(input_prefs, "ndof_zoom_invert")
layout.separator()
layout.label(text="Pan options")
@ -878,6 +878,7 @@ class USERPREF_MT_ndof_settings(Menu):
layout.prop(input_prefs, "ndof_panz_invert_axis")
layout.label(text="Zoom options")
layout.prop(input_prefs, "ndof_zoom_invert")
layout.prop(input_prefs, "ndof_zoom_updown")
layout.separator()

@ -1182,7 +1182,7 @@ class VIEW3D_MT_hook(Menu):
layout = self.layout
layout.operator_context = 'EXEC_AREA'
layout.operator("object.hook_add_newob")
layout.operator("object.hook_add_selob")
layout.operator("object.hook_add_selob").use_bone = False
layout.operator("object.hook_add_selob", text="Hook to Selected Object Bone").use_bone = True
if [mod.type == 'HOOK' for mod in context.active_object.modifiers]:

@ -68,13 +68,23 @@ def add_object_button(self, context):
icon='PLUGIN')
# This allows you to right click on a button and link to the manual
def add_object_manual_map():
url_manual_prefix = "http://wiki.blender.org/index.php/Doc:2.6/Manual/"
url_manual_mapping = (
("bpy.ops.mesh.add_object", "Modeling/Objects"),
)
return url_manual_prefix, url_manual_mapping
def register():
bpy.utils.register_class(OBJECT_OT_add_object)
bpy.utils.register_manual_map(add_object_manual_map)
bpy.types.INFO_MT_mesh_add.append(add_object_button)
def unregister():
bpy.utils.unregister_class(OBJECT_OT_add_object)
bpy.utils.unregister_manual_map(add_object_manual_map)
bpy.types.INFO_MT_mesh_add.remove(add_object_button)

@ -78,9 +78,9 @@ class AddBox(bpy.types.Operator):
def execute(self, context):
verts_loc, faces = add_box(self.width,
self.height,
self.depth,
)
self.height,
self.depth,
)
mesh = bpy.data.meshes.new("Box")

@ -43,7 +43,10 @@
#include "BKE_utildefines.h"
#include "BLI_blenlib.h"
#include "BLI_fileops.h"
#include "BLI_listbase.h"
#include "BLI_path_util.h"
#include "BLI_string.h"
#include "BIF_gl.h"

@ -43,10 +43,12 @@
#include "DNA_vec_types.h"
#include "BLI_blenlib.h"
#include "BLI_linklist.h" /* linknode */
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_rect.h"
#include "BLI_string.h"
#include "BLI_string_utf8.h"
#include "BLI_linklist.h" /* linknode */
#include "BIF_gl.h"
#include "BLF_api.h"
@ -152,7 +154,7 @@ static void blf_font_ensure_ascii_table(FontBLF *font)
_kern_mode, \
&(_delta)) == 0) \
{ \
_pen_x += delta.x >> 6; \
_pen_x += _delta.x >> 6; \
} \
} \
} (void)0
@ -229,9 +231,9 @@ void blf_font_buffer(FontBLF *font, const char *str)
FontBufInfoBLF *buf_info = &font->buf_info;
float b_col_float[4];
const unsigned char b_col_char[4] = {buf_info->col[0] * 255,
buf_info->col[1] * 255,
buf_info->col[2] * 255,
buf_info->col[3] * 255};
buf_info->col[1] * 255,
buf_info->col[2] * 255,
buf_info->col[3] * 255};
unsigned char *cbuf;
int chx, chy;
@ -242,7 +244,7 @@ void blf_font_buffer(FontBLF *font, const char *str)
blf_font_ensure_ascii_table(font);
/* another buffer spesific call for color conversion */
/* another buffer specific call for color conversion */
if (buf_info->do_color_management) {
srgb_to_linearrgb_v4(b_col_float, buf_info->col);
}
@ -425,8 +427,8 @@ void blf_font_width_and_height(FontBLF *font, const char *str, float *width, flo
}
blf_font_boundbox(font, str, &box);
*width = ((box.xmax - box.xmin) * xa);
*height = ((box.ymax - box.ymin) * ya);
*width = (BLI_RCT_SIZE_X(&box) * xa);
*height = (BLI_RCT_SIZE_Y(&box) * ya);
}
float blf_font_width(FontBLF *font, const char *str)
@ -440,7 +442,7 @@ float blf_font_width(FontBLF *font, const char *str)
xa = 1.0f;
blf_font_boundbox(font, str, &box);
return (box.xmax - box.xmin) * xa;
return BLI_RCT_SIZE_X(&box) * xa;
}
float blf_font_height(FontBLF *font, const char *str)
@ -454,7 +456,7 @@ float blf_font_height(FontBLF *font, const char *str)
ya = 1.0f;
blf_font_boundbox(font, str, &box);
return (box.ymax - box.ymin) * ya;
return BLI_RCT_SIZE_Y(&box) * ya;
}
float blf_font_fixed_width(FontBLF *font)

@ -46,7 +46,8 @@
#include "DNA_vec_types.h"
#include "DNA_userdef_types.h"
#include "BLI_blenlib.h"
#include "BLI_listbase.h"
#include "BLI_rect.h"
#include "BIF_gl.h"
#include "BLF_api.h"
@ -314,13 +315,14 @@ static void blf_texture_draw(float uv[2][2], float dx, float y1, float dx1, floa
static void blf_texture5_draw(const float shadow_col[4], float uv[2][2], float x1, float y1, float x2, float y2)
{
float soft[25] = {1 / 60.0f, 1 / 60.0f, 2 / 60.0f, 1 / 60.0f, 1 / 60.0f,
1 / 60.0f, 3 / 60.0f, 5 / 60.0f, 3 / 60.0f, 1 / 60.0f,
2 / 60.0f, 5 / 60.0f, 8 / 60.0f, 5 / 60.0f, 2 / 60.0f,
1 / 60.0f, 3 / 60.0f, 5 / 60.0f, 3 / 60.0f, 1 / 60.0f,
1 / 60.0f, 1 / 60.0f, 2 / 60.0f, 1 / 60.0f, 1 / 60.0f};
const float soft[25] = {1 / 60.0f, 1 / 60.0f, 2 / 60.0f, 1 / 60.0f, 1 / 60.0f,
1 / 60.0f, 3 / 60.0f, 5 / 60.0f, 3 / 60.0f, 1 / 60.0f,
2 / 60.0f, 5 / 60.0f, 8 / 60.0f, 5 / 60.0f, 2 / 60.0f,
1 / 60.0f, 3 / 60.0f, 5 / 60.0f, 3 / 60.0f, 1 / 60.0f,
1 / 60.0f, 1 / 60.0f, 2 / 60.0f, 1 / 60.0f, 1 / 60.0f};
float color[4], *fp = soft;
const float *fp = soft;
float color[4];
int dx, dy;
color[0] = shadow_col[0];
@ -340,11 +342,12 @@ static void blf_texture5_draw(const float shadow_col[4], float uv[2][2], float x
static void blf_texture3_draw(const float shadow_col[4], float uv[2][2], float x1, float y1, float x2, float y2)
{
float soft[9] = {1 / 16.0f, 2 / 16.0f, 1 / 16.0f,
2 / 16.0f, 4 / 16.0f, 2 / 16.0f,
1 / 16.0f, 2 / 16.0f, 1 / 16.0f};
const float soft[9] = {1 / 16.0f, 2 / 16.0f, 1 / 16.0f,
2 / 16.0f, 4 / 16.0f, 2 / 16.0f,
1 / 16.0f, 2 / 16.0f, 1 / 16.0f};
float color[4], *fp = soft;
const float *fp = soft;
float color[4];
int dx, dy;
color[0] = shadow_col[0];
@ -412,7 +415,7 @@ int blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y)
g->uv[1][1] = ((float)(g->yoff + g->height)) / ((float)gc->p2_height);
/* update the x offset for the next glyph. */
gc->x_offs += (int)(g->box.xmax - g->box.xmin + gc->pad);
gc->x_offs += (int)(BLI_RCT_SIZE_X(&g->box) + gc->pad);
gc->rem_glyphs--;
g->build_tex = 1;
@ -434,13 +437,13 @@ int blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y)
y2 = y + g->pos_y - g->height;
if (font->flags & BLF_CLIPPING) {
if (!BLI_in_rctf(&font->clip_rec, dx + font->pos[0], y1 + font->pos[1]))
if (!BLI_rctf_isect_pt(&font->clip_rec, dx + font->pos[0], y1 + font->pos[1]))
return 0;
if (!BLI_in_rctf(&font->clip_rec, dx + font->pos[0], y2 + font->pos[1]))
if (!BLI_rctf_isect_pt(&font->clip_rec, dx + font->pos[0], y2 + font->pos[1]))
return 0;
if (!BLI_in_rctf(&font->clip_rec, dx1 + font->pos[0], y2 + font->pos[1]))
if (!BLI_rctf_isect_pt(&font->clip_rec, dx1 + font->pos[0], y2 + font->pos[1]))
return 0;
if (!BLI_in_rctf(&font->clip_rec, dx1 + font->pos[0], y1 + font->pos[1]))
if (!BLI_rctf_isect_pt(&font->clip_rec, dx1 + font->pos[0], y1 + font->pos[1]))
return 0;
}

@ -47,15 +47,19 @@ struct rctf;
# define DO_INLINE static inline
#endif
void curvemapping_set_defaults(struct CurveMapping *cumap, int tot, float minx, float miny, float maxx, float maxy);
struct CurveMapping *curvemapping_add(int tot, float minx, float miny, float maxx, float maxy);
void curvemapping_free_data(struct CurveMapping *cumap);
void curvemapping_free(struct CurveMapping *cumap);
void curvemapping_copy_data(struct CurveMapping *target, struct CurveMapping *cumap);
struct CurveMapping *curvemapping_copy(struct CurveMapping *cumap);
void curvemapping_set_black_white_ex(const float black[3], const float white[3], float r_bwmul[3]);
void curvemapping_set_black_white(struct CurveMapping *cumap, const float black[3], const float white[3]);
#define CURVEMAP_SLOPE_NEGATIVE 0
#define CURVEMAP_SLOPE_POSITIVE 1
void curvemap_reset(struct CurveMap *cuma, struct rctf *clipr, int preset, int slope);
void curvemap_remove(struct CurveMap *cuma, int flag);
void curvemap_remove(struct CurveMap *cuma, const short flag);
void curvemap_remove_point(struct CurveMap *cuma, struct CurveMapPoint *cmp);
struct CurveMapPoint *curvemap_insert(struct CurveMap *cuma, float x, float y);
void curvemap_sethandle(struct CurveMap *cuma, int type);
@ -63,22 +67,31 @@ void curvemap_sethandle(struct CurveMap *cuma, int type);
void curvemapping_changed(struct CurveMapping *cumap, int rem_doubles);
void curvemapping_changed_all(struct CurveMapping *cumap);
/* call before _all_ evaluation functions */
void curvemapping_initialize(struct CurveMapping *cumap);
/* keep these (const CurveMap) - to help with thread safety */
/* single curve, no table check */
float curvemap_evaluateF(struct CurveMap *cuma, float value);
float curvemap_evaluateF(const struct CurveMap *cuma, float value);
/* single curve, with table check */
float curvemapping_evaluateF(struct CurveMapping *cumap, int cur, float value);
void curvemapping_evaluate3F(struct CurveMapping *cumap, float vecout[3], const float vecin[3]);
void curvemapping_evaluateRGBF(struct CurveMapping *cumap, float vecout[3], const float vecin[3]);
void curvemapping_evaluate_premulRGBF(struct CurveMapping *cumap, float vecout[3], const float vecin[3]);
float curvemapping_evaluateF(const struct CurveMapping *cumap, int cur, float value);
void curvemapping_evaluate3F(const struct CurveMapping *cumap, float vecout[3], const float vecin[3]);
void curvemapping_evaluateRGBF(const struct CurveMapping *cumap, float vecout[3], const float vecin[3]);
void curvemapping_evaluate_premulRGB(const struct CurveMapping *cumap, unsigned char vecout_byte[3], const unsigned char vecin_byte[3]);
void curvemapping_evaluate_premulRGBF_ex(const struct CurveMapping *cumap, float vecout[3], const float vecin[3],
const float black[3], const float bwmul[3]);
void curvemapping_evaluate_premulRGBF(const struct CurveMapping *cumap, float vecout[3], const float vecin[3]);
int curvemapping_RGBA_does_something(const struct CurveMapping *cumap);
void curvemapping_table_RGBA(const struct CurveMapping *cumap, float **array, int *size);
/* non-const, these modify the curve */
void curvemapping_do_ibuf(struct CurveMapping *cumap, struct ImBuf *ibuf);
void curvemapping_premultiply(struct CurveMapping *cumap, int restore);
int curvemapping_RGBA_does_something(struct CurveMapping *cumap);
void curvemapping_initialize(struct CurveMapping *cumap);
void curvemapping_table_RGBA(struct CurveMapping *cumap, float **array, int *size);
void BKE_histogram_update_sample_line(struct Histogram *hist, struct ImBuf *ibuf, const short use_color_management);
void scopes_update(struct Scopes *scopes, struct ImBuf *ibuf, int use_color_management);
void scopes_free(struct Scopes *scopes);
void scopes_new(struct Scopes *scopes);
#endif

@ -88,7 +88,7 @@ typedef struct bContextStore {
int used;
} bContextStore;
/* for the conrtext's rna mode enum
/* for the context's rna mode enum
* keep aligned with data_mode_strings in context.c */
enum {
CTX_MODE_EDIT_MESH = 0,
@ -174,7 +174,7 @@ void CTX_wm_operator_poll_msg_set(struct bContext *C, const char *msg);
*
* - listbases consist of CollectionPointerLink items and must be
* freed with BLI_freelistN!
* - the dir listbase consits of LinkData items */
* - the dir listbase consists of LinkData items */
/* data type, needed so we can tell between a NULL pointer and an empty list */
enum {

@ -76,13 +76,9 @@ void BKE_vfont_builtin_register(void *mem, int size);
void BKE_vfont_free_data(struct VFont *vfont);
void BKE_vfont_free(struct VFont *sc);
void BKE_vfont_free_global_ttf(void);
struct VFont *BKE_vfont_builtin_get(void);
struct VFont *BKE_vfont_load(struct Main *bmain, const char *name);
struct TmpFont *BKE_vfont_tmpfont_find(struct VFont *vfont);
void BKE_vfont_tmpfont_remove(struct VFont *vfont);
struct CharTrans *BKE_vfont_to_curve(struct Main *bmain, struct Scene *scene, struct Object *ob, int mode);
int BKE_vfont_select_get(struct Object *ob, int *start, int *end);

@ -19,7 +19,8 @@
* All rights reserved.
*
* Contributor(s): Blender Foundation,
* Sergey Sharybin
* Sergey Sharybin,
* Campbell Barton
*
* ***** END GPL LICENSE BLOCK *****
*/
@ -63,27 +64,12 @@ void BKE_mask_layer_copy_list(struct ListBase *masklayers_new, struct ListBase *
/* splines */
struct MaskSpline *BKE_mask_spline_add(struct MaskLayer *masklay);
unsigned int BKE_mask_spline_resolution(struct MaskSpline *spline, int width, int height);
unsigned int BKE_mask_spline_feather_resolution(struct MaskSpline *spline, int width, int height);
int BKE_mask_spline_differentiate_calc_total(const struct MaskSpline *spline, const unsigned int resol);
float (*BKE_mask_spline_differentiate(struct MaskSpline *spline, int *tot_diff_point))[2];
float (*BKE_mask_spline_feather_differentiated_points(struct MaskSpline *spline, int *tot_feather_point))[2];
float (*BKE_mask_spline_differentiate_with_resolution_ex(struct MaskSpline *spline, int *tot_diff_point,
const unsigned int resol))[2];
float (*BKE_mask_spline_differentiate_with_resolution(struct MaskSpline *spline, int width, int height, int *tot_diff_point))[2];
float (*BKE_mask_spline_feather_differentiated_points_with_resolution_ex(struct MaskSpline *spline, int *tot_feather_point,
const unsigned int resol))[2];
float (*BKE_mask_spline_feather_differentiated_points_with_resolution(struct MaskSpline *spline, int width, int height, int *tot_feather_point))[2];
float (*BKE_mask_spline_feather_points(struct MaskSpline *spline, int *tot_feather_point))[2];
void BKE_mask_point_direction_switch(struct MaskSplinePoint *point);
void BKE_mask_spline_direction_switch(struct MaskLayer *masklay, struct MaskSpline *spline);
struct BezTriple *BKE_mask_spline_point_next_bezt(struct MaskSpline *spline, struct MaskSplinePoint *points_array,
struct MaskSplinePoint *point);
typedef enum {
MASK_PROJ_NEG = -1,
MASK_PROJ_ANY = 0,
@ -98,19 +84,6 @@ void BKE_mask_point_handle(struct MaskSplinePoint *point, float handle[2]);
void BKE_mask_point_set_handle(struct MaskSplinePoint *point, float loc[2], int keep_direction,
float orig_handle[2], float orig_vec[3][3]);
float *BKE_mask_point_segment_diff(struct MaskSpline *spline, struct MaskSplinePoint *point,
unsigned int *tot_diff_point);
float *BKE_mask_point_segment_feather_diff(struct MaskSpline *spline, struct MaskSplinePoint *point,
unsigned int *tot_feather_point);
float *BKE_mask_point_segment_diff_with_resolution(struct MaskSpline *spline, struct MaskSplinePoint *point,
int width, int height,
unsigned int *tot_diff_point);
float *BKE_mask_point_segment_feather_diff_with_resolution(struct MaskSpline *spline, struct MaskSplinePoint *point,
int width, int height,
unsigned int *tot_feather_point);
void BKE_mask_point_segment_co(struct MaskSpline *spline, struct MaskSplinePoint *point, float u, float co[2]);
void BKE_mask_point_normal(struct MaskSpline *spline, struct MaskSplinePoint *point,
float u, float n[2]);
@ -203,6 +176,39 @@ int BKE_mask_get_duration(struct Mask *mask);
#define MASK_RESOL_MAX 128
/* mask_evaluate.c */
unsigned int BKE_mask_spline_resolution(struct MaskSpline *spline, int width, int height);
unsigned int BKE_mask_spline_feather_resolution(struct MaskSpline *spline, int width, int height);
int BKE_mask_spline_differentiate_calc_total(const struct MaskSpline *spline, const unsigned int resol);
float (*BKE_mask_spline_differentiate(struct MaskSpline *spline, int *tot_diff_point))[2];
float (*BKE_mask_spline_feather_differentiated_points(struct MaskSpline *spline, int *tot_feather_point))[2];
float (*BKE_mask_spline_differentiate_with_resolution_ex(struct MaskSpline *spline, int *tot_diff_point,
const unsigned int resol))[2];
void BKE_mask_spline_feather_collapse_inner_loops(struct MaskSpline *spline, float (*feather_points)[2], const int tot_feather_point);
float (*BKE_mask_spline_differentiate_with_resolution(struct MaskSpline *spline, int width, int height, int *tot_diff_point))[2];
float (*BKE_mask_spline_feather_differentiated_points_with_resolution_ex(struct MaskSpline *spline, int *tot_feather_point,
const unsigned int resol, const int do_feather_isect))[2];
float (*BKE_mask_spline_feather_differentiated_points_with_resolution(struct MaskSpline *spline, int width, int height,
int *tot_feather_point, const int do_feather_isect))[2];
/* *** mask point functions which involve evaluation *** */
float (*BKE_mask_spline_feather_points(struct MaskSpline *spline, int *tot_feather_point))[2];
float *BKE_mask_point_segment_diff(struct MaskSpline *spline, struct MaskSplinePoint *point,
unsigned int *tot_diff_point);
float *BKE_mask_point_segment_feather_diff(struct MaskSpline *spline, struct MaskSplinePoint *point,
unsigned int *tot_feather_point);
float *BKE_mask_point_segment_diff_with_resolution(struct MaskSpline *spline, struct MaskSplinePoint *point,
int width, int height,
unsigned int *tot_diff_point);
float *BKE_mask_point_segment_feather_diff_with_resolution(struct MaskSpline *spline, struct MaskSplinePoint *point,
int width, int height,
unsigned int *tot_feather_point);
/* mask_rasterize.c */
struct MaskRasterHandle;
typedef struct MaskRasterHandle MaskRasterHandle;

@ -48,6 +48,7 @@ struct Scene;
void init_def_material(void);
void BKE_material_free(struct Material *sc);
void BKE_material_free_ex(struct Material *ma, int do_id_user);
void test_object_materials(struct ID *id);
void resize_object_material(struct Object *ob, const short totcol);
void init_material(struct Material *ma);

@ -57,8 +57,8 @@ float *BKE_mball_make_orco(struct Object *ob, struct ListBase *dispbase);
void BKE_mball_properties_copy(struct Scene *scene, struct Object *active_object);
int BKE_mball_minmax(struct MetaBall *mb, float min[3], float max[3]);
int BKE_mball_center_median(struct MetaBall *mb, float cent[3]);
int BKE_mball_center_bounds(struct MetaBall *mb, float cent[3]);
int BKE_mball_center_median(struct MetaBall *mb, float r_cent[3]);
int BKE_mball_center_bounds(struct MetaBall *mb, float r_cent[3]);
void BKE_mball_translate(struct MetaBall *mb, float offset[3]);
struct MetaElem *BKE_mball_element_add(struct MetaBall *mb, const int type);

@ -146,7 +146,7 @@ typedef struct bNodeType {
/// Additional parameters in the side panel.
void (*uifuncbut)(struct uiLayout *, struct bContext *C, struct PointerRNA *ptr);
/// Additional drawing on backdrop.
void (*uibackdropfunc)(struct SpaceNode* snode, struct ImBuf* backdrop, struct bNode* node, int x, int y);
void (*uibackdropfunc)(struct SpaceNode *snode, struct ImBuf *backdrop, struct bNode *node, int x, int y);
/// Draw a node socket. Default draws the input value button.
NodeSocketButtonFunction drawinputfunc;
@ -301,21 +301,29 @@ struct bNodeType *ntreeGetNodeType(struct bNodeTree *ntree);
struct bNodeSocketType *ntreeGetSocketType(int type);
struct bNodeTree *ntreeAddTree(const char *name, int type, int nodetype);
void ntreeInitTypes(struct bNodeTree *ntree);
void ntreeInitTypes(struct bNodeTree *ntree);
void ntreeFreeTree(struct bNodeTree *ntree);
/* copy/free funcs, need to manage ID users */
void ntreeFreeTree_ex(struct bNodeTree *ntree, const short do_id_user);
void ntreeFreeTree(struct bNodeTree *ntree);
struct bNodeTree *ntreeCopyTree_ex(struct bNodeTree *ntree, const short do_id_user);
struct bNodeTree *ntreeCopyTree(struct bNodeTree *ntree);
void ntreeSwitchID(struct bNodeTree *ntree, struct ID *sce_from, struct ID *sce_to);
void ntreeMakeLocal(struct bNodeTree *ntree);
int ntreeHasType(struct bNodeTree *ntree, int type);
void ntreeSwitchID_ex(struct bNodeTree *ntree, struct ID *sce_from, struct ID *sce_to, const short do_id_user);
void ntreeSwitchID(struct bNodeTree *ntree, struct ID *sce_from, struct ID *sce_to);
/* node->id user count */
void ntreeUserIncrefID(struct bNodeTree *ntree);
void ntreeUserDecrefID(struct bNodeTree *ntree);
void ntreeUpdateTree(struct bNodeTree *ntree);
void ntreeMakeLocal(struct bNodeTree *ntree);
int ntreeHasType(struct bNodeTree *ntree, int type);
void ntreeUpdateTree(struct bNodeTree *ntree);
/* XXX Currently each tree update call does call to ntreeVerifyNodes too.
* Some day this should be replaced by a decent depsgraph automatism!
*/
void ntreeVerifyNodes(struct Main *main, struct ID *id);
void ntreeVerifyNodes(struct Main *main, struct ID *id);
void ntreeGetDependencyList(struct bNodeTree *ntree, struct bNode ***deplist, int *totnodes);
void ntreeGetDependencyList(struct bNodeTree *ntree, struct bNode ***deplist, int *totnodes);
/* XXX old trees handle output flags automatically based on special output node types and last active selection.
* new tree types have a per-output socket flag to indicate the final output to use explicitly.
@ -388,6 +396,7 @@ void nodeSocketSetType(struct bNodeSocket *sock, int type);
/* Node Clipboard */
void BKE_node_clipboard_init(struct bNodeTree *ntree);
void BKE_node_clipboard_clear(void);
int BKE_node_clipboard_validate(void);
void BKE_node_clipboard_add_node(struct bNode *node);
void BKE_node_clipboard_add_link(struct bNodeLink *link);
const struct ListBase *BKE_node_clipboard_get_nodes(void);
@ -671,7 +680,8 @@ void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMateria
#define CMP_NODE_KEYINGSCREEN 269
#define CMP_NODE_KEYING 270
#define CMP_NODE_TRACKPOS 271
#define CMP_NODE_INPAINT 272
#define CMP_NODE_INPAINT 272
#define CMP_NODE_DESPECKLE 273
#define CMP_NODE_GLARE 301
#define CMP_NODE_TONEMAP 302

@ -43,6 +43,7 @@ struct ReportList;
struct VFont;
/* pack */
struct PackedFile *dupPackedFile(const struct PackedFile *pf_src);
struct PackedFile *newPackedFile(struct ReportList *reports, const char *filename, const char *relabase);
struct PackedFile *newPackedFileMemory(void *mem, int memlen);

@ -55,7 +55,7 @@ struct wmWindowManager;
#include "RNA_types.h"
/* spacetype has everything stored to get an editor working, it gets initialized via
* ED_spacetypes_init() in editors/area/spacetypes.c */
* ED_spacetypes_init() in editors/space_api/spacetypes.c */
/* an editor in Blender is a combined ScrArea + SpaceType + SpaceData */
#define BKE_ST_MAXNAME 64

@ -31,11 +31,14 @@
*/
struct bContext;
struct StripColorBalance;
struct Editing;
struct ImBuf;
struct Main;
struct Mask;
struct Scene;
struct Sequence;
struct SequenceModifierData;
struct Strip;
struct StripElem;
struct bSound;
@ -241,6 +244,11 @@ void BKE_sequencer_cache_put(SeqRenderData context, struct Sequence *seq, float
void BKE_sequencer_cache_cleanup_sequence(struct Sequence *seq);
struct ImBuf *BKE_sequencer_preprocessed_cache_get(SeqRenderData context, struct Sequence *seq, float cfra, seq_stripelem_ibuf_t type);
void BKE_sequencer_preprocessed_cache_put(SeqRenderData context, struct Sequence *seq, float cfra, seq_stripelem_ibuf_t type, struct ImBuf *ibuf);
void BKE_sequencer_preprocessed_cache_cleanup(void);
void BKE_sequencer_preprocessed_cache_cleanup_sequence(struct Sequence *seq);
/* **********************************************************************
* seqeffects.c
*
@ -289,6 +297,7 @@ int BKE_sequence_swap(struct Sequence *seq_a, struct Sequence *seq_b, const char
int BKE_sequence_check_depend(struct Sequence *seq, struct Sequence *cur);
void BKE_sequence_invalidate_cache(struct Scene *scene, struct Sequence *seq);
void BKE_sequence_invalidate_cache_for_modifier(struct Scene *scene, struct Sequence *seq);
void BKE_sequencer_update_sound_bounds_all(struct Scene *scene);
void BKE_sequencer_update_sound_bounds(struct Scene *scene, struct Sequence *seq);
@ -347,4 +356,48 @@ extern SequencerDrawView sequencer_view3d_cb;
extern ListBase seqbase_clipboard;
extern int seqbase_clipboard_frame;
/* modifiers */
typedef struct SequenceModifierTypeInfo {
/* default name for the modifier */
char name[64]; /* MAX_NAME */
/* DNA structure name used on load/save filed */
char struct_name[64]; /* MAX_NAME */
/* size of modifier data structure, used by allocation */
int struct_size;
/* data initialization */
void (*init_data) (struct SequenceModifierData *smd);
/* free data used by modifier,
* only modifier-specific data should be freed, modifier descriptor would
* be freed outside of this callback
*/
void (*free_data) (struct SequenceModifierData *smd);
/* copy data from one modifier to another */
void (*copy_data) (struct SequenceModifierData *smd, struct SequenceModifierData *target);
/* apply modifier on a given image buffer */
struct ImBuf *(*apply) (struct SequenceModifierData *smd, struct ImBuf *ibuf, struct ImBuf *mask);
} SequenceModifierTypeInfo;
struct SequenceModifierTypeInfo *BKE_sequence_modifier_type_info_get(int type);
struct SequenceModifierData *BKE_sequence_modifier_new(struct Sequence *seq, const char *name, int type);
int BKE_sequence_modifier_remove(struct Sequence *seq, struct SequenceModifierData *smd);
void BKE_sequence_modifier_clear(struct Sequence *seq);
void BKE_sequence_modifier_free(struct SequenceModifierData *smd);
void BKE_sequence_modifier_unique_name(struct Sequence *seq, struct SequenceModifierData *smd);
struct SequenceModifierData *BKE_sequence_modifier_find_by_name(struct Sequence *seq, char *name);
struct ImBuf *BKE_sequence_modifier_apply_stack(SeqRenderData context, struct Sequence *seq, struct ImBuf *ibuf, int cfra);
void BKE_sequence_modifier_list_copy(struct Sequence *seqn, struct Sequence *seq);
int BKE_sequence_supports_modifiers(struct Sequence *seq);
/* internal filters */
struct ImBuf *BKE_sequencer_render_mask_input(SeqRenderData context, int mask_input_type, struct Sequence *mask_sequence, struct Mask *mask_id, int cfra, int make_float);
void BKE_sequencer_color_balance_apply(struct StripColorBalance *cb, struct ImBuf *ibuf, float mul, short make_float, struct ImBuf *mask_input);
#endif /* __BKE_SEQUENCER_H__ */

@ -103,7 +103,7 @@ set(SRC
intern/lattice.c
intern/library.c
intern/linestyle.c
intern/mask_rasterize.c
intern/mask_evaluate.c intern/mask_rasterize.c
intern/mask.c
intern/material.c
intern/mball.c
@ -130,6 +130,7 @@ set(SRC
intern/script.c
intern/seqcache.c
intern/seqeffects.c
intern/seqmodifier.c
intern/sequencer.c
intern/shrinkwrap.c
intern/sketch.c

@ -1798,7 +1798,7 @@ static void ccgSubSurf__calcSubdivLevel(CCGSubSurf *ss,
if (seamEdges < 2 || seamEdges != v->numEdges)
seam = 0;
if (!v->numEdges) {
if (!v->numEdges || ss->meshIFC.simpleSubdiv) {
VertDataCopy(nCo, co, ss);
}
else if (_vert_isBoundary(v)) {
@ -2246,7 +2246,7 @@ static void ccgSubSurf__sync(CCGSubSurf *ss)
if (seamEdges < 2 || seamEdges != v->numEdges)
seam = 0;
if (!v->numEdges) {
if (!v->numEdges || ss->meshIFC.simpleSubdiv) {
VertDataCopy(nCo, co, ss);
}
else if (_vert_isBoundary(v)) {
@ -2827,6 +2827,11 @@ int ccgSubSurf_getGridLevelSize(const CCGSubSurf *ss, int level)
}
}
int ccgSubSurf_getSimpleSubdiv(const CCGSubSurf *ss)
{
return ss->meshIFC.simpleSubdiv;
}
/* Vert accessors */
CCGVertHDL ccgSubSurf_getVertVertHandle(CCGVert *v)

@ -17,6 +17,7 @@ typedef struct CCGMeshIFC {
int vertUserSize, edgeUserSize, faceUserSize;
int numLayers;
int vertDataSize;
int simpleSubdiv;
} CCGMeshIFC;
/***/
@ -91,6 +92,7 @@ int ccgSubSurf_getEdgeSize (const CCGSubSurf *ss);
int ccgSubSurf_getEdgeLevelSize (const CCGSubSurf *ss, int level);
int ccgSubSurf_getGridSize (const CCGSubSurf *ss);
int ccgSubSurf_getGridLevelSize (const CCGSubSurf *ss, int level);
int ccgSubSurf_getSimpleSubdiv (const CCGSubSurf *ss);
CCGVert* ccgSubSurf_getVert (CCGSubSurf *ss, CCGVertHDL v);
CCGVertHDL ccgSubSurf_getVertVertHandle (CCGVert *v);

@ -541,7 +541,7 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob)
CustomData_free(&me->pdata, me->totpoly);
/* ok, this should now use new CD shapekey data,
* which shouuld be fed through the modifier
* which should be fed through the modifier
* stack*/
if (tmp.totvert != me->totvert && !did_shapekeys && me->key) {
printf("%s: YEEK! this should be recoded! Shape key loss!: ID '%s'\n", __func__, tmp.id.name);
@ -1793,7 +1793,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
{
finaldm->recalcTessellation(finaldm);
}
/* Even if tessellation is not needed, some modifiers migh have modified CD layers
/* Even if tessellation is not needed, some modifiers might have modified CD layers
* (like mloopcol or mloopuv), hence we have to update those. */
else if (finaldm->dirty & DM_DIRTY_TESS_CDLAYERS) {
/* A tessellation already exists, it should always have a CD_POLYINDEX. */

@ -282,7 +282,7 @@ void animviz_get_object_motionpaths(Object *ob, ListBase *targets)
/* ........ */
/* Note on evaluation optimisations:
/* Note on evaluation optimizations:
* Optimisations currently used here play tricks with the depsgraph in order to try and
* evaluate as few objects as strictly necessary to get nicer performance under standard
* production conditions. For those people who really need the accurate version,
@ -323,7 +323,7 @@ static void motionpaths_calc_optimise_depsgraph(Scene *scene, ListBase *targets)
/* update scene for current frame */
static void motionpaths_calc_update_scene(Scene *scene)
{
#if 1 // 'production' optimisations always on
#if 1 // 'production' optimizations always on
Base *base, *last = NULL;
/* only stuff that moves or needs display still */
@ -431,7 +431,7 @@ void animviz_calc_motionpaths(Scene *scene, ListBase *targets)
if (efra <= sfra) return;
/* optimize the depsgraph for faster updates */
/* TODO: whether this is used should depend on some setting for the level of optimisations used */
/* TODO: whether this is used should depend on some setting for the level of optimizations used */
motionpaths_calc_optimise_depsgraph(scene, targets);
/* calculate path over requested range */
@ -1279,9 +1279,9 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
if (part->dup_group == NULL || part->dup_group->gobject.first == NULL)
return;
for (go = part->dup_group->gobject.first; go; go = go->next)
if (go->ob == par)
return;
if (BLI_findptr(&part->dup_group->gobject, par, offsetof(GroupObject, ob))) {
return;
}
}
/* if we have a hair particle system, use the path cache */
@ -1469,6 +1469,18 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
quat_to_mat4(obmat, q);
obmat[3][3] = 1.0f;
/* add scaling if requested */
if ((part->draw & PART_DRAW_NO_SCALE_OB) == 0)
mult_m4_m4m4(obmat, obmat, size_mat);
}
else if (part->draw & PART_DRAW_NO_SCALE_OB) {
/* remove scaling */
float size_mat[4][4], original_size[3];
mat4_to_size(original_size, obmat);
size_to_mat4(size_mat, original_size);
invert_m4(size_mat);
mult_m4_m4m4(obmat, obmat, size_mat);
}

@ -1463,7 +1463,7 @@ void vec_roll_to_mat3(const float vec[3], const float roll, float mat[][3])
*
* was 0.0000000000001, caused bug [#31333], smaller values give unstable
* roll when toggling editmode again...
* No good value here, trying 0.000000001 as best compromize. :/
* No good value here, trying 0.000000001 as best compromise. :/
*/
if (dot_v3v3(axis, axis) > 1.0e-9f) {
/* if nor is *not* a multiple of target ... */

@ -421,7 +421,7 @@ void BKE_brush_curve_preset(Brush *b, /*CurveMappingPreset*/ int preset)
b->curve->preset = preset;
curvemap_reset(cm, &b->curve->clipr, b->curve->preset, CURVEMAP_SLOPE_NEGATIVE);
curvemapping_changed(b->curve, 0);
curvemapping_changed(b->curve, FALSE);
}
int BKE_brush_texture_set_nr(Brush *brush, int nr)
@ -1253,7 +1253,9 @@ float BKE_brush_curve_strength_clamp(Brush *br, float p, const float len)
if (p >= len) return 0;
else p = p / len;
curvemapping_initialize(br->curve);
p = curvemapping_evaluateF(br->curve, 0, p);
if (p < 0.0f) p = 0.0f;
else if (p > 1.0f) p = 1.0f;
return p;
@ -1267,6 +1269,7 @@ float BKE_brush_curve_strength(Brush *br, float p, const float len)
else
p = p / len;
curvemapping_initialize(br->curve);
return curvemapping_evaluateF(br->curve, 0, p);
}

@ -56,13 +56,11 @@
/* ***************** operations on full struct ************* */
CurveMapping *curvemapping_add(int tot, float minx, float miny, float maxx, float maxy)
void curvemapping_set_defaults(CurveMapping *cumap, int tot, float minx, float miny, float maxx, float maxy)
{
CurveMapping *cumap;
int a;
float clipminx, clipminy, clipmaxx, clipmaxy;
cumap = MEM_callocN(sizeof(CurveMapping), "new curvemap");
cumap->flag = CUMA_DO_CLIP;
if (tot == 4) cumap->cur = 3; /* rhms, hack for 'col' curve? */
@ -89,58 +87,93 @@ CurveMapping *curvemapping_add(int tot, float minx, float miny, float maxx, floa
}
cumap->changed_timestamp = 0;
}
CurveMapping *curvemapping_add(int tot, float minx, float miny, float maxx, float maxy)
{
CurveMapping *cumap;
cumap = MEM_callocN(sizeof(CurveMapping), "new curvemap");
curvemapping_set_defaults(cumap, tot, minx, miny, maxx, maxy);
return cumap;
}
void curvemapping_free(CurveMapping *cumap)
void curvemapping_free_data(CurveMapping *cumap)
{
int a;
if (cumap) {
for (a = 0; a < CM_TOT; a++) {
if (cumap->cm[a].curve) MEM_freeN(cumap->cm[a].curve);
if (cumap->cm[a].table) MEM_freeN(cumap->cm[a].table);
if (cumap->cm[a].premultable) MEM_freeN(cumap->cm[a].premultable);
for (a = 0; a < CM_TOT; a++) {
if (cumap->cm[a].curve) {
MEM_freeN(cumap->cm[a].curve);
cumap->cm[a].curve = NULL;
}
if (cumap->cm[a].table) {
MEM_freeN(cumap->cm[a].table);
cumap->cm[a].table = NULL;
}
if (cumap->cm[a].premultable) {
MEM_freeN(cumap->cm[a].premultable);
cumap->cm[a].premultable = NULL;
}
}
}
void curvemapping_free(CurveMapping *cumap)
{
if (cumap) {
curvemapping_free_data(cumap);
MEM_freeN(cumap);
}
}
void curvemapping_copy_data(CurveMapping *target, CurveMapping *cumap)
{
int a;
*target = *cumap;
for (a = 0; a < CM_TOT; a++) {
if (cumap->cm[a].curve)
target->cm[a].curve = MEM_dupallocN(cumap->cm[a].curve);
if (cumap->cm[a].table)
target->cm[a].table = MEM_dupallocN(cumap->cm[a].table);
if (cumap->cm[a].premultable)
target->cm[a].premultable = MEM_dupallocN(cumap->cm[a].premultable);
}
}
CurveMapping *curvemapping_copy(CurveMapping *cumap)
{
int a;
if (cumap) {
CurveMapping *cumapn = MEM_dupallocN(cumap);
for (a = 0; a < CM_TOT; a++) {
if (cumap->cm[a].curve)
cumapn->cm[a].curve = MEM_dupallocN(cumap->cm[a].curve);
if (cumap->cm[a].table)
cumapn->cm[a].table = MEM_dupallocN(cumap->cm[a].table);
if (cumap->cm[a].premultable)
cumapn->cm[a].premultable = MEM_dupallocN(cumap->cm[a].premultable);
}
curvemapping_copy_data(cumapn, cumap);
return cumapn;
}
return NULL;
}
void curvemapping_set_black_white(CurveMapping *cumap, const float black[3], const float white[3])
void curvemapping_set_black_white_ex(const float black[3], const float white[3], float r_bwmul[3])
{
int a;
if (white)
copy_v3_v3(cumap->white, white);
if (black)
copy_v3_v3(cumap->black, black);
for (a = 0; a < 3; a++) {
if (cumap->white[a] == cumap->black[a])
cumap->bwmul[a] = 0.0f;
else
cumap->bwmul[a] = 1.0f / (cumap->white[a] - cumap->black[a]);
}
const float delta = maxf(white[a] - black[a], 1e-5f);
r_bwmul[a] = 1.0f / delta;
}
}
void curvemapping_set_black_white(CurveMapping *cumap, const float black[3], const float white[3])
{
if (white) {
copy_v3_v3(cumap->white, white);
}
if (black) {
copy_v3_v3(cumap->black, black);
}
curvemapping_set_black_white_ex(cumap->black, cumap->white, cumap->bwmul);
}
/* ***************** operations on single curve ************* */
@ -173,7 +206,7 @@ void curvemap_remove_point(CurveMap *cuma, CurveMapPoint *point)
}
/* removes with flag set */
void curvemap_remove(CurveMap *cuma, int flag)
void curvemap_remove(CurveMap *cuma, const short flag)
{
CurveMapPoint *cmp = MEM_mallocN((cuma->totpoint) * sizeof(CurveMapPoint), "curve points");
int a, b, removed = 0;
@ -416,7 +449,7 @@ static void calchandle_curvemap(BezTriple *bezt, BezTriple *prev, BezTriple *nex
/* in X, out Y.
* X is presumed to be outside first or last */
static float curvemap_calc_extend(CurveMap *cuma, float x, const float first[2], const float last[2])
static float curvemap_calc_extend(const CurveMap *cuma, float x, const float first[2], const float last[2])
{
if (x <= first[0]) {
if ((cuma->flag & CUMA_EXTEND_EXTRAPOLATE) == 0) {
@ -644,7 +677,7 @@ void curvemapping_changed(CurveMapping *cumap, int rem_doubles)
CurveMap *cuma = cumap->cm + cumap->cur;
CurveMapPoint *cmp = cuma->curve;
rctf *clipr = &cumap->clipr;
float thresh = 0.01f * (clipr->xmax - clipr->xmin);
float thresh = 0.01f * BLI_RCT_SIZE_X(clipr);
float dx = 0.0f, dy = 0.0f;
int a;
@ -682,12 +715,12 @@ void curvemapping_changed(CurveMapping *cumap, int rem_doubles)
dy = cmp[a].y - cmp[a + 1].y;
if (sqrtf(dx * dx + dy * dy) < thresh) {
if (a == 0) {
cmp[a + 1].flag |= 2;
cmp[a + 1].flag |= CUMA_VECTOR;
if (cmp[a + 1].flag & CUMA_SELECT)
cmp[a].flag |= CUMA_SELECT;
}
else {
cmp[a].flag |= 2;
cmp[a].flag |= CUMA_VECTOR;
if (cmp[a].flag & CUMA_SELECT)
cmp[a + 1].flag |= CUMA_SELECT;
}
@ -707,7 +740,7 @@ void curvemapping_changed_all(CurveMapping *cumap)
for (a = 0; a < CM_TOT; a++) {
if (cumap->cm[a].curve) {
cumap->cur = a;
curvemapping_changed(cumap, 0);
curvemapping_changed(cumap, FALSE);
}
}
@ -715,7 +748,7 @@ void curvemapping_changed_all(CurveMapping *cumap)
}
/* table should be verified */
float curvemap_evaluateF(CurveMap *cuma, float value)
float curvemap_evaluateF(const CurveMap *cuma, float value)
{
float fi;
int i;
@ -737,49 +770,67 @@ float curvemap_evaluateF(CurveMap *cuma, float value)
}
/* works with curve 'cur' */
float curvemapping_evaluateF(CurveMapping *cumap, int cur, float value)
float curvemapping_evaluateF(const CurveMapping *cumap, int cur, float value)
{
CurveMap *cuma = cumap->cm + cur;
/* allocate or bail out */
if (cuma->table == NULL) {
curvemap_make_table(cuma, &cumap->clipr);
if (cuma->table == NULL)
return 1.0f - value;
}
const CurveMap *cuma = cumap->cm + cur;
return curvemap_evaluateF(cuma, value);
}
/* vector case */
void curvemapping_evaluate3F(CurveMapping *cumap, float vecout[3], const float vecin[3])
void curvemapping_evaluate3F(const CurveMapping *cumap, float vecout[3], const float vecin[3])
{
vecout[0] = curvemapping_evaluateF(cumap, 0, vecin[0]);
vecout[1] = curvemapping_evaluateF(cumap, 1, vecin[1]);
vecout[2] = curvemapping_evaluateF(cumap, 2, vecin[2]);
vecout[0] = curvemap_evaluateF(&cumap->cm[0], vecin[0]);
vecout[1] = curvemap_evaluateF(&cumap->cm[1], vecin[1]);
vecout[2] = curvemap_evaluateF(&cumap->cm[2], vecin[2]);
}
/* RGB case, no black/white points, no premult */
void curvemapping_evaluateRGBF(CurveMapping *cumap, float vecout[3], const float vecin[3])
void curvemapping_evaluateRGBF(const CurveMapping *cumap, float vecout[3], const float vecin[3])
{
vecout[0] = curvemapping_evaluateF(cumap, 0, curvemapping_evaluateF(cumap, 3, vecin[0]));
vecout[1] = curvemapping_evaluateF(cumap, 1, curvemapping_evaluateF(cumap, 3, vecin[1]));
vecout[2] = curvemapping_evaluateF(cumap, 2, curvemapping_evaluateF(cumap, 3, vecin[2]));
vecout[0] = curvemap_evaluateF(&cumap->cm[0], curvemap_evaluateF(&cumap->cm[3], vecin[0]));
vecout[1] = curvemap_evaluateF(&cumap->cm[1], curvemap_evaluateF(&cumap->cm[3], vecin[1]));
vecout[2] = curvemap_evaluateF(&cumap->cm[2], curvemap_evaluateF(&cumap->cm[3], vecin[2]));
}
/** same as #curvemapping_evaluate_premulRGBF
* but black/bwmul are passed as args for the compositor
* where they can change per pixel.
*
* Use in conjunction with #curvemapping_set_black_white_ex
*
* \param black Use instead of cumap->black
* \param bwmul Use instead of cumap->bwmul
*/
void curvemapping_evaluate_premulRGBF_ex(const CurveMapping *cumap, float vecout[3], const float vecin[3],
const float black[3], const float bwmul[3])
{
vecout[0] = curvemap_evaluateF(&cumap->cm[0], (vecin[0] - black[0]) * bwmul[0]);
vecout[1] = curvemap_evaluateF(&cumap->cm[1], (vecin[1] - black[1]) * bwmul[1]);
vecout[2] = curvemap_evaluateF(&cumap->cm[2], (vecin[2] - black[2]) * bwmul[2]);
}
/* RGB with black/white points and premult. tables are checked */
void curvemapping_evaluate_premulRGBF(CurveMapping *cumap, float vecout[3], const float vecin[3])
void curvemapping_evaluate_premulRGBF(const CurveMapping *cumap, float vecout[3], const float vecin[3])
{
float fac;
fac = (vecin[0] - cumap->black[0]) * cumap->bwmul[0];
vecout[0] = curvemap_evaluateF(cumap->cm, fac);
fac = (vecin[1] - cumap->black[1]) * cumap->bwmul[1];
vecout[1] = curvemap_evaluateF(cumap->cm + 1, fac);
fac = (vecin[2] - cumap->black[2]) * cumap->bwmul[2];
vecout[2] = curvemap_evaluateF(cumap->cm + 2, fac);
vecout[0] = curvemap_evaluateF(&cumap->cm[0], (vecin[0] - cumap->black[0]) * cumap->bwmul[0]);
vecout[1] = curvemap_evaluateF(&cumap->cm[1], (vecin[1] - cumap->black[1]) * cumap->bwmul[1]);
vecout[2] = curvemap_evaluateF(&cumap->cm[2], (vecin[2] - cumap->black[2]) * cumap->bwmul[2]);
}
/* same as above, byte version */
void curvemapping_evaluate_premulRGB(const CurveMapping *cumap, unsigned char vecout_byte[3], const unsigned char vecin_byte[3])
{
float vecin[3], vecout[3];
vecin[0] = (float) vecin_byte[0] / 255.0f;
vecin[1] = (float) vecin_byte[1] / 255.0f;
vecin[2] = (float) vecin_byte[2] / 255.0f;
curvemapping_evaluate_premulRGBF(cumap, vecout, vecin);
vecout_byte[0] = FTOCHAR(vecout[0]);
vecout_byte[1] = FTOCHAR(vecout[1]);
vecout_byte[2] = FTOCHAR(vecout[2]);
}
@ -840,7 +891,7 @@ void curvemapping_do_ibuf(CurveMapping *cumap, ImBuf *ibuf)
curvemapping_premultiply(cumap, 1);
}
int curvemapping_RGBA_does_something(CurveMapping *cumap)
int curvemapping_RGBA_does_something(const CurveMapping *cumap)
{
int a;
@ -876,13 +927,12 @@ void curvemapping_initialize(CurveMapping *cumap)
}
}
void curvemapping_table_RGBA(CurveMapping *cumap, float **array, int *size)
void curvemapping_table_RGBA(const CurveMapping *cumap, float **array, int *size)
{
int a;
*size = CM_TABLE + 1;
*array = MEM_callocN(sizeof(float) * (*size) * 4, "CurveMapping");
curvemapping_initialize(cumap);
for (a = 0; a < *size; a++) {
if (cumap->cm[0].table)

@ -1165,7 +1165,7 @@ void BKE_curve_forward_diff_bezier(float q0, float q1, float q2, float q3, float
static void forward_diff_bezier_cotangent(const float p0[3], const float p1[3], const float p2[3], const float p3[3],
float p[3], int it, int stride)
{
/* note that these are not purpendicular to the curve
/* note that these are not perpendicular to the curve
* they need to be rotated for this,
*
* This could also be optimized like BKE_curve_forward_diff_bezier */
@ -3047,29 +3047,6 @@ void BKE_nurbList_handles_set(ListBase *editnurb, short code)
}
}
static void swapdata(void *adr1, void *adr2, int len)
{
if (len <= 0) return;
if (len < 65) {
char adr[64];
memcpy(adr, adr1, len);
memcpy(adr1, adr2, len);
memcpy(adr2, adr, len);
}
else {
char *adr;
adr = (char *)MEM_mallocN(len, "curve swap");
memcpy(adr, adr1, len);
memcpy(adr1, adr2, len);
memcpy(adr2, adr, len);
MEM_freeN(adr);
}
}
void BKE_nurb_direction_switch(Nurb *nu)
{
BezTriple *bezt1, *bezt2;
@ -3077,7 +3054,9 @@ void BKE_nurb_direction_switch(Nurb *nu)
float *fp1, *fp2, *tempf;
int a, b;
if (nu->pntsu == 1 && nu->pntsv == 1) return;
if (nu->pntsu == 1 && nu->pntsv == 1) {
return;
}
if (nu->type == CU_BEZIER) {
a = nu->pntsu;
@ -3086,19 +3065,22 @@ void BKE_nurb_direction_switch(Nurb *nu)
if (a & 1) a += 1; /* if odd, also swap middle content */
a /= 2;
while (a > 0) {
if (bezt1 != bezt2)
if (bezt1 != bezt2) {
SWAP(BezTriple, *bezt1, *bezt2);
}
swapdata(bezt1->vec[0], bezt1->vec[2], 12);
if (bezt1 != bezt2)
swapdata(bezt2->vec[0], bezt2->vec[2], 12);
swap_v3_v3(bezt1->vec[0], bezt1->vec[2]);
if (bezt1 != bezt2) {
swap_v3_v3(bezt2->vec[0], bezt2->vec[2]);
}
SWAP(char, bezt1->h1, bezt1->h2);
SWAP(short, bezt1->f1, bezt1->f3);
SWAP(char, bezt1->f1, bezt1->f3);
if (bezt1 != bezt2) {
SWAP(char, bezt2->h1, bezt2->h2);
SWAP(short, bezt2->f1, bezt2->f3);
SWAP(char, bezt2->f1, bezt2->f3);
bezt1->alfa = -bezt1->alfa;
bezt2->alfa = -bezt2->alfa;
}

@ -72,25 +72,29 @@ typedef struct LayerTypeInfo {
const char *structname; /* name of the struct used, for file writing */
int structnum; /* number of structs per element, for file writing */
/* default layer name.
/**
* default layer name.
* note! when NULL this is a way to ensure there is only ever one item
* see: CustomData_layertype_is_singleton() */
const char *defaultname;
/* a function to copy count elements of this layer's data
/**
* a function to copy count elements of this layer's data
* (deep copy if appropriate)
* if NULL, memcpy is used
*/
void (*copy)(const void *source, void *dest, int count);
/* a function to free any dynamically allocated components of this
/**
* a function to free any dynamically allocated components of this
* layer's data (note the data pointer itself should not be freed)
* size should be the size of one element of this layer's data (e.g.
* LayerTypeInfo.size)
*/
void (*free)(void *data, int count, int size);
/* a function to interpolate between count source elements of this
/**
* a function to interpolate between count source elements of this
* layer's data and store the result in dest
* if weights == NULL or sub_weights == NULL, they should default to 1
*
@ -98,18 +102,24 @@ typedef struct LayerTypeInfo {
* sub_weights gives the sub-element weights for each element in sources
* (there should be (sub element count)^2 weights per element)
* count gives the number of elements in sources
*
* \note in some cases \a dest pointer is in \a sources
* so all functions have to take this into account and delay
* applying changes while reading from sources.
* See bug [#32395] - Campbell.
*/
void (*interp)(void **sources, float *weights, float *sub_weights,
void (*interp)(void **sources, const float *weights, const float *sub_weights,
int count, void *dest);
/* a function to swap the data in corners of the element */
/** a function to swap the data in corners of the element */
void (*swap)(void *data, const int *corner_indices);
/* a function to set a layer's data to default values. if NULL, the
/**
* a function to set a layer's data to default values. if NULL, the
* default is assumed to be all zeros */
void (*set_default)(void *data, int count);
/* functions necessary for geometry collapse*/
/** functions necessary for geometry collapse */
int (*equal)(void *data1, void *data2);
void (*multiply)(void *data, float fac);
void (*initminmax)(void *min, void *max);
@ -117,13 +127,13 @@ typedef struct LayerTypeInfo {
void (*dominmax)(void *data1, void *min, void *max);
void (*copyvalue)(void *source, void *dest);
/* a function to read data from a cdf file */
/** a function to read data from a cdf file */
int (*read)(CDataFile *cdf, void *data, int count);
/* a function to write data to a cdf file */
/** a function to write data to a cdf file */
int (*write)(CDataFile *cdf, void *data, int count);
/* a function to determine file size */
/** a function to determine file size */
size_t (*filesize)(CDataFile *cdf, void *data, int count);
} LayerTypeInfo;
@ -203,8 +213,8 @@ static void linklist_free_simple(void *link)
MEM_freeN(link);
}
static void layerInterp_mdeformvert(void **sources, float *weights,
float *UNUSED(sub_weights), int count, void *dest)
static void layerInterp_mdeformvert(void **sources, const float *weights,
const float *UNUSED(sub_weights), int count, void *dest)
{
MDeformVert *dvert = dest;
LinkNode *dest_dw = NULL; /* a list of lists of MDeformWeight pointers */
@ -243,6 +253,8 @@ static void layerInterp_mdeformvert(void **sources, float *weights,
}
}
/* delay writing to the destination incase dest is in sources */
/* now we know how many unique deform weights there are, so realloc */
if (dvert->dw) MEM_freeN(dvert->dw);
@ -261,8 +273,8 @@ static void layerInterp_mdeformvert(void **sources, float *weights,
}
static void layerInterp_msticky(void **sources, float *weights,
float *UNUSED(sub_weights), int count, void *dest)
static void layerInterp_msticky(void **sources, const float *weights,
const float *UNUSED(sub_weights), int count, void *dest)
{
float co[2], w;
MSticky *mst;
@ -276,6 +288,7 @@ static void layerInterp_msticky(void **sources, float *weights,
madd_v2_v2fl(co, mst->co, w);
}
/* delay writing to the destination incase dest is in sources */
mst = (MSticky *)dest;
copy_v2_v2(mst->co, co);
}
@ -291,13 +304,13 @@ static void layerCopy_tface(const void *source, void *dest, int count)
dest_tf[i] = source_tf[i];
}
static void layerInterp_tface(void **sources, float *weights,
float *sub_weights, int count, void *dest)
static void layerInterp_tface(void **sources, const float *weights,
const float *sub_weights, int count, void *dest)
{
MTFace *tf = dest;
int i, j, k;
float uv[4][2] = {{0.0f}};
float *sub_weight;
const float *sub_weight;
if (count <= 0) return;
@ -318,6 +331,7 @@ static void layerInterp_tface(void **sources, float *weights,
}
}
/* delay writing to the destination incase dest is in sources */
*tf = *(MTFace *)(*sources);
memcpy(tf->uv, uv, sizeof(tf->uv));
}
@ -392,13 +406,13 @@ static void layerCopy_origspace_face(const void *source, void *dest, int count)
dest_tf[i] = source_tf[i];
}
static void layerInterp_origspace_face(void **sources, float *weights,
float *sub_weights, int count, void *dest)
static void layerInterp_origspace_face(void **sources, const float *weights,
const float *sub_weights, int count, void *dest)
{
OrigSpaceFace *osf = dest;
int i, j, k;
float uv[4][2] = {{0.0f}};
float *sub_weight;
const float *sub_weight;
if (count <= 0) return;
@ -419,6 +433,8 @@ static void layerInterp_origspace_face(void **sources, float *weights,
}
}
/* delay writing to the destination incase dest is in sources */
#if 0 /* no need, this ONLY contains UV's */
*osf = *(OrigSpaceFace *)(*sources);
#endif
@ -680,12 +696,12 @@ static void layerDefault_mloopcol(void *data, int count)
}
static void layerInterp_mloopcol(void **sources, float *weights,
float *sub_weights, int count, void *dest)
static void layerInterp_mloopcol(void **sources, const float *weights,
const float *sub_weights, int count, void *dest)
{
MLoopCol *mc = dest;
int i;
float *sub_weight;
const float *sub_weight;
struct {
float a;
float r;
@ -719,7 +735,8 @@ static void layerInterp_mloopcol(void **sources, float *weights,
CLAMP(col.r, 0.0f, 255.0f);
CLAMP(col.g, 0.0f, 255.0f);
CLAMP(col.b, 0.0f, 255.0f);
/* delay writing to the destination incase dest is in sources */
mc->r = (int)col.r;
mc->g = (int)col.g;
mc->b = (int)col.b;
@ -768,11 +785,10 @@ static void layerAdd_mloopuv(void *data1, void *data2)
add_v2_v2(l1->uv, l2->uv);
}
static void layerInterp_mloopuv(void **sources, float *weights,
float *sub_weights, int count, void *dest)
static void layerInterp_mloopuv(void **sources, const float *weights,
const float *sub_weights, int count, void *dest)
{
MLoopUV *mluv = dest;
float *uv = mluv->uv;
float uv[2];
int i;
zero_v2(uv);
@ -793,6 +809,9 @@ static void layerInterp_mloopuv(void **sources, float *weights,
madd_v2_v2fl(uv, src->uv, weight);
}
}
/* delay writing to the destination incase dest is in sources */
copy_v2_v2(((MLoopUV *)dest)->uv, uv);
}
/* origspace is almost exact copy of mloopuv's, keep in sync */
@ -838,11 +857,10 @@ static void layerAdd_mloop_origspace(void *data1, void *data2)
add_v2_v2(l1->uv, l2->uv);
}
static void layerInterp_mloop_origspace(void **sources, float *weights,
float *sub_weights, int count, void *dest)
static void layerInterp_mloop_origspace(void **sources, const float *weights,
const float *sub_weights, int count, void *dest)
{
OrigSpaceLoop *mluv = dest;
float *uv = mluv->uv;
float uv[2];
int i;
zero_v2(uv);
@ -858,16 +876,19 @@ static void layerInterp_mloop_origspace(void **sources, float *weights,
}
else {
for (i = 0; i < count; i++) {
float weight = weights ? weights[i] : 1;
float weight = weights ? weights[i] : 1.0f;
OrigSpaceLoop *src = sources[i];
madd_v2_v2fl(uv, src->uv, weight);
}
}
/* delay writing to the destination incase dest is in sources */
copy_v2_v2(((OrigSpaceLoop *)dest)->uv, uv);
}
/* --- end copy */
static void layerInterp_mcol(void **sources, float *weights,
float *sub_weights, int count, void *dest)
static void layerInterp_mcol(void **sources, const float *weights,
const float *sub_weights, int count, void *dest)
{
MCol *mc = dest;
int i, j, k;
@ -878,7 +899,7 @@ static void layerInterp_mcol(void **sources, float *weights,
float b;
} col[4] = {{0.0f}};
float *sub_weight;
const float *sub_weight;
if (count <= 0) return;
@ -907,6 +928,7 @@ static void layerInterp_mcol(void **sources, float *weights,
}
}
/* delay writing to the destination incase dest is in sources */
for (j = 0; j < 4; ++j) {
/* Subdivide smooth or fractal can cause problems without clamping
@ -946,33 +968,36 @@ static void layerDefault_mcol(void *data, int count)
}
}
static void layerInterp_bweight(void **sources, float *weights,
float *UNUSED(sub_weights), int count, void *dest)
static void layerInterp_bweight(void **sources, const float *weights,
const float *UNUSED(sub_weights), int count, void *dest)
{
float *f = dest;
float f;
float **in = (float **)sources;
int i;
if (count <= 0) return;
*f = 0.0f;
f = 0.0f;
if (weights) {
for (i = 0; i < count; ++i) {
*f += *in[i] * weights[i];
f += *in[i] * weights[i];
}
}
else {
for (i = 0; i < count; ++i) {
*f += *in[i];
f += *in[i];
}
}
/* delay writing to the destination incase dest is in sources */
*((float *)dest) = f;
}
static void layerInterp_shapekey(void **sources, float *weights,
float *UNUSED(sub_weights), int count, void *dest)
static void layerInterp_shapekey(void **sources, const float *weights,
const float *UNUSED(sub_weights), int count, void *dest)
{
float *co = dest;
float co[3];
float **in = (float **)sources;
int i;
@ -990,6 +1015,9 @@ static void layerInterp_shapekey(void **sources, float *weights,
add_v3_v3(co, in[i]);
}
}
/* delay writing to the destination incase dest is in sources */
copy_v3_v3((float *)dest, co);
}
static void layerDefault_mvert_skin(void *data, int count)
@ -1003,8 +1031,8 @@ static void layerDefault_mvert_skin(void *data, int count)
}
}
static void layerInterp_mvert_skin(void **sources, float *weights,
float *UNUSED(sub_weights),
static void layerInterp_mvert_skin(void **sources, const float *weights,
const float *UNUSED(sub_weights),
int count, void *dest)
{
float radius[3], w;
@ -1019,6 +1047,7 @@ static void layerInterp_mvert_skin(void **sources, float *weights,
madd_v3_v3fl(radius, vs->radius, w);
}
/* delay writing to the destination incase dest is in sources */
vs = dest;
copy_v3_v3(vs->radius, radius);
vs->flag &= ~MVERT_SKIN_ROOT;
@ -1999,8 +2028,9 @@ void CustomData_interp(const CustomData *source, CustomData *dest,
if (dest->layers[dest_i].type == source->layers[src_i].type) {
void *src_data = source->layers[src_i].data;
for (j = 0; j < count; ++j)
for (j = 0; j < count; ++j) {
sources[j] = (char *)src_data + typeInfo->size * src_indices[j];
}
dest_offset = dest_index * typeInfo->size;
@ -2590,8 +2620,9 @@ void CustomData_bmesh_interp(CustomData *data, void **src_blocks, float *weights
CustomDataLayer *layer = &data->layers[i];
const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
if (typeInfo->interp) {
for (j = 0; j < count; ++j)
for (j = 0; j < count; ++j) {
sources[j] = (char *)src_blocks[j] + layer->offset;
}
typeInfo->interp(sources, weights, sub_weights, count,
(char *)dest_block + layer->offset);

@ -3996,7 +3996,7 @@ void surface_determineForceTargetPoints(PaintSurfaceData *sData, int index, floa
float force_intersect;
float temp;
/* project force vector on the plane determined by these two neightbour points
/* project force vector on the plane determined by these two neighbor points
* and calculate relative force angle from it*/
cross_v3_v3v3(tangent, bNeighs[closest_id[0]].dir, bNeighs[closest_id[1]].dir);
normalize_v3(tangent);

@ -365,7 +365,7 @@ int binarysearch_bezt_index(BezTriple array[], float frame, int arraylen, short
/* initialize replace-flag first */
*replace = 0;
/* sneaky optimisations (don't go through searching process if...):
/* sneaky optimizations (don't go through searching process if...):
* - keyframe to be added is to be added out of current bounds
* - keyframe to be added would replace one of the existing ones on bounds
*/

@ -60,10 +60,8 @@
#include "BKE_curve.h"
#include "BKE_displist.h"
static ListBase ttfdata = {NULL, NULL};
/* The vfont code */
void BKE_vfont_free_data(struct VFont *vfont)
{
if (vfont->data) {
@ -83,7 +81,10 @@ void BKE_vfont_free_data(struct VFont *vfont)
vfont->data = NULL;
}
BKE_vfont_tmpfont_remove(vfont);
if (vfont->temp_pf) {
freePackedFile(vfont->temp_pf); /* NULL when the font file can't be found on disk */
vfont->temp_pf = NULL;
}
}
void BKE_vfont_free(struct VFont *vf)
@ -91,7 +92,7 @@ void BKE_vfont_free(struct VFont *vf)
if (vf == NULL) return;
BKE_vfont_free_data(vf);
if (vf->packedfile) {
freePackedFile(vf->packedfile);
vf->packedfile = NULL;
@ -128,63 +129,11 @@ static PackedFile *get_builtin_packedfile(void)
}
}
static void vfont_tmpfont_free(struct TmpFont *tf)
{
if (tf->pf) {
freePackedFile(tf->pf); /* NULL when the font file can't be found on disk */
}
MEM_freeN(tf);
}
void BKE_vfont_free_global_ttf(void)
{
struct TmpFont *tf, *tf_next;
for (tf = ttfdata.first; tf; tf = tf_next) {
tf_next = tf->next;
vfont_tmpfont_free(tf);
}
ttfdata.first = ttfdata.last = NULL;
}
struct TmpFont *BKE_vfont_tmpfont_find(VFont *vfont)
{
struct TmpFont *tmpfnt = NULL;
if (vfont == NULL) return NULL;
/* Try finding the font from font list */
for (tmpfnt = ttfdata.first; tmpfnt; tmpfnt = tmpfnt->next) {
if (tmpfnt->vfont == vfont) {
break;
}
}
return tmpfnt;
}
/* assumes a VFont's tmpfont can't be in the database more then once */
void BKE_vfont_tmpfont_remove(VFont *vfont)
{
struct TmpFont *tmpfnt;
tmpfnt = BKE_vfont_tmpfont_find(vfont);
if (tmpfnt) {
vfont_tmpfont_free(tmpfnt);
BLI_remlink(&ttfdata, tmpfnt);
}
}
static VFontData *vfont_get_data(Main *bmain, VFont *vfont)
{
struct TmpFont *tmpfnt = NULL;
PackedFile *tpf;
if (vfont == NULL) return NULL;
/* Try finding the font from font list */
tmpfnt = BKE_vfont_tmpfont_find(vfont);
if (vfont == NULL) {
return NULL;
}
/* And then set the data */
if (!vfont->data) {
@ -198,30 +147,15 @@ static VFontData *vfont_get_data(Main *bmain, VFont *vfont)
pf = vfont->packedfile;
/* We need to copy a tmp font to memory unless it is already there */
if (!tmpfnt) {
tpf = MEM_callocN(sizeof(*tpf), "PackedFile");
tpf->data = MEM_mallocN(pf->size, "packFile");
tpf->size = pf->size;
memcpy(tpf->data, pf->data, pf->size);
/* Add temporary packed file to globals */
tmpfnt = (struct TmpFont *) MEM_callocN(sizeof(struct TmpFont), "temp_font");
tmpfnt->pf = tpf;
tmpfnt->vfont = vfont;
BLI_addtail(&ttfdata, tmpfnt);
if (vfont->temp_pf == NULL) {
vfont->temp_pf = dupPackedFile(pf);
}
}
else {
pf = newPackedFile(NULL, vfont->name, ID_BLEND_PATH(bmain, &vfont->id));
if (!tmpfnt) {
tpf = newPackedFile(NULL, vfont->name, ID_BLEND_PATH(bmain, &vfont->id));
/* Add temporary packed file to globals */
tmpfnt = (struct TmpFont *) MEM_callocN(sizeof(struct TmpFont), "temp_font");
tmpfnt->pf = tpf;
tmpfnt->vfont = vfont;
BLI_addtail(&ttfdata, tmpfnt);
if (vfont->temp_pf == NULL) {
vfont->temp_pf = newPackedFile(NULL, vfont->name, ID_BLEND_PATH(bmain, &vfont->id));
}
}
if (!pf) {
@ -252,9 +186,8 @@ VFont *BKE_vfont_load(Main *bmain, const char *name)
char filename[FILE_MAXFILE];
VFont *vfont = NULL;
PackedFile *pf;
PackedFile *tpf = NULL;
PackedFile *temp_pf = NULL;
int is_builtin;
struct TmpFont *tmpfnt;
if (strcmp(name, FO_BUILTIN_NAME) == 0) {
BLI_strncpy(filename, name, sizeof(filename));
@ -269,7 +202,7 @@ VFont *BKE_vfont_load(Main *bmain, const char *name)
BLI_splitdirstring(dir, filename);
pf = newPackedFile(NULL, name, bmain->name);
tpf = newPackedFile(NULL, name, bmain->name);
temp_pf = newPackedFile(NULL, name, bmain->name);
is_builtin = FALSE;
}
@ -295,10 +228,7 @@ VFont *BKE_vfont_load(Main *bmain, const char *name)
/* Do not add FO_BUILTIN_NAME to temporary listbase */
if (strcmp(filename, FO_BUILTIN_NAME)) {
tmpfnt = (struct TmpFont *) MEM_callocN(sizeof(struct TmpFont), "temp_font");
tmpfnt->pf = tpf;
tmpfnt->vfont = vfont;
BLI_addtail(&ttfdata, tmpfnt);
vfont->temp_pf = temp_pf;
}
}
@ -306,8 +236,6 @@ VFont *BKE_vfont_load(Main *bmain, const char *name)
if (!vfont || vfont->packedfile != pf) {
freePackedFile(pf);
}
//XXX waitcursor(0);
}
return vfont;
@ -317,14 +245,14 @@ static VFont *which_vfont(Curve *cu, CharInfo *info)
{
switch (info->flag & (CU_CHINFO_BOLD | CU_CHINFO_ITALIC)) {
case CU_CHINFO_BOLD:
if (cu->vfontb) return(cu->vfontb); else return(cu->vfont);
return cu->vfontb ? cu->vfontb : cu->vfont;
case CU_CHINFO_ITALIC:
if (cu->vfonti) return(cu->vfonti); else return(cu->vfont);
return cu->vfonti ? cu->vfonti : cu->vfont;
case (CU_CHINFO_BOLD | CU_CHINFO_ITALIC):
if (cu->vfontbi) return(cu->vfontbi); else return(cu->vfont);
return cu->vfontbi ? cu->vfontbi : cu->vfont;
default:
return(cu->vfont);
}
return cu->vfont;
}
}
VFont *BKE_vfont_builtin_get(void)
@ -344,6 +272,7 @@ static VChar *find_vfont_char(VFontData *vfd, intptr_t character)
{
VChar *che = NULL;
/* TODO: use ghash */
for (che = vfd->characters.first; che; che = che->next) {
if (che->index == character)
break;

@ -167,11 +167,13 @@ static int add_to_group_internal(Group *group, Object *ob)
{
GroupObject *go;
if (group == NULL || ob == NULL) return 0;
if (group == NULL || ob == NULL) {
return FALSE;
}
/* check if the object has been added already */
for (go = group->gobject.first; go; go = go->next) {
if (go->ob == ob) return 0;
if (BLI_findptr(&group->gobject, ob, offsetof(GroupObject, ob))) {
return FALSE;
}
go = MEM_callocN(sizeof(GroupObject), "groupobject");
@ -179,7 +181,7 @@ static int add_to_group_internal(Group *group, Object *ob)
go->ob = ob;
return 1;
return TRUE;
}
int add_to_group(Group *group, Object *object, Scene *scene, Base *base)
@ -245,15 +247,11 @@ int rem_from_group(Group *group, Object *object, Scene *scene, Base *base)
int object_in_group(Object *ob, Group *group)
{
GroupObject *go;
if (group == NULL || ob == NULL) return 0;
for (go = group->gobject.first; go; go = go->next) {
if (go->ob == ob)
return 1;
if (group == NULL || ob == NULL) {
return FALSE;
}
return 0;
return (BLI_findptr(&group->gobject, ob, offsetof(GroupObject, ob)) != NULL);
}
Group *find_group(Object *ob, Group *group)

@ -2145,7 +2145,9 @@ RenderResult *BKE_image_acquire_renderresult(Scene *scene, Image *ima)
void BKE_image_release_renderresult(Scene *scene, Image *ima)
{
if (ima->rr) ;
if (ima->rr) {
/* pass */
}
else if (ima->type == IMA_TYPE_R_RESULT) {
if (ima->render_slot == ima->last_render_slot)
RE_ReleaseResult(RE_GetRender(scene->id.name));

@ -19,7 +19,8 @@
* All rights reserved.
*
* Contributor(s): Blender Foundation,
* Sergey Sharybin
* Sergey Sharybin,
* Campbell Barton
*
* ***** END GPL LICENSE BLOCK *****
*/
@ -41,12 +42,8 @@
#include "DNA_mask_types.h"
#include "DNA_node_types.h"
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "DNA_movieclip_types.h"
#include "DNA_tracking_types.h"
#include "DNA_sequence_types.h"
#include "BKE_curve.h"
@ -58,7 +55,6 @@
#include "BKE_sequencer.h"
#include "BKE_tracking.h"
#include "BKE_movieclip.h"
#include "BKE_utildefines.h"
static MaskSplinePoint *mask_spline_point_next(MaskSpline *spline, MaskSplinePoint *points_array, MaskSplinePoint *point)
{
@ -90,7 +86,7 @@ static MaskSplinePoint *mask_spline_point_prev(MaskSpline *spline, MaskSplinePoi
}
}
static BezTriple *mask_spline_point_next_bezt(MaskSpline *spline, MaskSplinePoint *points_array, MaskSplinePoint *point)
BezTriple *BKE_mask_spline_point_next_bezt(MaskSpline *spline, MaskSplinePoint *points_array, MaskSplinePoint *point)
{
if (point == &points_array[spline->tot_point - 1]) {
if (spline->flag & MASK_SPLINE_CYCLIC) {
@ -158,7 +154,7 @@ MaskLayer *BKE_mask_layer_new(Mask *mask, const char *name)
mask->masklay_tot++;
masklay->blend = MASK_BLEND_MERGE;
masklay->blend = MASK_BLEND_MERGE_ADD;
masklay->alpha = 1.0f;
return masklay;
@ -269,586 +265,6 @@ MaskSpline *BKE_mask_spline_add(MaskLayer *masklay)
return spline;
}
unsigned int BKE_mask_spline_resolution(MaskSpline *spline, int width, int height)
{
float max_segment = 0.01f;
unsigned int i, resol = 1;
if (width != 0 && height != 0) {
if (width >= height)
max_segment = 1.0f / (float) width;
else
max_segment = 1.0f / (float) height;
}
for (i = 0; i < spline->tot_point; i++) {
MaskSplinePoint *point = &spline->points[i];
BezTriple *bezt, *bezt_next;
float a, b, c, len;
unsigned int cur_resol;
bezt = &point->bezt;
bezt_next = mask_spline_point_next_bezt(spline, spline->points, point);
if (bezt_next == NULL) {
break;
}
a = len_v3v3(bezt->vec[1], bezt->vec[2]);
b = len_v3v3(bezt->vec[2], bezt_next->vec[0]);
c = len_v3v3(bezt_next->vec[0], bezt_next->vec[1]);
len = a + b + c;
cur_resol = len / max_segment;
resol = MAX2(resol, cur_resol);
if (resol >= MASK_RESOL_MAX) {
break;
}
}
return CLAMPIS(resol, 1, MASK_RESOL_MAX);
}
unsigned int BKE_mask_spline_feather_resolution(MaskSpline *spline, int width, int height)
{
const float max_segment = 0.005;
unsigned int resol = BKE_mask_spline_resolution(spline, width, height);
float max_jump = 0.0f;
int i;
/* avoid checking the featrher if we already hit the maximum value */
if (resol >= MASK_RESOL_MAX) {
return MASK_RESOL_MAX;
}
for (i = 0; i < spline->tot_point; i++) {
MaskSplinePoint *point = &spline->points[i];
float prev_u, prev_w;
int j;
prev_u = 0.0f;
prev_w = point->bezt.weight;
for (j = 0; j < point->tot_uw; j++) {
const float w_diff = (point->uw[j].w - prev_w);
const float u_diff = (point->uw[j].u - prev_u);
/* avoid divide by zero and very high values,
* though these get clamped eventually */
if (u_diff > FLT_EPSILON) {
float jump = fabsf(w_diff / u_diff);
max_jump = MAX2(max_jump, jump);
}
prev_u = point->uw[j].u;
prev_w = point->uw[j].w;
}
}
resol += max_jump / max_segment;
return CLAMPIS(resol, 1, MASK_RESOL_MAX);
}
int BKE_mask_spline_differentiate_calc_total(const MaskSpline *spline, const unsigned int resol)
{
if (spline->flag & MASK_SPLINE_CYCLIC) {
return spline->tot_point * resol;
}
else {
return ((spline->tot_point - 1) * resol) + 1;
}
}
float (*BKE_mask_spline_differentiate_with_resolution_ex(MaskSpline *spline,
int *tot_diff_point,
const unsigned int resol
))[2]
{
MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
MaskSplinePoint *point, *prev;
float (*diff_points)[2], (*fp)[2];
const int tot = BKE_mask_spline_differentiate_calc_total(spline, resol);
int a;
if (spline->tot_point <= 1) {
/* nothing to differentiate */
*tot_diff_point = 0;
return NULL;
}
/* len+1 because of 'forward_diff_bezier' function */
*tot_diff_point = tot;
diff_points = fp = MEM_mallocN((tot + 1) * sizeof(*diff_points), "mask spline vets");
a = spline->tot_point - 1;
if (spline->flag & MASK_SPLINE_CYCLIC)
a++;
prev = points_array;
point = prev + 1;
while (a--) {
BezTriple *prevbezt;
BezTriple *bezt;
int j;
if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC))
point = points_array;
prevbezt = &prev->bezt;
bezt = &point->bezt;
for (j = 0; j < 2; j++) {
BKE_curve_forward_diff_bezier(prevbezt->vec[1][j], prevbezt->vec[2][j],
bezt->vec[0][j], bezt->vec[1][j],
&(*fp)[j], resol, 2 * sizeof(float));
}
fp += resol;
if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC) == 0) {
copy_v2_v2(*fp, bezt->vec[1]);
}
prev = point;
point++;
}
return diff_points;
}
float (*BKE_mask_spline_differentiate_with_resolution(MaskSpline *spline, int width, int height,
int *tot_diff_point
))[2]
{
int unsigned resol = BKE_mask_spline_resolution(spline, width, height);
return BKE_mask_spline_differentiate_with_resolution_ex(spline, tot_diff_point, resol);
}
float (*BKE_mask_spline_differentiate(MaskSpline *spline, int *tot_diff_point))[2]
{
return BKE_mask_spline_differentiate_with_resolution(spline, 0, 0, tot_diff_point);
}
/* ** feather points self-intersection collapse routine ** */
typedef struct FeatherEdgesBucket {
int tot_segment;
int (*segments)[2];
int alloc_segment;
} FeatherEdgesBucket;
static void feather_bucket_add_edge(FeatherEdgesBucket *bucket, int start, int end)
{
const int alloc_delta = 256;
if (bucket->tot_segment >= bucket->alloc_segment) {
if (!bucket->segments) {
bucket->segments = MEM_callocN(alloc_delta * sizeof(*bucket->segments), "feather bucket segments");
}
else {
bucket->segments = MEM_reallocN(bucket->segments,
(alloc_delta + bucket->tot_segment) * sizeof(*bucket->segments));
}
bucket->alloc_segment += alloc_delta;
}
bucket->segments[bucket->tot_segment][0] = start;
bucket->segments[bucket->tot_segment][1] = end;
bucket->tot_segment++;
}
static void feather_bucket_check_intersect(float (*feather_points)[2], int tot_feather_point, FeatherEdgesBucket *bucket,
int cur_a, int cur_b)
{
int i;
float *v1 = (float *) feather_points[cur_a];
float *v2 = (float *) feather_points[cur_b];
for (i = 0; i < bucket->tot_segment; i++) {
int check_a = bucket->segments[i][0];
int check_b = bucket->segments[i][1];
float *v3 = (float *) feather_points[check_a];
float *v4 = (float *) feather_points[check_b];
if (check_a >= cur_a - 1 || cur_b == check_a)
continue;
if (isect_seg_seg_v2(v1, v2, v3, v4)) {
int k;
float p[2];
float min_a[2], max_a[2];
float min_b[2], max_b[2];
isect_seg_seg_v2_point(v1, v2, v3, v4, p);
INIT_MINMAX2(min_a, max_a);
INIT_MINMAX2(min_b, max_b);
/* collapse loop with smaller AABB */
for (k = 0; k < tot_feather_point; k++) {
if (k >= check_b && k <= cur_a) {
DO_MINMAX2(feather_points[k], min_a, max_a);
}
else {
DO_MINMAX2(feather_points[k], min_b, max_b);
}
}
if (max_a[0] - min_a[0] < max_b[0] - min_b[0] ||
max_a[1] - min_a[1] < max_b[1] - min_b[1])
{
for (k = check_b; k <= cur_a; k++) {
copy_v2_v2(feather_points[k], p);
}
}
else {
for (k = 0; k <= check_a; k++) {
copy_v2_v2(feather_points[k], p);
}
if (cur_b != 0) {
for (k = cur_b; k < tot_feather_point; k++) {
copy_v2_v2(feather_points[k], p);
}
}
}
}
}
}
static int feather_bucket_index_from_coord(float co[2], const float min[2], const float bucket_scale[2],
const int buckets_per_side)
{
int x = (int) ((co[0] - min[0]) * bucket_scale[0]);
int y = (int) ((co[1] - min[1]) * bucket_scale[1]);
if (x == buckets_per_side)
x--;
if (y == buckets_per_side)
y--;
return y * buckets_per_side + x;
}
static void feather_bucket_get_diagonal(FeatherEdgesBucket *buckets, int start_bucket_index, int end_bucket_index,
int buckets_per_side, FeatherEdgesBucket **diagonal_bucket_a_r,
FeatherEdgesBucket **diagonal_bucket_b_r)
{
int start_bucket_x = start_bucket_index % buckets_per_side;
int start_bucket_y = start_bucket_index / buckets_per_side;
int end_bucket_x = end_bucket_index % buckets_per_side;
int end_bucket_y = end_bucket_index / buckets_per_side;
int diagonal_bucket_a_index = start_bucket_y * buckets_per_side + end_bucket_x;
int diagonal_bucket_b_index = end_bucket_y * buckets_per_side + start_bucket_x;
*diagonal_bucket_a_r = &buckets[diagonal_bucket_a_index];
*diagonal_bucket_b_r = &buckets[diagonal_bucket_b_index];
}
static void spline_feather_collapse_inner_loops(MaskSpline *spline, float (*feather_points)[2], int tot_feather_point)
{
#define BUCKET_INDEX(co) \
feather_bucket_index_from_coord(co, min, bucket_scale, buckets_per_side)
int buckets_per_side, tot_bucket;
float bucket_size, bucket_scale[2];
FeatherEdgesBucket *buckets;
int i;
float min[2], max[2];
float max_delta_x = -1.0f, max_delta_y = -1.0f, max_delta;
if (tot_feather_point < 4) {
/* self-intersection works only for quads at least,
* in other cases polygon can't be self-intersecting anyway
*/
return;
}
/* find min/max corners of mask to build buckets in that space */
INIT_MINMAX2(min, max);
for (i = 0; i < tot_feather_point; i++) {
int next = i + 1;
float delta;
DO_MINMAX2(feather_points[i], min, max);
if (next == tot_feather_point) {
if (spline->flag & MASK_SPLINE_CYCLIC)
next = 0;
else
break;
}
delta = fabsf(feather_points[i][0] - feather_points[next][0]);
if (delta > max_delta_x)
max_delta_x = delta;
delta = fabsf(feather_points[i][1] - feather_points[next][1]);
if (delta > max_delta_y)
max_delta_y = delta;
}
/* prevent divisionsby zero by ensuring bounding box is not collapsed */
if (max[0] - min[0] < FLT_EPSILON) {
max[0] += 0.01f;
min[0] -= 0.01f;
}
if (max[1] - min[1] < FLT_EPSILON) {
max[1] += 0.01f;
min[1] -= 0.01f;
}
/* use dynamically calculated buckets per side, so we likely wouldn't
* run into a situation when segment doesn't fit two buckets which is
* pain collecting candidates for intersection
*/
max_delta_x /= max[0] - min[0];
max_delta_y /= max[1] - min[1];
max_delta = MAX2(max_delta_x, max_delta_y);
buckets_per_side = MIN2(512, 0.9f / max_delta);
if (buckets_per_side == 0) {
/* happens when some segment fills the whole bounding box across some of dimension */
buckets_per_side = 1;
}
tot_bucket = buckets_per_side * buckets_per_side;
bucket_size = 1.0f / buckets_per_side;
/* pre-compute multipliers, to save mathematical operations in loops */
bucket_scale[0] = 1.0f / ((max[0] - min[0]) * bucket_size);
bucket_scale[1] = 1.0f / ((max[1] - min[1]) * bucket_size);
/* fill in buckets' edges */
buckets = MEM_callocN(sizeof(FeatherEdgesBucket) * tot_bucket, "feather buckets");
for (i = 0; i < tot_feather_point; i++) {
int start = i, end = i + 1;
int start_bucket_index, end_bucket_index;
if (end == tot_feather_point) {
if (spline->flag & MASK_SPLINE_CYCLIC)
end = 0;
else
break;
}
start_bucket_index = BUCKET_INDEX(feather_points[start]);
end_bucket_index = BUCKET_INDEX(feather_points[end]);
feather_bucket_add_edge(&buckets[start_bucket_index], start, end);
if (start_bucket_index != end_bucket_index) {
FeatherEdgesBucket *end_bucket = &buckets[end_bucket_index];
FeatherEdgesBucket *diagonal_bucket_a, *diagonal_bucket_b;
feather_bucket_get_diagonal(buckets, start_bucket_index, end_bucket_index, buckets_per_side,
&diagonal_bucket_a, &diagonal_bucket_b);
feather_bucket_add_edge(end_bucket, start, end);
feather_bucket_add_edge(diagonal_bucket_a, start, end);
feather_bucket_add_edge(diagonal_bucket_a, start, end);
}
}
/* check all edges for intersection with edges from their buckets */
for (i = 0; i < tot_feather_point; i++) {
int cur_a = i, cur_b = i + 1;
int start_bucket_index, end_bucket_index;
FeatherEdgesBucket *start_bucket;
if (cur_b == tot_feather_point)
cur_b = 0;
start_bucket_index = BUCKET_INDEX(feather_points[cur_a]);
end_bucket_index = BUCKET_INDEX(feather_points[cur_b]);
start_bucket = &buckets[start_bucket_index];
feather_bucket_check_intersect(feather_points, tot_feather_point, start_bucket, cur_a, cur_b);
if (start_bucket_index != end_bucket_index) {
FeatherEdgesBucket *end_bucket = &buckets[end_bucket_index];
FeatherEdgesBucket *diagonal_bucket_a, *diagonal_bucket_b;
feather_bucket_get_diagonal(buckets, start_bucket_index, end_bucket_index, buckets_per_side,
&diagonal_bucket_a, &diagonal_bucket_b);
feather_bucket_check_intersect(feather_points, tot_feather_point, end_bucket, cur_a, cur_b);
feather_bucket_check_intersect(feather_points, tot_feather_point, diagonal_bucket_a, cur_a, cur_b);
feather_bucket_check_intersect(feather_points, tot_feather_point, diagonal_bucket_b, cur_a, cur_b);
}
}
/* free buckets */
for (i = 0; i < tot_bucket; i++) {
if (buckets[i].segments)
MEM_freeN(buckets[i].segments);
}
MEM_freeN(buckets);
#undef BUCKET_INDEX
}
/**
* values align with #BKE_mask_spline_differentiate_with_resolution_ex
* when \a resol arguments match.
*/
float (*BKE_mask_spline_feather_differentiated_points_with_resolution_ex(MaskSpline *spline,
int *tot_feather_point,
const unsigned int resol
))[2]
{
MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
MaskSplinePoint *point, *prev;
float (*feather)[2], (*fp)[2];
const int tot = BKE_mask_spline_differentiate_calc_total(spline, resol);
int a;
/* tot+1 because of 'forward_diff_bezier' function */
feather = fp = MEM_mallocN((tot + 1) * sizeof(*feather), "mask spline feather diff points");
a = spline->tot_point - 1;
if (spline->flag & MASK_SPLINE_CYCLIC)
a++;
prev = points_array;
point = prev + 1;
while (a--) {
/* BezTriple *prevbezt; */ /* UNUSED */
/* BezTriple *bezt; */ /* UNUSED */
int j;
if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC))
point = points_array;
/* prevbezt = &prev->bezt; */
/* bezt = &point->bezt; */
for (j = 0; j < resol; j++, fp++) {
float u = (float) j / resol, weight;
float co[2], n[2];
/* TODO - these calls all calculate similar things
* could be unified for some speed */
BKE_mask_point_segment_co(spline, prev, u, co);
BKE_mask_point_normal(spline, prev, u, n);
weight = BKE_mask_point_weight(spline, prev, u);
madd_v2_v2v2fl(*fp, co, n, weight);
}
if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC) == 0) {
float u = 1.0f, weight;
float co[2], n[2];
BKE_mask_point_segment_co(spline, prev, u, co);
BKE_mask_point_normal(spline, prev, u, n);
weight = BKE_mask_point_weight(spline, prev, u);
madd_v2_v2v2fl(*fp, co, n, weight);
}
prev = point;
point++;
}
*tot_feather_point = tot;
if (spline->flag & MASK_SPLINE_NOINTERSECT)
spline_feather_collapse_inner_loops(spline, feather, tot);
return feather;
}
float (*BKE_mask_spline_feather_differentiated_points_with_resolution(MaskSpline *spline, int width, int height,
int *tot_feather_point))[2]
{
unsigned int resol = BKE_mask_spline_feather_resolution(spline, width, height);
return BKE_mask_spline_feather_differentiated_points_with_resolution_ex(spline, tot_feather_point, resol);
}
float (*BKE_mask_spline_feather_differentiated_points(MaskSpline *spline, int *tot_feather_point))[2]
{
return BKE_mask_spline_feather_differentiated_points_with_resolution(spline, 0, 0, tot_feather_point);
}
float (*BKE_mask_spline_feather_points(MaskSpline *spline, int *tot_feather_point))[2]
{
MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
int i, tot = 0;
float (*feather)[2], (*fp)[2];
/* count */
for (i = 0; i < spline->tot_point; i++) {
MaskSplinePoint *point = &points_array[i];
tot += point->tot_uw + 1;
}
/* create data */
feather = fp = MEM_mallocN(tot * sizeof(*feather), "mask spline feather points");
for (i = 0; i < spline->tot_point; i++) {
MaskSplinePoint *point = &points_array[i];
BezTriple *bezt = &point->bezt;
float weight, n[2];
int j;
BKE_mask_point_normal(spline, point, 0.0f, n);
weight = BKE_mask_point_weight(spline, point, 0.0f);
madd_v2_v2v2fl(*fp, bezt->vec[1], n, weight);
fp++;
for (j = 0; j < point->tot_uw; j++) {
float u = point->uw[j].u;
float co[2];
BKE_mask_point_segment_co(spline, point, u, co);
BKE_mask_point_normal(spline, point, u, n);
weight = BKE_mask_point_weight(spline, point, u);
madd_v2_v2v2fl(*fp, co, n, weight);
fp++;
}
}
*tot_feather_point = tot;
return feather;
}
void BKE_mask_point_direction_switch(MaskSplinePoint *point)
{
const int tot_uw = point->tot_uw;
@ -1067,73 +483,6 @@ void BKE_mask_point_set_handle(MaskSplinePoint *point, float loc[2], int keep_di
}
}
float *BKE_mask_point_segment_feather_diff_with_resolution(MaskSpline *spline, MaskSplinePoint *point,
int width, int height,
unsigned int *tot_feather_point)
{
float *feather, *fp;
unsigned int resol = BKE_mask_spline_feather_resolution(spline, width, height);
unsigned int i;
feather = fp = MEM_callocN(2 * resol * sizeof(float), "mask point spline feather diff points");
for (i = 0; i < resol; i++, fp += 2) {
float u = (float)(i % resol) / resol, weight;
float co[2], n[2];
BKE_mask_point_segment_co(spline, point, u, co);
BKE_mask_point_normal(spline, point, u, n);
weight = BKE_mask_point_weight(spline, point, u);
fp[0] = co[0] + n[0] * weight;
fp[1] = co[1] + n[1] * weight;
}
*tot_feather_point = resol;
return feather;
}
float *BKE_mask_point_segment_feather_diff(MaskSpline *spline, MaskSplinePoint *point, unsigned int *tot_feather_point)
{
return BKE_mask_point_segment_feather_diff_with_resolution(spline, point, 0, 0, tot_feather_point);
}
float *BKE_mask_point_segment_diff_with_resolution(MaskSpline *spline, MaskSplinePoint *point,
int width, int height, unsigned int *tot_diff_point)
{
MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point);
BezTriple *bezt, *bezt_next;
float *diff_points, *fp;
int j, resol = BKE_mask_spline_resolution(spline, width, height);
bezt = &point->bezt;
bezt_next = mask_spline_point_next_bezt(spline, points_array, point);
if (!bezt_next)
return NULL;
/* resol+1 because of 'forward_diff_bezier' function */
*tot_diff_point = resol + 1;
diff_points = fp = MEM_callocN((resol + 1) * 2 * sizeof(float), "mask segment vets");
for (j = 0; j < 2; j++) {
BKE_curve_forward_diff_bezier(bezt->vec[1][j], bezt->vec[2][j],
bezt_next->vec[0][j], bezt_next->vec[1][j],
fp + j, resol, 2 * sizeof(float));
}
copy_v2_v2(fp + 2 * resol, bezt_next->vec[1]);
return diff_points;
}
float *BKE_mask_point_segment_diff(MaskSpline *spline, MaskSplinePoint *point, unsigned int *tot_diff_point)
{
return BKE_mask_point_segment_diff_with_resolution(spline, point, 0, 0, tot_diff_point);
}
void BKE_mask_point_segment_co(MaskSpline *spline, MaskSplinePoint *point, float u, float co[2])
{
MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point);
@ -1141,7 +490,7 @@ void BKE_mask_point_segment_co(MaskSpline *spline, MaskSplinePoint *point, float
BezTriple *bezt = &point->bezt, *bezt_next;
float q0[2], q1[2], q2[2], r0[2], r1[2];
bezt_next = mask_spline_point_next_bezt(spline, points_array, point);
bezt_next = BKE_mask_spline_point_next_bezt(spline, points_array, point);
if (!bezt_next) {
copy_v2_v2(co, bezt->vec[1]);
@ -1165,7 +514,7 @@ void BKE_mask_point_normal(MaskSpline *spline, MaskSplinePoint *point, float u,
BezTriple *bezt = &point->bezt, *bezt_next;
float q0[2], q1[2], q2[2], r0[2], r1[2], vec[2];
bezt_next = mask_spline_point_next_bezt(spline, points_array, point);
bezt_next = BKE_mask_spline_point_next_bezt(spline, points_array, point);
if (!bezt_next) {
BKE_mask_point_handle(point, vec);
@ -1200,7 +549,7 @@ float BKE_mask_point_weight_scalar(MaskSpline *spline, MaskSplinePoint *point, c
MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point);
BezTriple *bezt = &point->bezt, *bezt_next;
bezt_next = mask_spline_point_next_bezt(spline, points_array, point);
bezt_next = BKE_mask_spline_point_next_bezt(spline, points_array, point);
if (!bezt_next) {
return bezt->weight;
@ -1221,7 +570,7 @@ float BKE_mask_point_weight(MaskSpline *spline, MaskSplinePoint *point, const fl
MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point);
BezTriple *bezt = &point->bezt, *bezt_next;
bezt_next = mask_spline_point_next_bezt(spline, points_array, point);
bezt_next = BKE_mask_spline_point_next_bezt(spline, points_array, point);
if (!bezt_next) {
return bezt->weight;
@ -1845,17 +1194,6 @@ void BKE_mask_calc_handle_point(MaskSpline *spline, MaskSplinePoint *point)
mask_calc_point_handle(point, point_prev, point_next);
}
static void enforce_dist_v2_v2fl(float v1[2], const float v2[2], const float dist)
{
if (!equals_v2v2(v2, v1)) {
float nor[2];
sub_v2_v2v2(nor, v1, v2);
normalize_v2(nor);
madd_v2_v2v2fl(v1, v2, nor, dist);
}
}
void BKE_mask_calc_handle_adjacent_interp(MaskSpline *spline, MaskSplinePoint *point, const float u)
{
/* TODO! - make this interpolate between siblings - not always midpoint! */
@ -1897,8 +1235,8 @@ void BKE_mask_calc_handle_adjacent_interp(MaskSpline *spline, MaskSplinePoint *p
length_average /= (float)length_tot;
weight_average /= (float)length_tot;
enforce_dist_v2_v2fl(point->bezt.vec[0], point->bezt.vec[1], length_average);
enforce_dist_v2_v2fl(point->bezt.vec[2], point->bezt.vec[1], length_average);
dist_ensure_v2_v2fl(point->bezt.vec[0], point->bezt.vec[1], length_average);
dist_ensure_v2_v2fl(point->bezt.vec[2], point->bezt.vec[1], length_average);
point->bezt.weight = weight_average;
}
}
@ -1930,8 +1268,8 @@ void BKE_mask_calc_handle_point_auto(MaskSpline *spline, MaskSplinePoint *point,
/* preserve length by applying it back */
if (do_recalc_length == FALSE) {
enforce_dist_v2_v2fl(point->bezt.vec[0], point->bezt.vec[1], length_average);
enforce_dist_v2_v2fl(point->bezt.vec[2], point->bezt.vec[1], length_average);
dist_ensure_v2_v2fl(point->bezt.vec[0], point->bezt.vec[1], length_average);
dist_ensure_v2_v2fl(point->bezt.vec[2], point->bezt.vec[1], length_average);
}
}

@ -0,0 +1,864 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2012 Blender Foundation.
* All rights reserved.
*
* Contributor(s): Blender Foundation,
* Sergey Sharybin,
* Campbell Barton
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/blenkernel/intern/mask_evaluate.c
* \ingroup bke
*
* Functions for evaluating the mask beziers into points for the outline and feather.
*/
#include <stddef.h>
#include <string.h>
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
#include "BLI_path_util.h"
#include "BLI_string.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "DNA_mask_types.h"
#include "DNA_node_types.h"
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "DNA_movieclip_types.h"
#include "DNA_tracking_types.h"
#include "DNA_sequence_types.h"
#include "BKE_curve.h"
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_mask.h"
#include "BKE_node.h"
#include "BKE_sequencer.h"
#include "BKE_tracking.h"
#include "BKE_movieclip.h"
#include "BKE_utildefines.h"
unsigned int BKE_mask_spline_resolution(MaskSpline *spline, int width, int height)
{
float max_segment = 0.01f;
unsigned int i, resol = 1;
if (width != 0 && height != 0) {
max_segment = 1.0f / (float)maxi(width, height);
}
for (i = 0; i < spline->tot_point; i++) {
MaskSplinePoint *point = &spline->points[i];
BezTriple *bezt_curr, *bezt_next;
float a, b, c, len;
unsigned int cur_resol;
bezt_curr = &point->bezt;
bezt_next = BKE_mask_spline_point_next_bezt(spline, spline->points, point);
if (bezt_next == NULL) {
break;
}
a = len_v3v3(bezt_curr->vec[1], bezt_curr->vec[2]);
b = len_v3v3(bezt_curr->vec[2], bezt_next->vec[0]);
c = len_v3v3(bezt_next->vec[0], bezt_next->vec[1]);
len = a + b + c;
cur_resol = len / max_segment;
resol = MAX2(resol, cur_resol);
if (resol >= MASK_RESOL_MAX) {
break;
}
}
return CLAMPIS(resol, 1, MASK_RESOL_MAX);
}
unsigned int BKE_mask_spline_feather_resolution(MaskSpline *spline, int width, int height)
{
const float max_segment = 0.005;
unsigned int resol = BKE_mask_spline_resolution(spline, width, height);
float max_jump = 0.0f;
int i;
/* avoid checking the featrher if we already hit the maximum value */
if (resol >= MASK_RESOL_MAX) {
return MASK_RESOL_MAX;
}
for (i = 0; i < spline->tot_point; i++) {
MaskSplinePoint *point = &spline->points[i];
float prev_u, prev_w;
int j;
prev_u = 0.0f;
prev_w = point->bezt.weight;
for (j = 0; j < point->tot_uw; j++) {
const float w_diff = (point->uw[j].w - prev_w);
const float u_diff = (point->uw[j].u - prev_u);
/* avoid divide by zero and very high values,
* though these get clamped eventually */
if (u_diff > FLT_EPSILON) {
float jump = fabsf(w_diff / u_diff);
max_jump = MAX2(max_jump, jump);
}
prev_u = point->uw[j].u;
prev_w = point->uw[j].w;
}
}
resol += max_jump / max_segment;
return CLAMPIS(resol, 1, MASK_RESOL_MAX);
}
int BKE_mask_spline_differentiate_calc_total(const MaskSpline *spline, const unsigned int resol)
{
if (spline->flag & MASK_SPLINE_CYCLIC) {
return spline->tot_point * resol;
}
else {
return ((spline->tot_point - 1) * resol) + 1;
}
}
float (*BKE_mask_spline_differentiate_with_resolution_ex(MaskSpline *spline,
int *tot_diff_point,
const unsigned int resol
))[2]
{
MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
MaskSplinePoint *point_curr, *point_prev;
float (*diff_points)[2], (*fp)[2];
const int tot = BKE_mask_spline_differentiate_calc_total(spline, resol);
int a;
if (spline->tot_point <= 1) {
/* nothing to differentiate */
*tot_diff_point = 0;
return NULL;
}
/* len+1 because of 'forward_diff_bezier' function */
*tot_diff_point = tot;
diff_points = fp = MEM_mallocN((tot + 1) * sizeof(*diff_points), "mask spline vets");
a = spline->tot_point - 1;
if (spline->flag & MASK_SPLINE_CYCLIC)
a++;
point_prev = points_array;
point_curr = point_prev + 1;
while (a--) {
BezTriple *bezt_prev;
BezTriple *bezt_curr;
int j;
if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC))
point_curr = points_array;
bezt_prev = &point_prev->bezt;
bezt_curr = &point_curr->bezt;
for (j = 0; j < 2; j++) {
BKE_curve_forward_diff_bezier(bezt_prev->vec[1][j], bezt_prev->vec[2][j],
bezt_curr->vec[0][j], bezt_curr->vec[1][j],
&(*fp)[j], resol, 2 * sizeof(float));
}
fp += resol;
if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC) == 0) {
copy_v2_v2(*fp, bezt_curr->vec[1]);
}
point_prev = point_curr;
point_curr++;
}
return diff_points;
}
float (*BKE_mask_spline_differentiate_with_resolution(MaskSpline *spline, int width, int height,
int *tot_diff_point
))[2]
{
int unsigned resol = BKE_mask_spline_resolution(spline, width, height);
return BKE_mask_spline_differentiate_with_resolution_ex(spline, tot_diff_point, resol);
}
float (*BKE_mask_spline_differentiate(MaskSpline *spline, int *tot_diff_point))[2]
{
return BKE_mask_spline_differentiate_with_resolution(spline, 0, 0, tot_diff_point);
}
/* ** feather points self-intersection collapse routine ** */
typedef struct FeatherEdgesBucket {
int tot_segment;
int (*segments)[2];
int alloc_segment;
} FeatherEdgesBucket;
static void feather_bucket_add_edge(FeatherEdgesBucket *bucket, int start, int end)
{
const int alloc_delta = 256;
if (bucket->tot_segment >= bucket->alloc_segment) {
if (!bucket->segments) {
bucket->segments = MEM_callocN(alloc_delta * sizeof(*bucket->segments), "feather bucket segments");
}
else {
bucket->segments = MEM_reallocN(bucket->segments,
(alloc_delta + bucket->tot_segment) * sizeof(*bucket->segments));
}
bucket->alloc_segment += alloc_delta;
}
bucket->segments[bucket->tot_segment][0] = start;
bucket->segments[bucket->tot_segment][1] = end;
bucket->tot_segment++;
}
static void feather_bucket_check_intersect(float (*feather_points)[2], int tot_feather_point, FeatherEdgesBucket *bucket,
int cur_a, int cur_b)
{
int i;
float *v1 = (float *) feather_points[cur_a];
float *v2 = (float *) feather_points[cur_b];
for (i = 0; i < bucket->tot_segment; i++) {
int check_a = bucket->segments[i][0];
int check_b = bucket->segments[i][1];
float *v3 = (float *) feather_points[check_a];
float *v4 = (float *) feather_points[check_b];
if (check_a >= cur_a - 1 || cur_b == check_a)
continue;
if (isect_seg_seg_v2(v1, v2, v3, v4)) {
int k;
float p[2];
float min_a[2], max_a[2];
float min_b[2], max_b[2];
isect_seg_seg_v2_point(v1, v2, v3, v4, p);
INIT_MINMAX2(min_a, max_a);
INIT_MINMAX2(min_b, max_b);
/* collapse loop with smaller AABB */
for (k = 0; k < tot_feather_point; k++) {
if (k >= check_b && k <= cur_a) {
DO_MINMAX2(feather_points[k], min_a, max_a);
}
else {
DO_MINMAX2(feather_points[k], min_b, max_b);
}
}
if (max_a[0] - min_a[0] < max_b[0] - min_b[0] ||
max_a[1] - min_a[1] < max_b[1] - min_b[1])
{
for (k = check_b; k <= cur_a; k++) {
copy_v2_v2(feather_points[k], p);
}
}
else {
for (k = 0; k <= check_a; k++) {
copy_v2_v2(feather_points[k], p);
}
if (cur_b != 0) {
for (k = cur_b; k < tot_feather_point; k++) {
copy_v2_v2(feather_points[k], p);
}
}
}
}
}
}
static int feather_bucket_index_from_coord(float co[2], const float min[2], const float bucket_scale[2],
const int buckets_per_side)
{
int x = (int) ((co[0] - min[0]) * bucket_scale[0]);
int y = (int) ((co[1] - min[1]) * bucket_scale[1]);
if (x == buckets_per_side)
x--;
if (y == buckets_per_side)
y--;
return y * buckets_per_side + x;
}
static void feather_bucket_get_diagonal(FeatherEdgesBucket *buckets, int start_bucket_index, int end_bucket_index,
int buckets_per_side, FeatherEdgesBucket **diagonal_bucket_a_r,
FeatherEdgesBucket **diagonal_bucket_b_r)
{
int start_bucket_x = start_bucket_index % buckets_per_side;
int start_bucket_y = start_bucket_index / buckets_per_side;
int end_bucket_x = end_bucket_index % buckets_per_side;
int end_bucket_y = end_bucket_index / buckets_per_side;
int diagonal_bucket_a_index = start_bucket_y * buckets_per_side + end_bucket_x;
int diagonal_bucket_b_index = end_bucket_y * buckets_per_side + start_bucket_x;
*diagonal_bucket_a_r = &buckets[diagonal_bucket_a_index];
*diagonal_bucket_b_r = &buckets[diagonal_bucket_b_index];
}
void BKE_mask_spline_feather_collapse_inner_loops(MaskSpline *spline, float (*feather_points)[2], const int tot_feather_point)
{
#define BUCKET_INDEX(co) \
feather_bucket_index_from_coord(co, min, bucket_scale, buckets_per_side)
int buckets_per_side, tot_bucket;
float bucket_size, bucket_scale[2];
FeatherEdgesBucket *buckets;
int i;
float min[2], max[2];
float max_delta_x = -1.0f, max_delta_y = -1.0f, max_delta;
if (tot_feather_point < 4) {
/* self-intersection works only for quads at least,
* in other cases polygon can't be self-intersecting anyway
*/
return;
}
/* find min/max corners of mask to build buckets in that space */
INIT_MINMAX2(min, max);
for (i = 0; i < tot_feather_point; i++) {
int next = i + 1;
float delta;
DO_MINMAX2(feather_points[i], min, max);
if (next == tot_feather_point) {
if (spline->flag & MASK_SPLINE_CYCLIC)
next = 0;
else
break;
}
delta = fabsf(feather_points[i][0] - feather_points[next][0]);
if (delta > max_delta_x)
max_delta_x = delta;
delta = fabsf(feather_points[i][1] - feather_points[next][1]);
if (delta > max_delta_y)
max_delta_y = delta;
}
/* prevent divisionsby zero by ensuring bounding box is not collapsed */
if (max[0] - min[0] < FLT_EPSILON) {
max[0] += 0.01f;
min[0] -= 0.01f;
}
if (max[1] - min[1] < FLT_EPSILON) {
max[1] += 0.01f;
min[1] -= 0.01f;
}
/* use dynamically calculated buckets per side, so we likely wouldn't
* run into a situation when segment doesn't fit two buckets which is
* pain collecting candidates for intersection
*/
max_delta_x /= max[0] - min[0];
max_delta_y /= max[1] - min[1];
max_delta = MAX2(max_delta_x, max_delta_y);
buckets_per_side = MIN2(512, 0.9f / max_delta);
if (buckets_per_side == 0) {
/* happens when some segment fills the whole bounding box across some of dimension */
buckets_per_side = 1;
}
tot_bucket = buckets_per_side * buckets_per_side;
bucket_size = 1.0f / buckets_per_side;
/* pre-compute multipliers, to save mathematical operations in loops */
bucket_scale[0] = 1.0f / ((max[0] - min[0]) * bucket_size);
bucket_scale[1] = 1.0f / ((max[1] - min[1]) * bucket_size);
/* fill in buckets' edges */
buckets = MEM_callocN(sizeof(FeatherEdgesBucket) * tot_bucket, "feather buckets");
for (i = 0; i < tot_feather_point; i++) {
int start = i, end = i + 1;
int start_bucket_index, end_bucket_index;
if (end == tot_feather_point) {
if (spline->flag & MASK_SPLINE_CYCLIC)
end = 0;
else
break;
}
start_bucket_index = BUCKET_INDEX(feather_points[start]);
end_bucket_index = BUCKET_INDEX(feather_points[end]);
feather_bucket_add_edge(&buckets[start_bucket_index], start, end);
if (start_bucket_index != end_bucket_index) {
FeatherEdgesBucket *end_bucket = &buckets[end_bucket_index];
FeatherEdgesBucket *diagonal_bucket_a, *diagonal_bucket_b;
feather_bucket_get_diagonal(buckets, start_bucket_index, end_bucket_index, buckets_per_side,
&diagonal_bucket_a, &diagonal_bucket_b);
feather_bucket_add_edge(end_bucket, start, end);
feather_bucket_add_edge(diagonal_bucket_a, start, end);
feather_bucket_add_edge(diagonal_bucket_a, start, end);
}
}
/* check all edges for intersection with edges from their buckets */
for (i = 0; i < tot_feather_point; i++) {
int cur_a = i, cur_b = i + 1;
int start_bucket_index, end_bucket_index;
FeatherEdgesBucket *start_bucket;
if (cur_b == tot_feather_point)
cur_b = 0;
start_bucket_index = BUCKET_INDEX(feather_points[cur_a]);
end_bucket_index = BUCKET_INDEX(feather_points[cur_b]);
start_bucket = &buckets[start_bucket_index];
feather_bucket_check_intersect(feather_points, tot_feather_point, start_bucket, cur_a, cur_b);
if (start_bucket_index != end_bucket_index) {
FeatherEdgesBucket *end_bucket = &buckets[end_bucket_index];
FeatherEdgesBucket *diagonal_bucket_a, *diagonal_bucket_b;
feather_bucket_get_diagonal(buckets, start_bucket_index, end_bucket_index, buckets_per_side,
&diagonal_bucket_a, &diagonal_bucket_b);
feather_bucket_check_intersect(feather_points, tot_feather_point, end_bucket, cur_a, cur_b);
feather_bucket_check_intersect(feather_points, tot_feather_point, diagonal_bucket_a, cur_a, cur_b);
feather_bucket_check_intersect(feather_points, tot_feather_point, diagonal_bucket_b, cur_a, cur_b);
}
}
/* free buckets */
for (i = 0; i < tot_bucket; i++) {
if (buckets[i].segments)
MEM_freeN(buckets[i].segments);
}
MEM_freeN(buckets);
#undef BUCKET_INDEX
}
/** only called from #BKE_mask_spline_feather_differentiated_points_with_resolution_ex() ! */
static float (*mask_spline_feather_differentiated_points_with_resolution_ex__even(MaskSpline *spline,
int *tot_feather_point,
const unsigned int resol,
const int do_feather_isect
))[2]
{
MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
MaskSplinePoint *point_curr, *point_prev;
float (*feather)[2], (*fp)[2];
const int tot = BKE_mask_spline_differentiate_calc_total(spline, resol);
int a;
/* tot+1 because of 'forward_diff_bezier' function */
feather = fp = MEM_mallocN((tot + 1) * sizeof(*feather), "mask spline feather diff points");
a = spline->tot_point - 1;
if (spline->flag & MASK_SPLINE_CYCLIC)
a++;
point_prev = points_array;
point_curr = point_prev + 1;
while (a--) {
/* BezTriple *bezt_prev; */ /* UNUSED */
/* BezTriple *bezt_curr; */ /* UNUSED */
int j;
if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC))
point_curr = points_array;
/* bezt_prev = &point_prev->bezt; */
/* bezt_curr = &point_curr->bezt; */
for (j = 0; j < resol; j++, fp++) {
float u = (float) j / resol, weight;
float co[2], n[2];
/* TODO - these calls all calculate similar things
* could be unified for some speed */
BKE_mask_point_segment_co(spline, point_prev, u, co);
BKE_mask_point_normal(spline, point_prev, u, n);
weight = BKE_mask_point_weight(spline, point_prev, u);
madd_v2_v2v2fl(*fp, co, n, weight);
}
if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC) == 0) {
float u = 1.0f, weight;
float co[2], n[2];
BKE_mask_point_segment_co(spline, point_prev, u, co);
BKE_mask_point_normal(spline, point_prev, u, n);
weight = BKE_mask_point_weight(spline, point_prev, u);
madd_v2_v2v2fl(*fp, co, n, weight);
}
point_prev = point_curr;
point_curr++;
}
*tot_feather_point = tot;
if ((spline->flag & MASK_SPLINE_NOINTERSECT) && do_feather_isect) {
BKE_mask_spline_feather_collapse_inner_loops(spline, feather, tot);
}
return feather;
}
/** only called from #BKE_mask_spline_feather_differentiated_points_with_resolution_ex() ! */
static float (*mask_spline_feather_differentiated_points_with_resolution_ex__double(MaskSpline *spline,
int *tot_feather_point,
const unsigned int resol,
const int do_feather_isect
))[2]
{
MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
MaskSplinePoint *point_curr, *point_prev;
float (*feather)[2], (*fp)[2];
const int tot = BKE_mask_spline_differentiate_calc_total(spline, resol);
int a;
if (spline->tot_point <= 1) {
/* nothing to differentiate */
*tot_feather_point = 0;
return NULL;
}
/* len+1 because of 'forward_diff_bezier' function */
*tot_feather_point = tot;
feather = fp = MEM_mallocN((tot + 1) * sizeof(*feather), "mask spline vets");
a = spline->tot_point - 1;
if (spline->flag & MASK_SPLINE_CYCLIC)
a++;
point_prev = points_array;
point_curr = point_prev + 1;
while (a--) {
BezTriple local_prevbezt;
BezTriple local_bezt;
float point_prev_n[2], point_curr_n[2], tvec[2];
float weight_prev, weight_curr;
float len_base, len_feather, len_scalar;
BezTriple *bezt_prev;
BezTriple *bezt_curr;
int j;
if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC))
point_curr = points_array;
bezt_prev = &point_prev->bezt;
bezt_curr = &point_curr->bezt;
/* modified copy for feather */
local_prevbezt = *bezt_prev;
local_bezt = *bezt_curr;
bezt_prev = &local_prevbezt;
bezt_curr = &local_bezt;
/* calc the normals */
sub_v2_v2v2(tvec, bezt_prev->vec[1], bezt_prev->vec[0]);
normalize_v2(tvec);
point_prev_n[0] = -tvec[1];
point_prev_n[1] = tvec[0];
sub_v2_v2v2(tvec, bezt_curr->vec[1], bezt_curr->vec[0]);
normalize_v2(tvec);
point_curr_n[0] = -tvec[1];
point_curr_n[1] = tvec[0];
weight_prev = bezt_prev->weight;
weight_curr = bezt_curr->weight;
mul_v2_fl(point_prev_n, weight_prev);
mul_v2_fl(point_curr_n, weight_curr);
/* before we transform verts */
len_base = len_v2v2(bezt_prev->vec[1], bezt_curr->vec[1]);
// add_v2_v2(bezt_prev->vec[0], point_prev_n); // not needed
add_v2_v2(bezt_prev->vec[1], point_prev_n);
add_v2_v2(bezt_prev->vec[2], point_prev_n);
add_v2_v2(bezt_curr->vec[0], point_curr_n);
add_v2_v2(bezt_curr->vec[1], point_curr_n);
// add_v2_v2(bezt_curr->vec[2], point_curr_n); // not needed
len_feather = len_v2v2(bezt_prev->vec[1], bezt_curr->vec[1]);
/* scale by chane in length */
len_scalar = len_feather / len_base;
dist_ensure_v2_v2fl(bezt_prev->vec[2], bezt_prev->vec[1], len_scalar * len_v2v2(bezt_prev->vec[2], bezt_prev->vec[1]));
dist_ensure_v2_v2fl(bezt_curr->vec[0], bezt_curr->vec[1], len_scalar * len_v2v2(bezt_curr->vec[0], bezt_curr->vec[1]));
for (j = 0; j < 2; j++) {
BKE_curve_forward_diff_bezier(bezt_prev->vec[1][j], bezt_prev->vec[2][j],
bezt_curr->vec[0][j], bezt_curr->vec[1][j],
&(*fp)[j], resol, 2 * sizeof(float));
}
/* scale by the uw's */
if (point_prev->tot_uw) {
for (j = 0; j < resol; j++, fp++) {
float u = (float) j / resol;
float weight_uw, weight_scalar;
float co[2];
/* TODO - these calls all calculate similar things
* could be unified for some speed */
BKE_mask_point_segment_co(spline, point_prev, u, co);
weight_uw = BKE_mask_point_weight(spline, point_prev, u);
weight_scalar = BKE_mask_point_weight_scalar(spline, point_prev, u);
dist_ensure_v2_v2fl(*fp, co, len_v2v2(*fp, co) * (weight_uw / weight_scalar));
}
}
else {
fp += resol;
}
if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC) == 0) {
copy_v2_v2(*fp, bezt_curr->vec[1]);
}
point_prev = point_curr;
point_curr++;
}
if ((spline->flag & MASK_SPLINE_NOINTERSECT) && do_feather_isect) {
BKE_mask_spline_feather_collapse_inner_loops(spline, feather, tot);
}
return feather;
}
/**
* values align with #BKE_mask_spline_differentiate_with_resolution_ex
* when \a resol arguments match.
*/
float (*BKE_mask_spline_feather_differentiated_points_with_resolution_ex(MaskSpline *spline,
int *tot_feather_point,
const unsigned int resol,
const int do_feather_isect
))[2]
{
switch (spline->offset_mode) {
case MASK_SPLINE_OFFSET_EVEN:
return mask_spline_feather_differentiated_points_with_resolution_ex__even(spline, tot_feather_point, resol, do_feather_isect);
break;
case MASK_SPLINE_OFFSET_SMOOTH:
default:
return mask_spline_feather_differentiated_points_with_resolution_ex__double(spline, tot_feather_point, resol, do_feather_isect);
break;
}
}
float (*BKE_mask_spline_feather_differentiated_points_with_resolution(MaskSpline *spline, int width, int height,
int *tot_feather_point, const int do_feather_isect))[2]
{
unsigned int resol = BKE_mask_spline_feather_resolution(spline, width, height);
return BKE_mask_spline_feather_differentiated_points_with_resolution_ex(spline, tot_feather_point, resol, do_feather_isect);
}
float (*BKE_mask_spline_feather_differentiated_points(MaskSpline *spline, int *tot_feather_point))[2]
{
return BKE_mask_spline_feather_differentiated_points_with_resolution(spline, 0, 0, tot_feather_point, TRUE);
}
float (*BKE_mask_spline_feather_points(MaskSpline *spline, int *tot_feather_point))[2]
{
MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
int i, tot = 0;
float (*feather)[2], (*fp)[2];
/* count */
for (i = 0; i < spline->tot_point; i++) {
MaskSplinePoint *point = &points_array[i];
tot += point->tot_uw + 1;
}
/* create data */
feather = fp = MEM_mallocN(tot * sizeof(*feather), "mask spline feather points");
for (i = 0; i < spline->tot_point; i++) {
MaskSplinePoint *point = &points_array[i];
BezTriple *bezt = &point->bezt;
float weight, n[2];
int j;
BKE_mask_point_normal(spline, point, 0.0f, n);
weight = BKE_mask_point_weight(spline, point, 0.0f);
madd_v2_v2v2fl(*fp, bezt->vec[1], n, weight);
fp++;
for (j = 0; j < point->tot_uw; j++) {
float u = point->uw[j].u;
float co[2];
BKE_mask_point_segment_co(spline, point, u, co);
BKE_mask_point_normal(spline, point, u, n);
weight = BKE_mask_point_weight(spline, point, u);
madd_v2_v2v2fl(*fp, co, n, weight);
fp++;
}
}
*tot_feather_point = tot;
return feather;
}
/* *** mask point functions which involve evaluation *** */
float *BKE_mask_point_segment_feather_diff_with_resolution(MaskSpline *spline, MaskSplinePoint *point,
int width, int height,
unsigned int *tot_feather_point)
{
float *feather, *fp;
unsigned int resol = BKE_mask_spline_feather_resolution(spline, width, height);
unsigned int i;
feather = fp = MEM_callocN(2 * resol * sizeof(float), "mask point spline feather diff points");
for (i = 0; i < resol; i++, fp += 2) {
float u = (float)(i % resol) / resol, weight;
float co[2], n[2];
BKE_mask_point_segment_co(spline, point, u, co);
BKE_mask_point_normal(spline, point, u, n);
weight = BKE_mask_point_weight(spline, point, u);
fp[0] = co[0] + n[0] * weight;
fp[1] = co[1] + n[1] * weight;
}
*tot_feather_point = resol;
return feather;
}
float *BKE_mask_point_segment_feather_diff(MaskSpline *spline, MaskSplinePoint *point, unsigned int *tot_feather_point)
{
return BKE_mask_point_segment_feather_diff_with_resolution(spline, point, 0, 0, tot_feather_point);
}
float *BKE_mask_point_segment_diff_with_resolution(MaskSpline *spline, MaskSplinePoint *point,
int width, int height, unsigned int *tot_diff_point)
{
MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point);
BezTriple *bezt, *bezt_next;
float *diff_points, *fp;
int j, resol = BKE_mask_spline_resolution(spline, width, height);
bezt = &point->bezt;
bezt_next = BKE_mask_spline_point_next_bezt(spline, points_array, point);
if (!bezt_next)
return NULL;
/* resol+1 because of 'forward_diff_bezier' function */
*tot_diff_point = resol + 1;
diff_points = fp = MEM_callocN((resol + 1) * 2 * sizeof(float), "mask segment vets");
for (j = 0; j < 2; j++) {
BKE_curve_forward_diff_bezier(bezt->vec[1][j], bezt->vec[2][j],
bezt_next->vec[0][j], bezt_next->vec[1][j],
fp + j, resol, 2 * sizeof(float));
}
copy_v2_v2(fp + 2 * resol, bezt_next->vec[1]);
return diff_points;
}
float *BKE_mask_point_segment_diff(MaskSpline *spline, MaskSplinePoint *point, unsigned int *tot_diff_point)
{
return BKE_mask_point_segment_diff_with_resolution(spline, point, 0, 0, tot_diff_point);
}

@ -370,8 +370,8 @@ static void layer_bucket_init(MaskRasterLayer *layer, const float pixel_size)
{
MemArena *arena = BLI_memarena_new(1 << 16, __func__);
const float bucket_dim_x = layer->bounds.xmax - layer->bounds.xmin;
const float bucket_dim_y = layer->bounds.ymax - layer->bounds.ymin;
const float bucket_dim_x = BLI_RCT_SIZE_X(&layer->bounds);
const float bucket_dim_y = BLI_RCT_SIZE_Y(&layer->bounds);
layer->buckets_x = (bucket_dim_x / pixel_size) / (float)BUCKET_PIXELS_PER_CELL;
layer->buckets_y = (bucket_dim_y / pixel_size) / (float)BUCKET_PIXELS_PER_CELL;
@ -575,6 +575,7 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mas
int tot_diff_point;
float (*diff_feather_points)[2];
float (*diff_feather_points_flip)[2];
int tot_diff_feather_points;
const unsigned int resol_a = BKE_mask_spline_resolution(spline, width, height) / 4;
@ -586,7 +587,7 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mas
if (do_feather) {
diff_feather_points = BKE_mask_spline_feather_differentiated_points_with_resolution_ex(
spline, &tot_diff_feather_points, resol);
spline, &tot_diff_feather_points, resol, FALSE);
BLI_assert(diff_feather_points);
}
else {
@ -649,6 +650,11 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mas
}
if (is_fill) {
/* applt intersections depending on fill settings */
if (spline->flag & MASK_SPLINE_NOINTERSECT) {
BKE_mask_spline_feather_collapse_inner_loops(spline, diff_feather_points, tot_diff_feather_points);
}
copy_v2_v2(co, diff_points[0]);
sf_vert_prev = BLI_scanfill_vert_add(&sf_ctx, co);
sf_vert_prev->tmp.u = sf_vert_tot;
@ -710,11 +716,27 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mas
/* unfilled spline */
if (diff_feather_points) {
float co_diff[3];
float co_diff[2];
float co_feather[3];
co_feather[2] = 1.0f;
if (spline->flag & MASK_SPLINE_NOINTERSECT) {
diff_feather_points_flip = MEM_mallocN(sizeof(float) * 2 * tot_diff_feather_points, "diff_feather_points_flip");
for (j = 0; j < tot_diff_point; j++) {
sub_v2_v2v2(co_diff, diff_points[j], diff_feather_points[j]);
add_v2_v2v2(diff_feather_points_flip[j], diff_points[j], co_diff);
}
BKE_mask_spline_feather_collapse_inner_loops(spline, diff_feather_points, tot_diff_feather_points);
BKE_mask_spline_feather_collapse_inner_loops(spline, diff_feather_points_flip, tot_diff_feather_points);
}
else {
diff_feather_points_flip = NULL;
}
open_spline_ranges[open_spline_index].vertex_offset = sf_vert_tot;
open_spline_ranges[open_spline_index].vertex_total = tot_diff_point;
@ -738,8 +760,14 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mas
/* feather vert B */
sub_v2_v2v2(co_diff, co, co_feather);
add_v2_v2v2(co_feather, co, co_diff);
if (diff_feather_points_flip) {
copy_v2_v2(co_feather, diff_feather_points_flip[j]);
}
else {
sub_v2_v2v2(co_diff, co, co_feather);
add_v2_v2v2(co_feather, co, co_diff);
}
sf_vert = BLI_scanfill_vert_add(&sf_ctx, co_feather);
sf_vert->tmp.u = sf_vert_tot;
sf_vert->keyindex = SF_KEYINDEX_TEMP_ID;
@ -752,6 +780,11 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mas
tot_feather_quads -= 2;
}
if (diff_feather_points_flip) {
MEM_freeN(diff_feather_points_flip);
diff_feather_points_flip = NULL;
}
/* cap ends */
/* dummy init value */
@ -1163,7 +1196,7 @@ static float maskrasterize_layer_isect(unsigned int *face, float (*cos)[3], cons
BLI_INLINE unsigned int layer_bucket_index_from_xy(MaskRasterLayer *layer, const float xy[2])
{
BLI_assert(BLI_in_rctf_v(&layer->bounds, xy));
BLI_assert(BLI_rctf_isect_pt_v(&layer->bounds, xy));
return ( (unsigned int)((xy[0] - layer->bounds.xmin) * layer->buckets_xy_scalar[0])) +
(((unsigned int)((xy[1] - layer->bounds.ymin) * layer->buckets_xy_scalar[1])) * layer->buckets_x);
@ -1200,7 +1233,7 @@ static float layer_bucket_depth_from_xy(MaskRasterLayer *layer, const float xy[2
float BKE_maskrasterize_handle_sample(MaskRasterHandle *mr_handle, const float xy[2])
{
/* can't do this because some layers may invert */
/* if (BLI_in_rctf_v(&mr_handle->bounds, xy)) */
/* if (BLI_rctf_isect_pt_v(&mr_handle->bounds, xy)) */
const unsigned int layers_tot = mr_handle->layers_tot;
unsigned int i;
@ -1213,7 +1246,7 @@ float BKE_maskrasterize_handle_sample(MaskRasterHandle *mr_handle, const float x
float value_layer;
/* also used as signal for unused layer (when render is disabled) */
if (layer->alpha != 0.0f && BLI_in_rctf_v(&layer->bounds, xy)) {
if (layer->alpha != 0.0f && BLI_rctf_isect_pt_v(&layer->bounds, xy)) {
value_layer = 1.0f - layer_bucket_depth_from_xy(layer, xy);
switch (layer->falloff) {
@ -1249,9 +1282,12 @@ float BKE_maskrasterize_handle_sample(MaskRasterHandle *mr_handle, const float x
}
switch (layer->blend) {
case MASK_BLEND_MERGE:
case MASK_BLEND_MERGE_ADD:
value += value_layer * (1.0f - value);
break;
case MASK_BLEND_MERGE_SUBTRACT:
value -= value_layer * value;
break;
case MASK_BLEND_ADD:
value += value_layer;
break;

@ -79,13 +79,19 @@ void init_def_material(void)
/* not material itself */
void BKE_material_free(Material *ma)
{
BKE_material_free_ex(ma, TRUE);
}
/* not material itself */
void BKE_material_free_ex(Material *ma, int do_id_user)
{
MTex *mtex;
int a;
for (a = 0; a < MAX_MTEX; a++) {
mtex = ma->mtex[a];
if (mtex && mtex->tex) mtex->tex->id.us--;
if (do_id_user && mtex && mtex->tex) mtex->tex->id.us--;
if (mtex) MEM_freeN(mtex);
}
@ -101,7 +107,7 @@ void BKE_material_free(Material *ma)
/* is no lib link block, but material extension */
if (ma->nodetree) {
ntreeFreeTree(ma->nodetree);
ntreeFreeTree_ex(ma->nodetree, do_id_user);
MEM_freeN(ma->nodetree);
}
@ -236,7 +242,7 @@ Material *BKE_material_copy(Material *ma)
if (ma->preview) man->preview = BKE_previewimg_copy(ma->preview);
if (ma->nodetree) {
man->nodetree = ntreeCopyTree(ma->nodetree); /* 0 == full new tree */
man->nodetree = ntreeCopyTree(ma->nodetree);
}
man->gpumaterial.first = man->gpumaterial.last = NULL;
@ -808,7 +814,7 @@ void assign_material(Object *ob, Material *ma, short act, int assign_type)
*totcolp = act;
}
// Determine the object/mesh linking
/* Determine the object/mesh linking */
if (assign_type == BKE_MAT_ASSIGN_USERPREF && ob->totcol && ob->actcol) {
/* copy from previous material */
bit = ob->matbits[ob->actcol - 1];
@ -1484,7 +1490,11 @@ void ramp_blend(int type, float r_col[3], const float fac, const float col[3])
}
}
/* copy/paste buffer, if we had a propper py api that would be better */
/**
* \brief copy/paste buffer, if we had a propper py api that would be better
* \note matcopybuf.nodetree does _NOT_ use ID's
* \todo matcopybuf.nodetree's node->id's are NOT validated, this will crash!
*/
static Material matcopybuf;
static short matcopied = 0;
@ -1512,7 +1522,7 @@ void free_matcopybuf(void)
matcopybuf.ramp_spec = NULL;
if (matcopybuf.nodetree) {
ntreeFreeTree(matcopybuf.nodetree);
ntreeFreeTree_ex(matcopybuf.nodetree, FALSE);
MEM_freeN(matcopybuf.nodetree);
matcopybuf.nodetree = NULL;
}
@ -1538,7 +1548,7 @@ void copy_matcopybuf(Material *ma)
matcopybuf.mtex[a] = MEM_dupallocN(mtex);
}
}
matcopybuf.nodetree = ntreeCopyTree(ma->nodetree);
matcopybuf.nodetree = ntreeCopyTree_ex(ma->nodetree, FALSE);
matcopybuf.preview = NULL;
matcopybuf.gpumaterial.first = matcopybuf.gpumaterial.last = NULL;
matcopied = 1;
@ -1583,7 +1593,7 @@ void paste_matcopybuf(Material *ma)
}
}
ma->nodetree = ntreeCopyTree(matcopybuf.nodetree);
ma->nodetree = ntreeCopyTree_ex(matcopybuf.nodetree, FALSE);
}
@ -1624,7 +1634,7 @@ static void decode_tfaceflag(Material *ma, int flag, int convertall)
/* flag is shifted in 1 to make 0 != no flag yet (see encode_tfaceflag) */
flag -= 1;
alphablend = flag >> 15; //encoded in the encode_tfaceflag function
alphablend = flag >> 15; /* encoded in the encode_tfaceflag function */
(*game).flag = 0;
/* General Material Options */
@ -2024,8 +2034,7 @@ int do_version_tface(Main *main, int fileload)
nowarning = 0;
}
else
convert_tfacematerial(main, ma);
continue;
convert_tfacematerial(main, ma); continue;
}
/* no conflicts in this material - 90% of cases

@ -67,12 +67,9 @@
/* Data types */
typedef struct point { /* a three-dimensional point */
float x, y, z; /* its coordinates */
} MB_POINT;
typedef struct vertex { /* surface vertex */
MB_POINT position, normal; /* position and surface normal */
float co[3]; /* position and surface normal */
float no[3];
} VERTEX;
typedef struct vertices { /* list of vertices in polygonization */
@ -82,7 +79,7 @@ typedef struct vertices { /* list of vertices in polygonization */
typedef struct corner { /* corner of a cube */
int i, j, k; /* (i, j, k) is index within lattice */
float x, y, z, value; /* location and function value */
float co[3], value; /* location and function value */
struct corner *next;
} CORNER;
@ -159,11 +156,11 @@ struct pgn_elements {
};
/* Forward declarations */
static int vertid(CORNER *c1, CORNER *c2, PROCESS *p, MetaBall *mb);
static int vertid(const CORNER *c1, const CORNER *c2, PROCESS *p, MetaBall *mb);
static int setcenter(CENTERLIST *table[], int i, int j, int k);
static CORNER *setcorner(PROCESS *p, int i, int j, int k);
static void converge(MB_POINT *p1, MB_POINT *p2, float v1, float v2,
float (*function)(float, float, float), MB_POINT *p, MetaBall *mb, int f);
static void converge(const float p1[3], const float p2[3], float v1, float v2,
float (*function)(float, float, float), float p[3], MetaBall *mb, int f);
/* Global variables */
@ -631,77 +628,70 @@ static void calc_mballco(MetaElem *ml, float vec[3])
static float densfunc(MetaElem *ball, float x, float y, float z)
{
float dist2 = 0.0, dx, dy, dz;
float vec[3];
float dist2;
float dvec[3] = {x, y, z};
vec[0] = x;
vec[1] = y;
vec[2] = z;
mul_m4_v3((float (*)[4])ball->imat, vec);
dx = vec[0];
dy = vec[1];
dz = vec[2];
mul_m4_v3((float (*)[4])ball->imat, dvec);
if (ball->type == MB_BALL) {
}
else if (ball->type == MB_TUBEX) {
if (dx > ball->len) dx -= ball->len;
else if (dx < -ball->len) dx += ball->len;
else dx = 0.0;
}
else if (ball->type == MB_TUBEY) {
if (dy > ball->len) dy -= ball->len;
else if (dy < -ball->len) dy += ball->len;
else dy = 0.0;
}
else if (ball->type == MB_TUBEZ) {
if (dz > ball->len) dz -= ball->len;
else if (dz < -ball->len) dz += ball->len;
else dz = 0.0;
}
else if (ball->type == MB_TUBE) {
if (dx > ball->expx) dx -= ball->expx;
else if (dx < -ball->expx) dx += ball->expx;
else dx = 0.0;
}
else if (ball->type == MB_PLANE) {
if (dx > ball->expx) dx -= ball->expx;
else if (dx < -ball->expx) dx += ball->expx;
else dx = 0.0;
if (dy > ball->expy) dy -= ball->expy;
else if (dy < -ball->expy) dy += ball->expy;
else dy = 0.0;
}
else if (ball->type == MB_ELIPSOID) {
dx *= 1 / ball->expx;
dy *= 1 / ball->expy;
dz *= 1 / ball->expz;
}
else if (ball->type == MB_CUBE) {
if (dx > ball->expx) dx -= ball->expx;
else if (dx < -ball->expx) dx += ball->expx;
else dx = 0.0;
if (dy > ball->expy) dy -= ball->expy;
else if (dy < -ball->expy) dy += ball->expy;
else dy = 0.0;
if (dz > ball->expz) dz -= ball->expz;
else if (dz < -ball->expz) dz += ball->expz;
else dz = 0.0;
switch (ball->type) {
case MB_BALL:
/* do nothing */
break;
case MB_TUBEX:
if (dvec[0] > ball->len) dvec[0] -= ball->len;
else if (dvec[0] < -ball->len) dvec[0] += ball->len;
else dvec[0] = 0.0;
break;
case MB_TUBEY:
if (dvec[1] > ball->len) dvec[1] -= ball->len;
else if (dvec[1] < -ball->len) dvec[1] += ball->len;
else dvec[1] = 0.0;
break;
case MB_TUBEZ:
if (dvec[2] > ball->len) dvec[2] -= ball->len;
else if (dvec[2] < -ball->len) dvec[2] += ball->len;
else dvec[2] = 0.0;
break;
case MB_TUBE:
if (dvec[0] > ball->expx) dvec[0] -= ball->expx;
else if (dvec[0] < -ball->expx) dvec[0] += ball->expx;
else dvec[0] = 0.0;
break;
case MB_PLANE:
if (dvec[0] > ball->expx) dvec[0] -= ball->expx;
else if (dvec[0] < -ball->expx) dvec[0] += ball->expx;
else dvec[0] = 0.0;
if (dvec[1] > ball->expy) dvec[1] -= ball->expy;
else if (dvec[1] < -ball->expy) dvec[1] += ball->expy;
else dvec[1] = 0.0;
break;
case MB_ELIPSOID:
dvec[0] /= ball->expx;
dvec[1] /= ball->expy;
dvec[2] /= ball->expz;
break;
case MB_CUBE:
if (dvec[0] > ball->expx) dvec[0] -= ball->expx;
else if (dvec[0] < -ball->expx) dvec[0] += ball->expx;
else dvec[0] = 0.0;
if (dvec[1] > ball->expy) dvec[1] -= ball->expy;
else if (dvec[1] < -ball->expy) dvec[1] += ball->expy;
else dvec[1] = 0.0;
if (dvec[2] > ball->expz) dvec[2] -= ball->expz;
else if (dvec[2] < -ball->expz) dvec[2] += ball->expz;
else dvec[2] = 0.0;
break;
}
dist2 = (dx * dx + dy * dy + dz * dz);
dist2 = 1.0f - (len_v3(dvec) / ball->rad2);
if (ball->flag & MB_NEGATIVE) {
dist2 = 1.0f - (dist2 / ball->rad2);
if (dist2 < 0.0f) return 0.5f;
return 0.5f - ball->s * dist2 * dist2 * dist2;
if ((ball->flag & MB_NEGATIVE) == 0) {
return (dist2 < 0.0f) ? -0.5f : (ball->s * dist2 * dist2 * dist2) - 0.5f;
}
else {
dist2 = 1.0f - (dist2 / ball->rad2);
if (dist2 < 0.0f) return -0.5f;
return ball->s * dist2 * dist2 * dist2 - 0.5f;
return (dist2 < 0.0f) ? 0.5f : 0.5f - (ball->s * dist2 * dist2 * dist2);
}
}
@ -784,15 +774,12 @@ static float metaball(float x, float y, float z)
if (totelem > 1) {
node = find_metaball_octal_node(metaball_tree->first, x, y, z, metaball_tree->depth);
if (node) {
ml_p = node->elems.first;
while (ml_p) {
for (ml_p = node->elems.first; ml_p; ml_p = ml_p->next) {
dens += densfunc(ml_p->ml, x, y, z);
ml_p = ml_p->next;
}
dens += -0.5f * (metaball_tree->pos - node->pos);
dens += 0.5f * (metaball_tree->neg - node->neg);
dens += 0.5f * (metaball_tree->neg - node->neg);
}
else {
for (a = 0; a < totelem; a++) {
@ -1074,12 +1061,12 @@ static CORNER *setcorner(PROCESS *p, int i, int j, int k)
c = (CORNER *) new_pgn_element(sizeof(CORNER));
c->i = i;
c->x = ((float)i - 0.5f) * p->size;
c->co[0] = ((float)i - 0.5f) * p->size;
c->j = j;
c->y = ((float)j - 0.5f) * p->size;
c->co[1] = ((float)j - 0.5f) * p->size;
c->k = k;
c->z = ((float)k - 0.5f) * p->size;
c->value = p->function(c->x, c->y, c->z);
c->co[2] = ((float)k - 0.5f) * p->size;
c->value = p->function(c->co[0], c->co[1], c->co[2]);
c->next = p->corners[index];
p->corners[index] = c;
@ -1204,7 +1191,7 @@ void BKE_mball_cubeTable_free(void)
/* setcenter: set (i, j, k) entry of table[]
* return 1 if already set; otherwise, set and return 0 */
static int setcenter(CENTERLIST *table[], int i, int j, int k)
static int setcenter(CENTERLIST *table[], const int i, const int j, const int k)
{
int index;
CENTERLIST *newc, *l, *q;
@ -1324,72 +1311,46 @@ static void addtovertices(VERTICES *vertices, VERTEX v)
/* vnormal: compute unit length surface normal at point */
static void vnormal(MB_POINT *point, PROCESS *p, MB_POINT *v)
static void vnormal(const float point[3], PROCESS *p, float r_no[3])
{
float delta = 0.2f * p->delta;
float f = p->function(point->x, point->y, point->z);
float f = p->function(point[0], point[1], point[2]);
v->x = p->function(point->x + delta, point->y, point->z) - f;
v->y = p->function(point->x, point->y + delta, point->z) - f;
v->z = p->function(point->x, point->y, point->z + delta) - f;
f = sqrtf(v->x * v->x + v->y * v->y + v->z * v->z);
if (f != 0.0f) {
v->x /= f;
v->y /= f;
v->z /= f;
}
r_no[0] = p->function(point[0] + delta, point[1], point[2]) - f;
r_no[1] = p->function(point[0], point[1] + delta, point[2]) - f;
r_no[2] = p->function(point[0], point[1], point[2] + delta) - f;
f = normalize_v3(r_no);
if (FALSE) {
MB_POINT temp;
if (0) {
float tvec[3];
delta *= 2.0f;
f = p->function(point->x, point->y, point->z);
f = p->function(point[0], point[1], point[2]);
temp.x = p->function(point->x + delta, point->y, point->z) - f;
temp.y = p->function(point->x, point->y + delta, point->z) - f;
temp.z = p->function(point->x, point->y, point->z + delta) - f;
f = sqrtf(temp.x * temp.x + temp.y * temp.y + temp.z * temp.z);
tvec[0] = p->function(point[0] + delta, point[1], point[2]) - f;
tvec[1] = p->function(point[0], point[1] + delta, point[2]) - f;
tvec[2] = p->function(point[0], point[1], point[2] + delta) - f;
if (f != 0.0f) {
temp.x /= f;
temp.y /= f;
temp.z /= f;
v->x += temp.x;
v->y += temp.y;
v->z += temp.z;
f = sqrtf(v->x * v->x + v->y * v->y + v->z * v->z);
if (f != 0.0f) {
v->x /= f;
v->y /= f;
v->z /= f;
}
if (normalize_v3(tvec) != 0.0f) {
add_v3_v3(r_no, tvec);
normalize_v3(r_no);
}
}
}
static int vertid(CORNER *c1, CORNER *c2, PROCESS *p, MetaBall *mb)
static int vertid(const CORNER *c1, const CORNER *c2, PROCESS *p, MetaBall *mb)
{
VERTEX v;
MB_POINT a, b;
int vid = getedge(p->edges, c1->i, c1->j, c1->k, c2->i, c2->j, c2->k);
if (vid != -1) return vid; /* previously computed */
a.x = c1->x;
a.y = c1->y;
a.z = c1->z;
b.x = c2->x;
b.y = c2->y;
b.z = c2->z;
if (vid != -1) {
return vid; /* previously computed */
}
converge(&a, &b, c1->value, c2->value, p->function, &v.position, mb, 1); /* position */
vnormal(&v.position, p, &v.normal);
converge(c1->co, c2->co, c1->value, c2->value, p->function, v.co, mb, 1); /* position */
vnormal(v.co, p, v.no);
addtovertices(&p->vertices, v); /* save vertex */
vid = p->vertices.count - 1;
@ -1403,101 +1364,95 @@ static int vertid(CORNER *c1, CORNER *c2, PROCESS *p, MetaBall *mb)
/* converge: from two points of differing sign, converge to zero crossing */
/* watch it: p1 and p2 are used to calculate */
static void converge(MB_POINT *p1, MB_POINT *p2, float v1, float v2,
float (*function)(float, float, float), MB_POINT *p, MetaBall *mb, int f)
static void converge(const float p1[3], const float p2[3], float v1, float v2,
float (*function)(float, float, float), float p[3], MetaBall *mb, int f)
{
int i = 0;
MB_POINT pos, neg;
float pos[3], neg[3];
float positive = 0.0f, negative = 0.0f;
float dx = 0.0f, dy = 0.0f, dz = 0.0f;
float dvec[3];
if (v1 < 0) {
pos = *p2;
neg = *p1;
copy_v3_v3(pos, p2);
copy_v3_v3(neg, p1);
positive = v2;
negative = v1;
}
else {
pos = *p1;
neg = *p2;
copy_v3_v3(pos, p1);
copy_v3_v3(neg, p2);
positive = v1;
negative = v2;
}
dx = pos.x - neg.x;
dy = pos.y - neg.y;
dz = pos.z - neg.z;
sub_v3_v3v3(dvec, pos, neg);
/* Approximation by linear interpolation is faster then binary subdivision,
* but it results sometimes (mb->thresh < 0.2) into the strange results */
if ((mb->thresh > 0.2f) && (f == 1)) {
if ((dy == 0.0f) && (dz == 0.0f)) {
p->x = neg.x - negative * dx / (positive - negative);
p->y = neg.y;
p->z = neg.z;
if ((dvec[1] == 0.0f) && (dvec[2] == 0.0f)) {
p[0] = neg[0] - negative * dvec[0] / (positive - negative);
p[1] = neg[1];
p[2] = neg[2];
return;
}
if ((dx == 0.0f) && (dz == 0.0f)) {
p->x = neg.x;
p->y = neg.y - negative * dy / (positive - negative);
p->z = neg.z;
if ((dvec[0] == 0.0f) && (dvec[2] == 0.0f)) {
p[0] = neg[0];
p[1] = neg[1] - negative * dvec[1] / (positive - negative);
p[2] = neg[2];
return;
}
if ((dx == 0.0f) && (dy == 0.0f)) {
p->x = neg.x;
p->y = neg.y;
p->z = neg.z - negative * dz / (positive - negative);
if ((dvec[0] == 0.0f) && (dvec[1] == 0.0f)) {
p[0] = neg[0];
p[1] = neg[1];
p[2] = neg[2] - negative * dvec[2] / (positive - negative);
return;
}
}
if ((dy == 0.0f) && (dz == 0.0f)) {
p->y = neg.y;
p->z = neg.z;
if ((dvec[1] == 0.0f) && (dvec[2] == 0.0f)) {
p[1] = neg[1];
p[2] = neg[2];
while (1) {
if (i++ == RES) return;
p->x = 0.5f * (pos.x + neg.x);
if ((function(p->x, p->y, p->z)) > 0.0f) pos.x = p->x; else neg.x = p->x;
p[0] = 0.5f * (pos[0] + neg[0]);
if ((function(p[0], p[1], p[2])) > 0.0f) pos[0] = p[0]; else neg[0] = p[0];
}
}
if ((dx == 0.0f) && (dz == 0.0f)) {
p->x = neg.x;
p->z = neg.z;
if ((dvec[0] == 0.0f) && (dvec[2] == 0.0f)) {
p[0] = neg[0];
p[2] = neg[2];
while (1) {
if (i++ == RES) return;
p->y = 0.5f * (pos.y + neg.y);
if ((function(p->x, p->y, p->z)) > 0.0f) pos.y = p->y; else neg.y = p->y;
p[1] = 0.5f * (pos[1] + neg[1]);
if ((function(p[0], p[1], p[2])) > 0.0f) pos[1] = p[1]; else neg[1] = p[1];
}
}
if ((dx == 0.0f) && (dy == 0.0f)) {
p->x = neg.x;
p->y = neg.y;
if ((dvec[0] == 0.0f) && (dvec[1] == 0.0f)) {
p[0] = neg[0];
p[1] = neg[1];
while (1) {
if (i++ == RES) return;
p->z = 0.5f * (pos.z + neg.z);
if ((function(p->x, p->y, p->z)) > 0.0f) pos.z = p->z; else neg.z = p->z;
p[2] = 0.5f * (pos[2] + neg[2]);
if ((function(p[0], p[1], p[2])) > 0.0f) pos[2] = p[2]; else neg[2] = p[2];
}
}
/* This is necessary to find start point */
while (1) {
p->x = 0.5f * (pos.x + neg.x);
p->y = 0.5f * (pos.y + neg.y);
p->z = 0.5f * (pos.z + neg.z);
mid_v3_v3v3(&p[0], pos, neg);
if (i++ == RES) return;
if ((function(p->x, p->y, p->z)) > 0.0f) {
pos.x = p->x;
pos.y = p->y;
pos.z = p->z;
if (i++ == RES) {
return;
}
if ((function(p[0], p[1], p[2])) > 0.0f) {
copy_v3_v3(pos, &p[0]);
}
else {
neg.x = p->x;
neg.y = p->y;
neg.z = p->z;
copy_v3_v3(neg, &p[0]);
}
}
}
@ -1535,114 +1490,111 @@ static void add_cube(PROCESS *mbproc, int i, int j, int k, int count)
static void find_first_points(PROCESS *mbproc, MetaBall *mb, int a)
{
MB_POINT IN, in, OUT, out; /*point;*/
MetaElem *ml;
int i, j, k, c_i, c_j, c_k;
int index[3] = {1, 0, -1};
float f = 0.0f;
float in_v /*, out_v*/;
MB_POINT workp;
float tmp_v, workp_v, max_len, len, dx, dy, dz, nx, ny, nz, MAXN;
ml = mainb[a];
f = 1 - (mb->thresh / ml->s);
f = 1.0 - (mb->thresh / ml->s);
/* Skip, when Stiffness of MetaElement is too small ... MetaElement can't be
* visible alone ... but still can influence others MetaElements :-) */
if (f > 0.0f) {
OUT.x = IN.x = in.x = 0.0;
OUT.y = IN.y = in.y = 0.0;
OUT.z = IN.z = in.z = 0.0;
float IN[3] = {0.0f}, OUT[3] = {0.0f}, in[3] = {0.0f}, out[3];
int i, j, k, c_i, c_j, c_k;
int index[3] = {1, 0, -1};
float in_v /*, out_v*/;
float workp[3];
float dvec[3];
float tmp_v, workp_v, max_len, len, nx, ny, nz, MAXN;
calc_mballco(ml, (float *)&in);
in_v = mbproc->function(in.x, in.y, in.z);
calc_mballco(ml, in);
in_v = mbproc->function(in[0], in[1], in[2]);
for (i = 0; i < 3; i++) {
switch (ml->type) {
case MB_BALL:
OUT.x = out.x = IN.x + index[i] * ml->rad;
OUT[0] = out[0] = IN[0] + index[i] * ml->rad;
break;
case MB_TUBE:
case MB_PLANE:
case MB_ELIPSOID:
case MB_CUBE:
OUT.x = out.x = IN.x + index[i] * (ml->expx + ml->rad);
OUT[0] = out[0] = IN[0] + index[i] * (ml->expx + ml->rad);
break;
}
for (j = 0; j < 3; j++) {
switch (ml->type) {
case MB_BALL:
OUT.y = out.y = IN.y + index[j] * ml->rad;
OUT[1] = out[1] = IN[1] + index[j] * ml->rad;
break;
case MB_TUBE:
case MB_PLANE:
case MB_ELIPSOID:
case MB_CUBE:
OUT.y = out.y = IN.y + index[j] * (ml->expy + ml->rad);
OUT[1] = out[1] = IN[1] + index[j] * (ml->expy + ml->rad);
break;
}
for (k = 0; k < 3; k++) {
out.x = OUT.x;
out.y = OUT.y;
out[0] = OUT[0];
out[1] = OUT[1];
switch (ml->type) {
case MB_BALL:
case MB_TUBE:
case MB_PLANE:
out.z = IN.z + index[k] * ml->rad;
out[2] = IN[2] + index[k] * ml->rad;
break;
case MB_ELIPSOID:
case MB_CUBE:
out.z = IN.z + index[k] * (ml->expz + ml->rad);
out[2] = IN[2] + index[k] * (ml->expz + ml->rad);
break;
}
calc_mballco(ml, (float *)&out);
calc_mballco(ml, out);
/*out_v = mbproc->function(out.x, out.y, out.z);*/ /*UNUSED*/
/*out_v = mbproc->function(out[0], out[1], out[2]);*/ /*UNUSED*/
/* find "first points" on Implicit Surface of MetaElemnt ml */
workp.x = in.x;
workp.y = in.y;
workp.z = in.z;
copy_v3_v3(workp, in);
workp_v = in_v;
max_len = sqrtf((out.x - in.x) * (out.x - in.x) + (out.y - in.y) * (out.y - in.y) + (out.z - in.z) * (out.z - in.z));
max_len = len_v3v3(out, in);
nx = abs((out.x - in.x) / mbproc->size);
ny = abs((out.y - in.y) / mbproc->size);
nz = abs((out.z - in.z) / mbproc->size);
nx = abs((out[0] - in[0]) / mbproc->size);
ny = abs((out[1] - in[1]) / mbproc->size);
nz = abs((out[2] - in[2]) / mbproc->size);
MAXN = MAX3(nx, ny, nz);
if (MAXN != 0.0f) {
dx = (out.x - in.x) / MAXN;
dy = (out.y - in.y) / MAXN;
dz = (out.z - in.z) / MAXN;
dvec[0] = (out[0] - in[0]) / MAXN;
dvec[1] = (out[1] - in[1]) / MAXN;
dvec[2] = (out[2] - in[2]) / MAXN;
len = 0.0;
while (len <= max_len) {
workp.x += dx;
workp.y += dy;
workp.z += dz;
workp[0] += dvec[0];
workp[1] += dvec[1];
workp[2] += dvec[2];
/* compute value of implicite function */
tmp_v = mbproc->function(workp.x, workp.y, workp.z);
tmp_v = mbproc->function(workp[0], workp[1], workp[2]);
/* add cube to the stack, when value of implicite function crosses zero value */
if ((tmp_v < 0.0f && workp_v >= 0.0f) || (tmp_v > 0.0f && workp_v <= 0.0f)) {
/* indexes of CUBE, which includes "first point" */
c_i = (int)floor(workp.x / mbproc->size);
c_j = (int)floor(workp.y / mbproc->size);
c_k = (int)floor(workp.z / mbproc->size);
c_i = (int)floor(workp[0] / mbproc->size);
c_j = (int)floor(workp[1] / mbproc->size);
c_k = (int)floor(workp[2] / mbproc->size);
/* add CUBE (with indexes c_i, c_j, c_k) to the stack,
* this cube includes found point of Implicit Surface */
if (ml->flag & MB_NEGATIVE)
add_cube(mbproc, c_i, c_j, c_k, 2);
else
if ((ml->flag & MB_NEGATIVE) == 0) {
add_cube(mbproc, c_i, c_j, c_k, 1);
}
else {
add_cube(mbproc, c_i, c_j, c_k, 2);
}
}
len = sqrtf((workp.x - in.x) * (workp.x - in.x) + (workp.y - in.y) * (workp.y - in.y) + (workp.z - in.z) * (workp.z - in.z));
len = len_v3v3(workp, in);
workp_v = tmp_v;
}
@ -1928,11 +1880,11 @@ static void fill_metaball_octal_node(octal_node *node, MetaElem *ml, short i)
BLI_addtail(&(node->nodes[i]->elems), ml_p);
node->count++;
if (ml->flag & MB_NEGATIVE) {
node->nodes[i]->neg++;
if ((ml->flag & MB_NEGATIVE) == 0) {
node->nodes[i]->pos++;
}
else {
node->nodes[i]->pos++;
node->nodes[i]->neg++;
}
}
@ -2258,14 +2210,14 @@ static void init_metaball_octal_tree(int depth)
ml_p->ml = mainb[a];
BLI_addtail(&node->elems, ml_p);
if (mainb[a]->flag & MB_NEGATIVE) {
/* number of negative MetaElem in scene */
metaball_tree->neg++;
}
else {
if ((mainb[a]->flag & MB_NEGATIVE) == 0) {
/* number of positive MetaElem in scene */
metaball_tree->pos++;
}
else {
/* number of negative MetaElem in scene */
metaball_tree->neg++;
}
}
/* size of first node */
@ -2283,7 +2235,7 @@ void BKE_mball_polygonize(Scene *scene, Object *ob, ListBase *dispbase)
MetaBall *mb;
DispList *dl;
int a, nr_cubes;
float *ve, *no, totsize, width;
float *co, *no, totsize, width;
mb = ob->data;
@ -2308,11 +2260,11 @@ void BKE_mball_polygonize(Scene *scene, Object *ob, ListBase *dispbase)
}
/* if scene includes more then one MetaElem, then octal tree optimization is used */
if ((totelem > 1) && (totelem <= 64)) init_metaball_octal_tree(1);
if ((totelem > 64) && (totelem <= 128)) init_metaball_octal_tree(2);
if ((totelem > 128) && (totelem <= 512)) init_metaball_octal_tree(3);
if ((totelem > 512) && (totelem <= 1024)) init_metaball_octal_tree(4);
if (totelem > 1024) init_metaball_octal_tree(5);
if ((totelem > 1) && (totelem <= 64)) init_metaball_octal_tree(1);
if ((totelem > 64) && (totelem <= 128)) init_metaball_octal_tree(2);
if ((totelem > 128) && (totelem <= 512)) init_metaball_octal_tree(3);
if ((totelem > 512) && (totelem <= 1024)) init_metaball_octal_tree(4);
if (totelem > 1024) init_metaball_octal_tree(5);
/* don't polygonize metaballs with too high resolution (base mball to small)
* note: Eps was 0.0001f but this was giving problems for blood animation for durian, using 0.00001f */
@ -2362,6 +2314,8 @@ void BKE_mball_polygonize(Scene *scene, Object *ob, ListBase *dispbase)
}
if (curindex) {
VERTEX *ptr = mbproc.vertices.ptr;
dl = MEM_callocN(sizeof(DispList), "mbaldisp");
BLI_addtail(dispbase, dl);
dl->type = DL_INDEX4;
@ -2372,17 +2326,12 @@ void BKE_mball_polygonize(Scene *scene, Object *ob, ListBase *dispbase)
indices = NULL;
a = mbproc.vertices.count;
dl->verts = ve = MEM_mallocN(sizeof(float) * 3 * a, "mballverts");
dl->verts = co = MEM_mallocN(sizeof(float) * 3 * a, "mballverts");
dl->nors = no = MEM_mallocN(sizeof(float) * 3 * a, "mballnors");
for (a = 0; a < mbproc.vertices.count; a++, no += 3, ve += 3) {
ve[0] = mbproc.vertices.ptr[a].position.x;
ve[1] = mbproc.vertices.ptr[a].position.y;
ve[2] = mbproc.vertices.ptr[a].position.z;
no[0] = mbproc.vertices.ptr[a].normal.x;
no[1] = mbproc.vertices.ptr[a].normal.y;
no[2] = mbproc.vertices.ptr[a].normal.z;
for (a = 0; a < mbproc.vertices.count; ptr++, a++, no += 3, co += 3) {
copy_v3_v3(co, ptr->co);
copy_v3_v3(no, ptr->no);
}
}
@ -2403,29 +2352,30 @@ int BKE_mball_minmax(MetaBall *mb, float min[3], float max[3])
return (mb->elems.first != NULL);
}
int BKE_mball_center_median(MetaBall *mb, float cent[3])
int BKE_mball_center_median(MetaBall *mb, float r_cent[3])
{
MetaElem *ml;
int total = 0;
zero_v3(cent);
zero_v3(r_cent);
for (ml = mb->elems.first; ml; ml = ml->next) {
add_v3_v3(cent, &ml->x);
add_v3_v3(r_cent, &ml->x);
}
if (total)
mul_v3_fl(cent, 1.0f / (float)total);
if (total) {
mul_v3_fl(r_cent, 1.0f / (float)total);
}
return (total != 0);
}
int BKE_mball_center_bounds(MetaBall *mb, float cent[3])
int BKE_mball_center_bounds(MetaBall *mb, float r_cent[3])
{
float min[3], max[3];
if (BKE_mball_minmax(mb, min, max)) {
mid_v3_v3v3(cent, min, max);
mid_v3_v3v3(r_cent, min, max);
return 1;
}

@ -2702,13 +2702,13 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata,
#endif
{
/* sort loop indices to ensure winding is correct */
if (mf->v1 > mf->v2) SWAP(int, mf->v1, mf->v2);
if (mf->v2 > mf->v3) SWAP(int, mf->v2, mf->v3);
if (mf->v1 > mf->v2) SWAP(int, mf->v1, mf->v2);
if (mf->v1 > mf->v2) SWAP(unsigned int, mf->v1, mf->v2);
if (mf->v2 > mf->v3) SWAP(unsigned int, mf->v2, mf->v3);
if (mf->v1 > mf->v2) SWAP(unsigned int, mf->v1, mf->v2);
if (mf->v1 > mf->v2) SWAP(int, mf->v1, mf->v2);
if (mf->v2 > mf->v3) SWAP(int, mf->v2, mf->v3);
if (mf->v1 > mf->v2) SWAP(int, mf->v1, mf->v2);
if (mf->v1 > mf->v2) SWAP(unsigned int, mf->v1, mf->v2);
if (mf->v2 > mf->v3) SWAP(unsigned int, mf->v2, mf->v3);
if (mf->v1 > mf->v2) SWAP(unsigned int, mf->v1, mf->v2);
}
/* end abusing the edcode */

@ -764,7 +764,7 @@ void BKE_nlastrips_clear_metas(ListBase *strips, short onlySel, short onlyTemp)
}
/* Add the given NLA-Strip to the given Meta-Strip, assuming that the
* strip isn't attached to anyy list of strips
* strip isn't attached to any list of strips
*/
short BKE_nlameta_add_strip(NlaStrip *mstrip, NlaStrip *strip)
{

@ -671,7 +671,7 @@ bNodeTree *ntreeAddTree(const char *name, int type, int nodetype)
* copying for internal use (threads for eg), where you wont want it to modify the
* scene data.
*/
static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_make_extern)
static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_id_user, const short do_make_extern)
{
bNodeTree *newtree;
bNode *node /*, *nnode */ /* UNUSED */, *last;
@ -702,6 +702,11 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_make_e
last = ntree->nodes.last;
for (node = ntree->nodes.first; node; node = node->next) {
/* ntreeUserDecrefID inline */
if (do_id_user) {
id_us_plus(node->id);
}
if (do_make_extern) {
id_lib_extern(node->id);
}
@ -751,22 +756,56 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_make_e
return newtree;
}
bNodeTree *ntreeCopyTree_ex(bNodeTree *ntree, const short do_id_user)
{
return ntreeCopyTree_internal(ntree, do_id_user, TRUE);
}
bNodeTree *ntreeCopyTree(bNodeTree *ntree)
{
return ntreeCopyTree_internal(ntree, TRUE);
return ntreeCopyTree_ex(ntree, TRUE);
}
/* use when duplicating scenes */
void ntreeSwitchID(bNodeTree *ntree, ID *id_from, ID *id_to)
void ntreeSwitchID_ex(bNodeTree *ntree, ID *id_from, ID *id_to, const short do_id_user)
{
bNode *node;
if (id_from == id_to) {
/* should never happen but may as well skip if it does */
return;
}
/* for scene duplication only */
for (node = ntree->nodes.first; node; node = node->next) {
if (node->id == id_from) {
if (do_id_user) {
id_us_min(id_from);
id_us_plus(id_to);
}
node->id = id_to;
}
}
}
void ntreeSwitchID(bNodeTree *ntree, ID *id_from, ID *id_to)
{
ntreeSwitchID_ex(ntree, id_from, id_to, TRUE);
}
void ntreeUserIncrefID(bNodeTree *ntree)
{
bNode *node;
for (node = ntree->nodes.first; node; node = node->next) {
id_us_plus(node->id);
}
}
void ntreeUserDecrefID(bNodeTree *ntree)
{
bNode *node;
for (node = ntree->nodes.first; node; node = node->next) {
id_us_min(node->id);
}
}
/* *************** preview *********** */
/* if node->preview, then we assume the rect to exist */
@ -913,6 +952,7 @@ static void node_unlink_attached(bNodeTree *ntree, bNode *parent)
}
}
/** \note caller needs to manage node->id user */
void nodeFreeNode(bNodeTree *ntree, bNode *node)
{
bNodeSocket *sock, *nextsock;
@ -956,7 +996,7 @@ void nodeFreeNode(bNodeTree *ntree, bNode *node)
}
/* do not free ntree itself here, BKE_libblock_free calls this function too */
void ntreeFreeTree(bNodeTree *ntree)
void ntreeFreeTree_ex(bNodeTree *ntree, const short do_id_user)
{
bNode *node, *next;
bNodeSocket *sock;
@ -990,6 +1030,12 @@ void ntreeFreeTree(bNodeTree *ntree)
for (node = ntree->nodes.first; node; node = next) {
next = node->next;
/* ntreeUserIncrefID inline */
if (do_id_user) {
id_us_min(node->id);
}
nodeFreeNode(ntree, node);
}
@ -1000,6 +1046,11 @@ void ntreeFreeTree(bNodeTree *ntree)
node_socket_free_default_value(sock->type, sock->default_value);
BLI_freelistN(&ntree->outputs);
}
/* same as ntreeFreeTree_ex but always manage users */
void ntreeFreeTree(bNodeTree *ntree)
{
ntreeFreeTree_ex(ntree, TRUE);
}
void ntreeFreeCache(bNodeTree *ntree)
{
@ -1188,7 +1239,7 @@ bNodeTree *ntreeLocalize(bNodeTree *ntree)
}
/* node copy func */
ltree = ntreeCopyTree_internal(ntree, FALSE);
ltree = ntreeCopyTree_internal(ntree, FALSE, FALSE);
if (adt) {
AnimData *ladt = BKE_animdata_from_id(&ltree->id);
@ -1248,7 +1299,7 @@ void ntreeLocalMerge(bNodeTree *localtree, bNodeTree *ntree)
if (ntreetype->local_merge)
ntreetype->local_merge(localtree, ntree);
ntreeFreeTree(localtree);
ntreeFreeTree_ex(localtree, FALSE);
MEM_freeN(localtree);
}
@ -1425,13 +1476,37 @@ void nodeSocketSetType(bNodeSocket *sock, int type)
/* ************** Node Clipboard *********** */
#define USE_NODE_CB_VALIDATE
#ifdef USE_NODE_CB_VALIDATE
/**
* This data structure is to validate the node on creation,
* otherwise we may reference missing data.
*
* Currently its only used for ID's, but nodes may one day
* reference other pointers which need validation.
*/
typedef struct bNodeClipboardExtraInfo {
struct bNodeClipboardExtraInfo *next, *prev;
ID *id;
char id_name[MAX_ID_NAME];
char library_name[FILE_MAX];
} bNodeClipboardExtraInfo;
#endif /* USE_NODE_CB_VALIDATE */
typedef struct bNodeClipboard {
ListBase nodes;
#ifdef USE_NODE_CB_VALIDATE
ListBase nodes_extra_info;
#endif
ListBase links;
int type;
} bNodeClipboard;
bNodeClipboard node_clipboard;
bNodeClipboard node_clipboard = {{0}};
void BKE_node_clipboard_init(struct bNodeTree *ntree)
{
@ -1454,11 +1529,83 @@ void BKE_node_clipboard_clear(void)
nodeFreeNode(NULL, node);
}
node_clipboard.nodes.first = node_clipboard.nodes.last = NULL;
#ifdef USE_NODE_CB_VALIDATE
BLI_freelistN(&node_clipboard.nodes_extra_info);
#endif
}
/* return FALSE when one or more ID's are lost */
int BKE_node_clipboard_validate(void)
{
int ok = TRUE;
#ifdef USE_NODE_CB_VALIDATE
bNodeClipboardExtraInfo *node_info;
bNode *node;
/* lists must be aligned */
BLI_assert(BLI_countlist(&node_clipboard.nodes) ==
BLI_countlist(&node_clipboard.nodes_extra_info));
for (node = node_clipboard.nodes.first, node_info = node_clipboard.nodes_extra_info.first;
node;
node = node->next, node_info = node_info->next)
{
/* validate the node against the stored node info */
/* re-assign each loop since we may clear,
* open a new file where the ID is valid, and paste again */
node->id = node_info->id;
/* currently only validate the ID */
if (node->id) {
ListBase *lb = which_libbase(G.main, GS(node_info->id_name));
BLI_assert(lb != NULL);
if (BLI_findindex(lb, node_info->id) == -1) {
/* may assign NULL */
node->id = BLI_findstring(lb, node_info->id_name + 2, offsetof(ID, name) + 2);
if (node->id == NULL) {
ok = FALSE;
}
}
}
}
#endif /* USE_NODE_CB_VALIDATE */
return ok;
}
void BKE_node_clipboard_add_node(bNode *node)
{
#ifdef USE_NODE_CB_VALIDATE
/* add extra info */
bNodeClipboardExtraInfo *node_info = MEM_mallocN(sizeof(bNodeClipboardExtraInfo), STRINGIFY(bNodeClipboardExtraInfo));
node_info->id = node->id;
if (node->id) {
BLI_strncpy(node_info->id_name, node->id->name, sizeof(node_info->id_name));
if (node->id->lib) {
BLI_strncpy(node_info->library_name, node->id->lib->filepath, sizeof(node_info->library_name));
}
else {
node_info->library_name[0] = '\0';
}
}
else {
node_info->id_name[0] = '\0';
node_info->library_name[0] = '\0';
}
BLI_addtail(&node_clipboard.nodes_extra_info, node_info);
/* end extra info */
#endif /* USE_NODE_CB_VALIDATE */
/* add node */
BLI_addtail(&node_clipboard.nodes, node);
}
void BKE_node_clipboard_add_link(bNodeLink *link)
@ -1992,6 +2139,7 @@ static void registerCompositNodes(bNodeTreeType *ttype)
register_node_type_cmp_vecblur(ttype);
register_node_type_cmp_dilateerode(ttype);
register_node_type_cmp_inpaint(ttype);
register_node_type_cmp_despeckle(ttype);
register_node_type_cmp_defocus(ttype);
register_node_type_cmp_valtorgb(ttype);

@ -1524,7 +1524,7 @@ void BKE_object_mat3_to_rot(Object *ob, float mat[][3], short use_compat)
/* end drot correction */
if (use_compat) mat3_to_compatible_eulO(ob->rot, ob->rot, ob->rotmode, tmat);
else mat3_to_eulO(ob->rot, ob->rotmode, tmat);
else mat3_to_eulO(ob->rot, ob->rotmode, tmat);
}
}
}

@ -158,7 +158,17 @@ void freePackedFile(PackedFile *pf)
else
printf("freePackedFile: Trying to free a NULL pointer\n");
}
PackedFile *dupPackedFile(const PackedFile *pf_src)
{
PackedFile *pf_dst;
pf_dst = MEM_dupallocN(pf_src);
pf_dst->data = MEM_dupallocN(pf_src->data);
return pf_dst;
}
PackedFile *newPackedFileMemory(void *mem, int memlen)
{
PackedFile *pf = MEM_callocN(sizeof(*pf), "PackedFile");

@ -155,7 +155,8 @@ Scene *BKE_scene_copy(Scene *sce, int type)
BKE_keyingsets_copy(&(scen->keyingsets), &(sce->keyingsets));
if (sce->nodetree) {
scen->nodetree = ntreeCopyTree(sce->nodetree); /* copies actions */
/* ID's are managed on both copy and switch */
scen->nodetree = ntreeCopyTree(sce->nodetree);
ntreeSwitchID(scen->nodetree, &sce->id, &scen->id);
}
@ -557,14 +558,7 @@ Scene *BKE_scene_add(const char *name)
Base *BKE_scene_base_find(Scene *scene, Object *ob)
{
Base *base;
base = scene->base.first;
while (base) {
if (base->object == ob) return base;
base = base->next;
}
return NULL;
return BLI_findptr(&scene->base, ob, offsetof(Base, object));
}
void BKE_scene_set_background(Main *bmain, Scene *scene)
@ -589,10 +583,10 @@ void BKE_scene_set_background(Main *bmain, Scene *scene)
/* group flags again */
for (group = bmain->group.first; group; group = group->id.next) {
go = group->gobject.first;
while (go) {
if (go->ob) go->ob->flag |= OB_FROMGROUP;
go = go->next;
for (go = group->gobject.first; go; go = go->next) {
if (go->ob) {
go->ob->flag |= OB_FROMGROUP;
}
}
}

@ -37,8 +37,11 @@
#include "BKE_sequencer.h"
#include "IMB_moviecache.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
#include "BLI_listbase.h"
typedef struct SeqCacheKey {
struct Sequence *seq;
SeqRenderData context;
@ -46,7 +49,25 @@ typedef struct SeqCacheKey {
seq_stripelem_ibuf_t type;
} SeqCacheKey;
typedef struct SeqPreprocessCacheElem {
struct SeqPreprocessCacheElem *next, *prev;
struct Sequence *seq;
SeqRenderData context;
seq_stripelem_ibuf_t type;
ImBuf *ibuf;
} SeqPreprocessCacheElem;
typedef struct SeqPreprocessCache {
int cfra;
ListBase elems;
} SeqPreprocessCache;
static struct MovieCache *moviecache = NULL;
static struct SeqPreprocessCache *preprocess_cache = NULL;
static void preprocessed_cache_destruct(void);
static int seq_cmp_render_data(const SeqRenderData *a, const SeqRenderData *b)
{
@ -160,6 +181,8 @@ void BKE_sequencer_cache_destruct(void)
{
if (moviecache)
IMB_moviecache_free(moviecache);
preprocessed_cache_destruct();
}
void BKE_sequencer_cache_cleanup(void)
@ -168,6 +191,8 @@ void BKE_sequencer_cache_cleanup(void)
IMB_moviecache_free(moviecache);
moviecache = IMB_moviecache_create("seqcache", sizeof(SeqCacheKey), seqcache_hashhash, seqcache_hashcmp);
}
BKE_sequencer_preprocessed_cache_cleanup();
}
static int seqcache_key_check_seq(void *userkey, void *userdata)
@ -219,3 +244,100 @@ void BKE_sequencer_cache_put(SeqRenderData context, Sequence *seq, float cfra, s
IMB_moviecache_put(moviecache, &key, i);
}
void BKE_sequencer_preprocessed_cache_cleanup(void)
{
SeqPreprocessCacheElem *elem;
if (!preprocess_cache)
return;
for (elem = preprocess_cache->elems.first; elem; elem = elem->next) {
IMB_freeImBuf(elem->ibuf);
}
BLI_freelistN(&preprocess_cache->elems);
preprocess_cache->elems.first = preprocess_cache->elems.last = NULL;
}
static void preprocessed_cache_destruct(void)
{
if (!preprocess_cache)
return;
BKE_sequencer_preprocessed_cache_cleanup();
MEM_freeN(preprocess_cache);
preprocess_cache = NULL;
}
ImBuf *BKE_sequencer_preprocessed_cache_get(SeqRenderData context, Sequence *seq, float cfra, seq_stripelem_ibuf_t type)
{
SeqPreprocessCacheElem *elem;
if (!preprocess_cache)
return NULL;
if (preprocess_cache->cfra != cfra)
return NULL;
for (elem = preprocess_cache->elems.first; elem; elem = elem->next) {
if (elem->seq != seq)
continue;
if (elem->type != type)
continue;
if (seq_cmp_render_data(&elem->context, &context) != 0)
continue;
IMB_refImBuf(elem->ibuf);
return elem->ibuf;
}
return NULL;
}
void BKE_sequencer_preprocessed_cache_put(SeqRenderData context, Sequence *seq, float cfra, seq_stripelem_ibuf_t type, ImBuf *ibuf)
{
SeqPreprocessCacheElem *elem;
if (!preprocess_cache) {
preprocess_cache = MEM_callocN(sizeof(SeqPreprocessCache), "sequencer preprocessed cache");
}
else {
if (preprocess_cache->cfra != cfra)
BKE_sequencer_preprocessed_cache_cleanup();
}
elem = MEM_callocN(sizeof(SeqPreprocessCacheElem), "sequencer preprocessed cache element");
elem->seq = seq;
elem->type = type;
elem->context = context;
elem->ibuf = ibuf;
preprocess_cache->cfra = cfra;
IMB_refImBuf(ibuf);
BLI_addtail(&preprocess_cache->elems, elem);
}
void BKE_sequencer_preprocessed_cache_cleanup_sequence(Sequence *seq)
{
SeqPreprocessCacheElem *elem, *elem_next;
if (!preprocess_cache)
return;
for (elem = preprocess_cache->elems.first; elem; elem = elem_next) {
elem_next = elem->next;
if (elem->seq == seq) {
IMB_freeImBuf(elem->ibuf);
BLI_freelinkN(&preprocess_cache->elems, elem);
}
}
}

@ -56,7 +56,7 @@
#include "RNA_access.h"
static void slize_get_byte_buffers(const SeqRenderData *context, const ImBuf *ibuf1, const ImBuf *ibuf2,
static void slice_get_byte_buffers(const SeqRenderData *context, const ImBuf *ibuf1, const ImBuf *ibuf2,
const ImBuf *ibuf3, const ImBuf *out, int start_line, unsigned char **rect1,
unsigned char **rect2, unsigned char **rect3, unsigned char **rect_out)
{
@ -72,7 +72,7 @@ static void slize_get_byte_buffers(const SeqRenderData *context, const ImBuf *ib
*rect3 = (unsigned char*) ibuf3->rect + offset;
}
static void slize_get_float_buffers(const SeqRenderData *context, const ImBuf *ibuf1, const ImBuf *ibuf2,
static void slice_get_float_buffers(const SeqRenderData *context, const ImBuf *ibuf1, const ImBuf *ibuf2,
const ImBuf *ibuf3, const ImBuf *out, int start_line,
float **rect1, float **rect2, float **rect3, float **rect_out)
{
@ -286,14 +286,14 @@ static void do_alphaover_effect(SeqRenderData context, Sequence *UNUSED(seq), fl
if (out->rect_float) {
float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
slize_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
slice_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
do_alphaover_effect_float(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out);
}
else {
unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
slize_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
do_alphaover_effect_byte(facf0, facf1, context.rectx, total_lines, (char *) rect1, (char *) rect2, (char *) rect_out);
}
@ -448,14 +448,14 @@ static void do_alphaunder_effect(SeqRenderData context, Sequence *UNUSED(seq), f
if (out->rect_float) {
float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
slize_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
slice_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
do_alphaunder_effect_float(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out);
}
else {
unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
slize_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
do_alphaunder_effect_byte(facf0, facf1, context.rectx, total_lines, (char *) rect1, (char *) rect2, (char *) rect_out);
}
@ -558,14 +558,14 @@ static void do_cross_effect(SeqRenderData context, Sequence *UNUSED(seq), float
if (out->rect_float) {
float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
slize_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
slice_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
do_cross_effect_float(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out);
}
else {
unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
slize_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
do_cross_effect_byte(facf0, facf1, context.rectx, total_lines, (char *) rect1, (char *) rect2, (char *) rect_out);
}
@ -807,14 +807,14 @@ static void do_gammacross_effect(SeqRenderData context, Sequence *UNUSED(seq), f
if (out->rect_float) {
float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
slize_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
slice_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
do_gammacross_effect_float(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out);
}
else {
unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
slize_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
do_gammacross_effect_byte(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out);
}
@ -913,14 +913,14 @@ static void do_add_effect(SeqRenderData context, Sequence *UNUSED(seq), float UN
if (out->rect_float) {
float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
slize_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
slice_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
do_add_effect_float(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out);
}
else {
unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
slize_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
do_add_effect_byte(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out);
}
@ -1017,14 +1017,14 @@ static void do_sub_effect(SeqRenderData context, Sequence *UNUSED(seq), float UN
if (out->rect_float) {
float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
slize_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
slice_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
do_sub_effect_float(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out);
}
else {
unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
slize_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
do_sub_effect_byte(facf0, facf1, context.rectx, total_lines, (char *) rect1, (char *) rect2, (char *) rect_out);
}
@ -1214,14 +1214,14 @@ static void do_mul_effect(SeqRenderData context, Sequence *UNUSED(seq), float UN
if (out->rect_float) {
float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
slize_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
slice_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
do_mul_effect_float(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out);
}
else {
unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
slize_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
do_mul_effect_byte(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out);
}
@ -2748,7 +2748,7 @@ static void do_overdrop_effect(SeqRenderData context, Sequence *UNUSED(seq), flo
if (out->rect_float) {
float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
slize_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
slice_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
do_drop_effect_float(facf0, facf1, x, y, rect1, rect2, rect_out);
do_alphaover_effect_float(facf0, facf1, x, y, rect1, rect2, rect_out);
@ -2756,7 +2756,7 @@ static void do_overdrop_effect(SeqRenderData context, Sequence *UNUSED(seq), flo
else {
unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
slize_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
do_drop_effect_byte(facf0, facf1, x, y, (char *) rect1, (char *) rect2, (char *) rect_out);
do_alphaover_effect_byte(facf0, facf1, x, y, (char *) rect1, (char *) rect2, (char *) rect_out);

@ -0,0 +1,651 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2012 Blender Foundation.
* All rights reserved.
*
* Contributor(s): Blender Foundation,
* Sergey Sharybin
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/blenkernel/intern/seqmodifier.c
* \ingroup bke
*/
#include <stddef.h>
#include <string.h>
#include "MEM_guardedalloc.h"
#include "BLI_listbase.h"
#include "BLI_path_util.h"
#include "BLI_string.h"
#include "BLI_utildefines.h"
#include "BLI_math.h"
#include "DNA_sequence_types.h"
#include "BKE_colortools.h"
#include "BKE_sequencer.h"
#include "BKE_utildefines.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
static SequenceModifierTypeInfo *modifiersTypes[NUM_SEQUENCE_MODIFIER_TYPES];
static int modifierTypesInit = FALSE;
/*********************** Modifiers *************************/
typedef void (*modifier_apply_threaded_cb) (int width, int height, unsigned char *rect, float *rect_float,
unsigned char *mask_rect, float *mask_rect_float, void *data_v);
typedef struct ModifierInitData {
ImBuf *ibuf;
ImBuf *mask;
void *user_data;
modifier_apply_threaded_cb apply_callback;
} ModifierInitData;
typedef struct ModifierThread {
int width, height;
unsigned char *rect, *mask_rect;
float *rect_float, *mask_rect_float;
void *user_data;
modifier_apply_threaded_cb apply_callback;
} ModifierThread;
static ImBuf *modifier_mask_get(SequenceModifierData *smd, SeqRenderData context, int cfra, int make_float)
{
return BKE_sequencer_render_mask_input(context, smd->mask_input_type, smd->mask_sequence, smd->mask_id, cfra, make_float);
}
static void modifier_init_handle(void *handle_v, int start_line, int tot_line, void *init_data_v)
{
ModifierThread *handle = (ModifierThread *) handle_v;
ModifierInitData *init_data = (ModifierInitData *) init_data_v;
ImBuf *ibuf = init_data->ibuf;
ImBuf *mask = init_data->mask;
int offset = 4 * start_line * ibuf->x;
memset(handle, 0, sizeof(ModifierThread));
handle->width = ibuf->x;
handle->height = tot_line;
handle->apply_callback = init_data->apply_callback;
handle->user_data = init_data->user_data;
if (ibuf->rect)
handle->rect = (unsigned char *) ibuf->rect + offset;
if (ibuf->rect_float)
handle->rect_float = ibuf->rect_float + offset;
if (mask) {
if (mask->rect)
handle->mask_rect = (unsigned char *) mask->rect + offset;
if (mask->rect_float)
handle->mask_rect_float = mask->rect_float + offset;
}
else {
handle->mask_rect = NULL;
handle->mask_rect_float = NULL;
}
}
static void *modifier_do_thread(void *thread_data_v)
{
ModifierThread *td = (ModifierThread *) thread_data_v;
td->apply_callback(td->width, td->height, td->rect, td->rect_float, td->mask_rect, td->mask_rect_float, td->user_data);
return NULL;
}
static void modifier_apply_threaded(ImBuf *ibuf, ImBuf *mask, modifier_apply_threaded_cb apply_callback, void *user_data)
{
ModifierInitData init_data;
init_data.ibuf = ibuf;
init_data.mask = mask;
init_data.user_data = user_data;
init_data.apply_callback = apply_callback;
IMB_processor_apply_threaded(ibuf->y, sizeof(ModifierThread), &init_data,
modifier_init_handle, modifier_do_thread);
}
/* **** Color Balance Modifier **** */
void colorBalance_init_data(SequenceModifierData *smd)
{
ColorBalanceModifierData *cbmd = (ColorBalanceModifierData *) smd;
int c;
cbmd->color_multiply = 1.0f;
for (c = 0; c < 3; c++) {
cbmd->color_balance.lift[c] = 1.0f;
cbmd->color_balance.gamma[c] = 1.0f;
cbmd->color_balance.gain[c] = 1.0f;
}
}
ImBuf *colorBalance_apply(SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask)
{
ColorBalanceModifierData *cbmd = (ColorBalanceModifierData *) smd;
ImBuf *ibuf_new = IMB_dupImBuf(ibuf);
BKE_sequencer_color_balance_apply(&cbmd->color_balance, ibuf_new, cbmd->color_multiply, FALSE, mask);
return ibuf_new;
}
static SequenceModifierTypeInfo seqModifier_ColorBalance = {
"Color Balance", /* name */
"ColorBalanceModifierData", /* struct_name */
sizeof(ColorBalanceModifierData), /* struct_size */
colorBalance_init_data, /* init_data */
NULL, /* free_data */
NULL, /* copy_data */
colorBalance_apply /* apply */
};
/* **** Curves Modifier **** */
void curves_init_data(SequenceModifierData *smd)
{
CurvesModifierData *cmd = (CurvesModifierData *) smd;
curvemapping_set_defaults(&cmd->curve_mapping, 4, 0.0f, 0.0f, 1.0f, 1.0f);
}
void curves_free_data(SequenceModifierData *smd)
{
CurvesModifierData *cmd = (CurvesModifierData *) smd;
curvemapping_free_data(&cmd->curve_mapping);
}
void curves_copy_data(SequenceModifierData *target, SequenceModifierData *smd)
{
CurvesModifierData *cmd = (CurvesModifierData *) smd;
CurvesModifierData *cmd_target = (CurvesModifierData *) target;
curvemapping_copy_data(&cmd_target->curve_mapping, &cmd->curve_mapping);
}
void curves_apply_threaded(int width, int height, unsigned char *rect, float *rect_float,
unsigned char *mask_rect, float *mask_rect_float, void *data_v)
{
CurveMapping *curve_mapping = (CurveMapping *) data_v;
int x, y;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
int pixel_index = (y * width + x) * 4;
if (rect_float) {
float *pixel = rect_float + pixel_index;
float result[3];
curvemapping_evaluate_premulRGBF(curve_mapping, result, pixel);
if (mask_rect_float) {
float *m = mask_rect_float + pixel_index;
pixel[0] = pixel[0] * (1.0f - m[0]) + result[0] * m[0];
pixel[1] = pixel[1] * (1.0f - m[1]) + result[1] * m[1];
pixel[2] = pixel[2] * (1.0f - m[2]) + result[2] * m[2];
}
else {
pixel[0] = result[0];
pixel[1] = result[1];
pixel[2] = result[2];
}
}
if (rect) {
unsigned char *pixel = rect + pixel_index;
unsigned char result[3];
curvemapping_evaluate_premulRGB(curve_mapping, result, pixel);
if (mask_rect) {
float t[3];
rgb_uchar_to_float(t, mask_rect + pixel_index);
pixel[0] = pixel[0] * (1.0f - t[0]) + result[0] * t[0];
pixel[1] = pixel[1] * (1.0f - t[1]) + result[1] * t[1];
pixel[2] = pixel[2] * (1.0f - t[2]) + result[2] * t[2];
}
else {
pixel[0] = result[0];
pixel[1] = result[1];
pixel[2] = result[2];
}
}
}
}
}
ImBuf *curves_apply(struct SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask)
{
CurvesModifierData *cmd = (CurvesModifierData *) smd;
ImBuf *ibuf_new = IMB_dupImBuf(ibuf);
float black[3] = {0.0f, 0.0f, 0.0f};
float white[3] = {1.0f, 1.0f, 1.0f};
curvemapping_initialize(&cmd->curve_mapping);
curvemapping_premultiply(&cmd->curve_mapping, 0);
curvemapping_set_black_white(&cmd->curve_mapping, black, white);
modifier_apply_threaded(ibuf_new, mask, curves_apply_threaded, &cmd->curve_mapping);
curvemapping_premultiply(&cmd->curve_mapping, 1);
return ibuf_new;
}
static SequenceModifierTypeInfo seqModifier_Curves = {
"Curves", /* name */
"CurvesModifierData", /* struct_name */
sizeof(CurvesModifierData), /* struct_size */
curves_init_data, /* init_data */
curves_free_data, /* free_data */
curves_copy_data, /* copy_data */
curves_apply /* apply */
};
/* **** Hue Correct Modifier **** */
void hue_correct_init_data(SequenceModifierData *smd)
{
HueCorrectModifierData *hcmd = (HueCorrectModifierData *) smd;
int c;
curvemapping_set_defaults(&hcmd->curve_mapping, 1, 0.0f, 0.0f, 1.0f, 1.0f);
hcmd->curve_mapping.preset = CURVE_PRESET_MID9;
for (c = 0; c < 3; c++) {
CurveMap *cuma = &hcmd->curve_mapping.cm[c];
curvemap_reset(cuma, &hcmd->curve_mapping.clipr, hcmd->curve_mapping.preset, CURVEMAP_SLOPE_POSITIVE);
}
/* default to showing Saturation */
hcmd->curve_mapping.cur = 1;
}
void hue_correct_free_data(SequenceModifierData *smd)
{
HueCorrectModifierData *hcmd = (HueCorrectModifierData *) smd;
curvemapping_free_data(&hcmd->curve_mapping);
}
void hue_correct_copy_data(SequenceModifierData *target, SequenceModifierData *smd)
{
HueCorrectModifierData *hcmd = (HueCorrectModifierData *) smd;
HueCorrectModifierData *hcmd_target = (HueCorrectModifierData *) target;
curvemapping_copy_data(&hcmd_target->curve_mapping, &hcmd->curve_mapping);
}
void hue_correct_apply_threaded(int width, int height, unsigned char *rect, float *rect_float,
unsigned char *mask_rect, float *mask_rect_float, void *data_v)
{
CurveMapping *curve_mapping = (CurveMapping *) data_v;
int x, y;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
int pixel_index = (y * width + x) * 4;
float pixel[3], result[3], mask[3] = {1.0f, 1.0f, 1.0f};
float hsv[3], f;
if (rect_float)
copy_v3_v3(pixel, rect_float + pixel_index);
else
rgb_uchar_to_float(pixel, rect + pixel_index);
rgb_to_hsv(pixel[0], pixel[1], pixel[2], hsv, hsv + 1, hsv + 2);
/* adjust hue, scaling returned default 0.5 up to 1 */
f = curvemapping_evaluateF(curve_mapping, 0, hsv[0]);
hsv[0] += f - 0.5f;
/* adjust saturation, scaling returned default 0.5 up to 1 */
f = curvemapping_evaluateF(curve_mapping, 1, hsv[0]);
hsv[1] *= (f * 2.0f);
/* adjust value, scaling returned default 0.5 up to 1 */
f = curvemapping_evaluateF(curve_mapping, 2, hsv[0]);
hsv[2] *= (f * 2.f);
hsv[0] = hsv[0] - floorf(hsv[0]); /* mod 1.0 */
CLAMP(hsv[1], 0.0f, 1.0f);
/* convert back to rgb */
hsv_to_rgb(hsv[0], hsv[1], hsv[2], result, result + 1, result + 2);
if (mask_rect_float)
copy_v3_v3(mask, mask_rect_float + pixel_index);
else if (mask_rect)
rgb_uchar_to_float(mask, mask_rect + pixel_index);
result[0] = pixel[0] * (1.0f - mask[0]) + result[0] * mask[0];
result[1] = pixel[1] * (1.0f - mask[1]) + result[1] * mask[1];
result[2] = pixel[2] * (1.0f - mask[2]) + result[2] * mask[2];
if (rect_float)
copy_v3_v3(rect_float + pixel_index, result);
else
rgb_float_to_uchar(rect + pixel_index, result);
}
}
}
ImBuf *hue_correct_apply(struct SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask)
{
HueCorrectModifierData *hcmd = (HueCorrectModifierData *) smd;
ImBuf *ibuf_new = IMB_dupImBuf(ibuf);
curvemapping_initialize(&hcmd->curve_mapping);
modifier_apply_threaded(ibuf_new, mask, hue_correct_apply_threaded, &hcmd->curve_mapping);
return ibuf_new;
}
static SequenceModifierTypeInfo seqModifier_HueCorrect = {
"Hue Correct", /* name */
"HueCorrectModifierData", /* struct_name */
sizeof(HueCorrectModifierData), /* struct_size */
hue_correct_init_data, /* init_data */
hue_correct_free_data, /* free_data */
hue_correct_copy_data, /* copy_data */
hue_correct_apply /* apply */
};
/* **** Bright/Contrast Modifier **** */
typedef struct BrightContrastThreadData {
float bright;
float contrast;
} BrightContrastThreadData;
void brightcontrast_apply_threaded(int width, int height, unsigned char *rect, float *rect_float,
unsigned char *mask_rect, float *mask_rect_float, void *data_v)
{
BrightContrastThreadData *data = (BrightContrastThreadData *) data_v;
int x, y;
float i;
int c;
float a, b, v;
float brightness = data->bright / 100.0f;
float contrast = data->contrast;
float delta = contrast / 200.0f;
a = 1.0f - delta * 2.0f;
/*
* The algorithm is by Werner D. Streidt
* (http://visca.com/ffactory/archives/5-99/msg00021.html)
* Extracted of OpenCV demhist.c
*/
if (contrast > 0) {
a = 1.0f / a;
b = a * (brightness - delta);
}
else {
delta *= -1;
b = a * (brightness + delta);
}
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
int pixel_index = (y * width + x) * 4;
if (rect) {
unsigned char *pixel = rect + pixel_index;
for (c = 0; c < 3; c++) {
i = pixel[c];
v = a * i + b;
if (mask_rect) {
unsigned char *m = mask_rect + pixel_index;
float t = (float) m[c] / 255.0f;
pixel[c] = pixel[c] * (1.0f - t) + v * t;
}
else
pixel[c] = v;
}
}
else if (rect_float) {
float *pixel = rect_float + pixel_index;
for (c = 0; c < 3; c++) {
i = pixel[c];
v = a * i + b;
if (mask_rect_float) {
float *m = mask_rect_float + pixel_index;
pixel[c] = pixel[c] * (1.0f - m[c]) + v * m[c];
}
else
pixel[c] = v;
}
}
}
}
}
ImBuf *brightcontrast_apply(struct SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask)
{
BrightContrastModifierData *bcmd = (BrightContrastModifierData *) smd;
BrightContrastThreadData data;
ImBuf *ibuf_new = IMB_dupImBuf(ibuf);
data.bright = bcmd->bright;
data.contrast = bcmd->contrast;
modifier_apply_threaded(ibuf_new, mask, brightcontrast_apply_threaded, &data);
return ibuf_new;
}
static SequenceModifierTypeInfo seqModifier_BrightContrast = {
"Bright/Contrast", /* name */
"BrightContrastModifierData", /* struct_name */
sizeof(BrightContrastModifierData), /* struct_size */
NULL, /* init_data */
NULL, /* free_data */
NULL, /* copy_data */
brightcontrast_apply /* apply */
};
/*********************** Modifier functions *************************/
static void sequence_modifier_type_info_init(void)
{
#define INIT_TYPE(typeName) (modifiersTypes[seqModifierType_##typeName] = &seqModifier_##typeName)
INIT_TYPE(ColorBalance);
INIT_TYPE(Curves);
INIT_TYPE(HueCorrect);
INIT_TYPE(BrightContrast);
#undef INIT_TYPE
}
SequenceModifierTypeInfo *BKE_sequence_modifier_type_info_get(int type)
{
if (!modifierTypesInit) {
sequence_modifier_type_info_init();
modifierTypesInit = TRUE;
}
return modifiersTypes[type];
}
SequenceModifierData *BKE_sequence_modifier_new(Sequence *seq, const char *name, int type)
{
SequenceModifierData *smd;
SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(type);
smd = MEM_callocN(smti->struct_size, "sequence modifier");
smd->type = type;
smd->flag |= SEQUENCE_MODIFIER_EXPANDED;
if (!name || !name[0])
BLI_strncpy(smd->name, smti->name, sizeof(smd->name));
else
BLI_strncpy(smd->name, name, sizeof(smd->name));
BLI_addtail(&seq->modifiers, smd);
BKE_sequence_modifier_unique_name(seq, smd);
if (smti->init_data)
smti->init_data(smd);
return smd;
}
int BKE_sequence_modifier_remove(Sequence *seq, SequenceModifierData *smd)
{
if (BLI_findindex(&seq->modifiers, smd) == -1)
return FALSE;
BLI_remlink(&seq->modifiers, smd);
BKE_sequence_modifier_free(smd);
return TRUE;
}
void BKE_sequence_modifier_clear(Sequence *seq)
{
SequenceModifierData *smd, *smd_next;
for (smd = seq->modifiers.first; smd; smd = smd_next) {
smd_next = smd->next;
BKE_sequence_modifier_free(smd);
}
seq->modifiers.first = seq->modifiers.last = NULL;
}
void BKE_sequence_modifier_free(SequenceModifierData *smd)
{
SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type);
if (smti && smti->free_data) {
smti->free_data(smd);
}
MEM_freeN(smd);
}
void BKE_sequence_modifier_unique_name(Sequence *seq, SequenceModifierData *smd)
{
SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type);
BLI_uniquename(&seq->modifiers, smd, smti->name, '.', offsetof(SequenceModifierData, name), sizeof(smd->name));
}
SequenceModifierData *BKE_sequence_modifier_find_by_name(Sequence *seq, char *name)
{
return BLI_findstring(&(seq->modifiers), name, offsetof(SequenceModifierData, name));
}
ImBuf *BKE_sequence_modifier_apply_stack(SeqRenderData context, Sequence *seq, ImBuf *ibuf, int cfra)
{
SequenceModifierData *smd;
ImBuf *processed_ibuf = ibuf;
for (smd = seq->modifiers.first; smd; smd = smd->next) {
SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type);
ImBuf *ibuf_new;
/* could happen if modifier is being removed or not exists in current version of blender */
if (!smti)
continue;
/* modifier is muted, do nothing */
if (smd->flag & SEQUENCE_MODIFIER_MUTE)
continue;
if (smti->apply) {
ImBuf *mask = modifier_mask_get(smd, context, cfra, ibuf->rect_float != NULL);
if (processed_ibuf == ibuf)
processed_ibuf = IMB_dupImBuf(ibuf);
ibuf_new = smti->apply(smd, processed_ibuf, mask);
if (ibuf_new != processed_ibuf) {
IMB_freeImBuf(processed_ibuf);
processed_ibuf = ibuf_new;
}
if (mask)
IMB_freeImBuf(mask);
}
}
return processed_ibuf;
}
void BKE_sequence_modifier_list_copy(Sequence *seqn, Sequence *seq)
{
SequenceModifierData *smd;
for (smd = seq->modifiers.first; smd; smd = smd->next) {
SequenceModifierData *smdn;
SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type);
smdn = MEM_dupallocN(smd);
if (smti && smti->copy_data)
smti->copy_data(smdn, smd);
smdn->next = smdn->prev = NULL;
BLI_addtail(&seqn->modifiers, smdn);
}
}
int BKE_sequence_supports_modifiers(Sequence *seq)
{
return !ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD);
}

@ -83,6 +83,7 @@
static ImBuf *seq_render_strip_stack(SeqRenderData context, ListBase *seqbasep, float cfra, int chanshown);
static ImBuf *seq_render_strip(SeqRenderData context, Sequence *seq, float cfra);
static void seq_free_animdata(Scene *scene, Sequence *seq);
static ImBuf *seq_render_mask(SeqRenderData context, Mask *mask, float nr, short make_float);
/* **** XXX ******** */
#define SELECT 1
@ -203,7 +204,13 @@ void BKE_sequence_free(Scene *scene, Sequence *seq)
seq_free_animdata(scene, seq);
}
BKE_sequencer_cache_cleanup_sequence(seq);
/* free modifiers */
BKE_sequence_modifier_clear(seq);
/* free cached data used by this strip,
* also invalidate cache for all dependent sequences
*/
BKE_sequence_invalidate_cache(scene, seq);
MEM_freeN(seq);
}
@ -1432,7 +1439,7 @@ static void make_cb_table_float(float lift, float gain, float gamma,
}
}
static void color_balance_byte_byte(Sequence *seq, unsigned char *rect, unsigned char *mask_rect, int width, int height, float mul)
static void color_balance_byte_byte(StripColorBalance *cb_, unsigned char *rect, unsigned char *mask_rect, int width, int height, float mul)
{
unsigned char cb_tab[3][256];
int c;
@ -1440,7 +1447,7 @@ static void color_balance_byte_byte(Sequence *seq, unsigned char *rect, unsigned
unsigned char *e = p + width * 4 * height;
unsigned char *m = mask_rect;
StripColorBalance cb = calc_cb(seq->strip->color_balance);
StripColorBalance cb = calc_cb(cb_);
for (c = 0; c < 3; c++) {
make_cb_table_byte(cb.lift[c], cb.gain[c], cb.gamma[c], cb_tab[c], mul);
@ -1466,7 +1473,7 @@ static void color_balance_byte_byte(Sequence *seq, unsigned char *rect, unsigned
}
}
static void color_balance_byte_float(Sequence *seq, unsigned char *rect, float *rect_float, unsigned char *mask_rect, int width, int height, float mul)
static void color_balance_byte_float(StripColorBalance *cb_, unsigned char *rect, float *rect_float, unsigned char *mask_rect, int width, int height, float mul)
{
float cb_tab[4][256];
int c, i;
@ -1478,7 +1485,7 @@ static void color_balance_byte_float(Sequence *seq, unsigned char *rect, float *
o = rect_float;
cb = calc_cb(seq->strip->color_balance);
cb = calc_cb(cb_);
for (c = 0; c < 3; c++) {
make_cb_table_float(cb.lift[c], cb.gain[c], cb.gamma[c], cb_tab[c], mul);
@ -1510,12 +1517,12 @@ static void color_balance_byte_float(Sequence *seq, unsigned char *rect, float *
}
}
static void color_balance_float_float(Sequence *seq, float *rect_float, float *mask_rect_float, int width, int height, float mul)
static void color_balance_float_float(StripColorBalance *cb_, float *rect_float, float *mask_rect_float, int width, int height, float mul)
{
float *p = rect_float;
float *e = rect_float + width * 4 * height;
float *m = mask_rect_float;
StripColorBalance cb = calc_cb(seq->strip->color_balance);
StripColorBalance cb = calc_cb(cb_);
while (p < e) {
int c;
@ -1535,20 +1542,23 @@ static void color_balance_float_float(Sequence *seq, float *rect_float, float *m
}
typedef struct ColorBalanceInitData {
Sequence *seq;
StripColorBalance *cb;
ImBuf *ibuf;
float mul;
ImBuf *mask;
short make_float;
} ColorBalanceInitData;
typedef struct ColorBalanceThread {
Sequence *seq;
StripColorBalance *cb;
float mul;
int width, height;
unsigned char *rect, *mask_rect;
float *rect_float, *mask_rect_float;
short make_float;
} ColorBalanceThread;
static void color_balance_init_handle(void *handle_v, int start_line, int tot_line, void *init_data_v)
@ -1562,10 +1572,11 @@ static void color_balance_init_handle(void *handle_v, int start_line, int tot_li
memset(handle, 0, sizeof(ColorBalanceThread));
handle->seq = init_data->seq;
handle->cb = init_data->cb;
handle->mul = init_data->mul;
handle->width = ibuf->x;
handle->height = tot_line;
handle->make_float = init_data->make_float;
if (ibuf->rect)
handle->rect = (unsigned char *) ibuf->rect + offset;
@ -1589,7 +1600,7 @@ static void color_balance_init_handle(void *handle_v, int start_line, int tot_li
static void *color_balance_do_thread(void *thread_data_v)
{
ColorBalanceThread *thread_data = (ColorBalanceThread *) thread_data_v;
Sequence *seq = thread_data->seq;
StripColorBalance *cb = thread_data->cb;
int width = thread_data->width, height = thread_data->height;
unsigned char *rect = thread_data->rect;
unsigned char *mask_rect = thread_data->mask_rect;
@ -1598,48 +1609,56 @@ static void *color_balance_do_thread(void *thread_data_v)
float mul = thread_data->mul;
if (rect_float) {
color_balance_float_float(seq, rect_float, mask_rect_float, width, height, mul);
color_balance_float_float(cb, rect_float, mask_rect_float, width, height, mul);
}
else if (seq->flag & SEQ_MAKE_FLOAT) {
color_balance_byte_float(seq, rect, rect_float, mask_rect, width, height, mul);
else if (thread_data->make_float) {
color_balance_byte_float(cb, rect, rect_float, mask_rect, width, height, mul);
}
else {
color_balance_byte_byte(seq, rect, mask_rect, width, height, mul);
color_balance_byte_byte(cb, rect, mask_rect, width, height, mul);
}
return NULL;
}
static void color_balance(SeqRenderData context, Sequence *seq, ImBuf *ibuf, float mul, int cfra)
ImBuf *BKE_sequencer_render_mask_input(SeqRenderData context, int mask_input_type, Sequence *mask_sequence, Mask *mask_id, int cfra, int make_float)
{
ColorBalanceInitData init_data;
ImBuf *mask_input = NULL;
if (!ibuf->rect_float && seq->flag & SEQ_MAKE_FLOAT)
imb_addrectfloatImBuf(ibuf);
if (mask_input_type == SEQUENCE_MASK_INPUT_STRIP) {
if (mask_sequence) {
mask_input = seq_render_strip(context, mask_sequence, cfra);
init_data.seq = seq;
init_data.ibuf = ibuf;
init_data.mul = mul;
init_data.mask = NULL;
if (seq->mask_sequence) {
if (seq->mask_sequence != seq && !BKE_sequence_check_depend(seq, seq->mask_sequence)) {
ImBuf *mask = seq_render_strip(context, seq->mask_sequence, cfra);
if (mask) {
if (ibuf->rect_float) {
if (!mask->rect_float)
IMB_float_from_rect(mask);
}
else {
if (!mask->rect)
IMB_rect_from_float(mask);
}
init_data.mask = mask;
if (make_float) {
if (!mask_input->rect_float)
IMB_float_from_rect(mask_input);
}
else {
if (!mask_input->rect)
IMB_rect_from_float(mask_input);
}
}
}
else if (mask_input_type == SEQUENCE_MASK_INPUT_ID) {
mask_input = seq_render_mask(context, mask_id, cfra, make_float);
}
return mask_input;
}
void BKE_sequencer_color_balance_apply(StripColorBalance *cb, ImBuf *ibuf, float mul, short make_float, ImBuf *mask_input)
{
ColorBalanceInitData init_data;
if (!ibuf->rect_float && make_float)
imb_addrectfloatImBuf(ibuf);
init_data.cb = cb;
init_data.ibuf = ibuf;
init_data.mul = mul;
init_data.mask = NULL;
init_data.make_float = make_float;
init_data.mask = mask_input;
IMB_processor_apply_threaded(ibuf->y, sizeof(ColorBalanceThread), &init_data,
color_balance_init_handle, color_balance_do_thread);
@ -1650,9 +1669,26 @@ static void color_balance(SeqRenderData context, Sequence *seq, ImBuf *ibuf, flo
*/
if (ibuf->rect_float && ibuf->rect)
imb_freerectImBuf(ibuf);
}
if (init_data.mask)
IMB_freeImBuf(init_data.mask);
static void sequence_color_balance(SeqRenderData context, Sequence *seq, ImBuf *ibuf, float mul, int cfra)
{
StripColorBalance *cb = seq->strip->color_balance;
ImBuf *mask_input = NULL;
short make_float = seq->flag & SEQ_MAKE_FLOAT;
if (seq->mask_sequence) {
if (seq->mask_sequence != seq && !BKE_sequence_check_depend(seq, seq->mask_sequence)) {
int make_float = ibuf->rect_float != NULL;
mask_input = BKE_sequencer_render_mask_input(context, SEQUENCE_MASK_INPUT_STRIP, seq->mask_sequence, NULL, cfra, make_float);
}
}
BKE_sequencer_color_balance_apply(cb, ibuf, mul, make_float, mask_input);
if (mask_input)
IMB_freeImBuf(mask_input);
}
/*
@ -1696,6 +1732,10 @@ int BKE_sequencer_input_have_to_preprocess(SeqRenderData UNUSED(context), Sequen
if (seq->sat != 1.0f) {
return TRUE;
}
if (seq->modifiers.first) {
return TRUE;
}
return FALSE;
}
@ -1795,7 +1835,7 @@ static ImBuf *input_preprocess(SeqRenderData context, Sequence *seq, float cfra,
}
if (seq->flag & SEQ_USE_COLOR_BALANCE && seq->strip->color_balance) {
color_balance(context, seq, ibuf, mul, cfra);
sequence_color_balance(context, seq, ibuf, mul, cfra);
mul = 1.0;
}
@ -1818,7 +1858,6 @@ static ImBuf *input_preprocess(SeqRenderData context, Sequence *seq, float cfra,
}
}
if (ibuf->x != context.rectx || ibuf->y != context.recty) {
if (context.scene->r.mode & R_OSA) {
IMB_scaleImBuf(ibuf, (short)context.rectx, (short)context.recty);
@ -1827,6 +1866,16 @@ static ImBuf *input_preprocess(SeqRenderData context, Sequence *seq, float cfra,
IMB_scalefastImBuf(ibuf, (short)context.rectx, (short)context.recty);
}
}
if (seq->modifiers.first) {
ImBuf *ibuf_new = BKE_sequence_modifier_apply_stack(context, seq, ibuf, cfra);
if (ibuf_new != ibuf) {
IMB_freeImBuf(ibuf);
ibuf = ibuf_new;
}
}
return ibuf;
}
@ -2098,23 +2147,23 @@ static ImBuf *seq_render_movieclip_strip(SeqRenderData context, Sequence *seq, f
}
static ImBuf *seq_render_mask_strip(SeqRenderData context, Sequence *seq, float nr)
static ImBuf *seq_render_mask(SeqRenderData context, Mask *mask, float nr, short make_float)
{
/* TODO - add option to rasterize to alpha imbuf? */
ImBuf *ibuf = NULL;
float *maskbuf;
int i;
if (!seq->mask) {
if (!mask) {
return NULL;
}
else {
Mask *mask_temp;
MaskRasterHandle *mr_handle;
mask_temp = BKE_mask_copy_nolib(seq->mask);
mask_temp = BKE_mask_copy_nolib(mask);
BKE_mask_evaluate(mask_temp, seq->mask->sfra + nr, TRUE);
BKE_mask_evaluate(mask_temp, mask->sfra + nr, TRUE);
maskbuf = MEM_mallocN(sizeof(float) * context.rectx * context.recty, __func__);
@ -2131,7 +2180,7 @@ static ImBuf *seq_render_mask_strip(SeqRenderData context, Sequence *seq, float
}
if (seq->flag & SEQ_MAKE_FLOAT) {
if (make_float) {
/* pixels */
float *fp_src;
float *fp_dst;
@ -2173,6 +2222,13 @@ static ImBuf *seq_render_mask_strip(SeqRenderData context, Sequence *seq, float
return ibuf;
}
static ImBuf *seq_render_mask_strip(SeqRenderData context, Sequence *seq, float nr)
{
short make_float = seq->flag & SEQ_MAKE_FLOAT;
return seq_render_mask(context, seq->mask, nr, make_float);
}
static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float nr)
{
ImBuf *ibuf = NULL;
@ -2328,10 +2384,162 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float
return ibuf;
}
static ImBuf *do_render_strip_uncached(SeqRenderData context, Sequence *seq, float cfra)
{
ImBuf *ibuf = NULL;
float nr = give_stripelem_index(seq, cfra);
int type = (seq->type & SEQ_TYPE_EFFECT && seq->type != SEQ_TYPE_SPEED) ? SEQ_TYPE_EFFECT : seq->type;
int use_preprocess = BKE_sequencer_input_have_to_preprocess(context, seq, cfra);
char name[FILE_MAX];
switch (type) {
case SEQ_TYPE_META:
{
ImBuf *meta_ibuf = NULL;
if (seq->seqbase.first)
meta_ibuf = seq_render_strip_stack(context, &seq->seqbase, seq->start + nr, 0);
if (meta_ibuf) {
ibuf = meta_ibuf;
if (ibuf && use_preprocess) {
ImBuf *i = IMB_dupImBuf(ibuf);
IMB_freeImBuf(ibuf);
ibuf = i;
}
}
break;
}
case SEQ_TYPE_SPEED:
{
ImBuf *child_ibuf = NULL;
float f_cfra;
SpeedControlVars *s = (SpeedControlVars *)seq->effectdata;
BKE_sequence_effect_speed_rebuild_map(context.scene, seq, 0);
/* weeek! */
f_cfra = seq->start + s->frameMap[(int)nr];
child_ibuf = seq_render_strip(context, seq->seq1, f_cfra);
if (child_ibuf) {
ibuf = child_ibuf;
if (ibuf && use_preprocess) {
ImBuf *i = IMB_dupImBuf(ibuf);
IMB_freeImBuf(ibuf);
ibuf = i;
}
}
break;
}
case SEQ_TYPE_EFFECT:
{
ibuf = seq_render_effect_strip_impl(context, seq, seq->start + nr);
break;
}
case SEQ_TYPE_IMAGE:
{
StripElem *s_elem = BKE_sequencer_give_stripelem(seq, cfra);
if (s_elem) {
BLI_join_dirfile(name, sizeof(name), seq->strip->dir, s_elem->name);
BLI_path_abs(name, G.main->name);
}
if (s_elem && (ibuf = IMB_loadiffname(name, IB_rect))) {
/* we don't need both (speed reasons)! */
if (ibuf->rect_float && ibuf->rect)
imb_freerectImBuf(ibuf);
/* all sequencer color is done in SRGB space, linear gives odd crossfades */
if (ibuf->profile == IB_PROFILE_LINEAR_RGB)
IMB_convert_profile(ibuf, IB_PROFILE_NONE);
copy_to_ibuf_still(context, seq, nr, ibuf);
s_elem->orig_width = ibuf->x;
s_elem->orig_height = ibuf->y;
}
break;
}
case SEQ_TYPE_MOVIE:
{
seq_open_anim_file(seq);
if (seq->anim) {
IMB_anim_set_preseek(seq->anim, seq->anim_preseek);
ibuf = IMB_anim_absolute(seq->anim, nr + seq->anim_startofs,
seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN,
seq_rendersize_to_proxysize(context.preview_render_size));
/* we don't need both (speed reasons)! */
if (ibuf && ibuf->rect_float && ibuf->rect)
imb_freerectImBuf(ibuf);
if (ibuf) {
seq->strip->stripdata->orig_width = ibuf->x;
seq->strip->stripdata->orig_height = ibuf->y;
}
}
copy_to_ibuf_still(context, seq, nr, ibuf);
break;
}
case SEQ_TYPE_SCENE:
{
/* scene can be NULL after deletions */
ibuf = seq_render_scene_strip(context, seq, nr);
/* Scene strips update all animation, so we need to restore original state.*/
BKE_animsys_evaluate_all_animation(context.bmain, context.scene, cfra);
copy_to_ibuf_still(context, seq, nr, ibuf);
break;
}
case SEQ_TYPE_MOVIECLIP:
{
ibuf = seq_render_movieclip_strip(context, seq, nr);
if (ibuf && use_preprocess) {
ImBuf *i = IMB_dupImBuf(ibuf);
IMB_freeImBuf(ibuf);
ibuf = i;
}
copy_to_ibuf_still(context, seq, nr, ibuf);
break;
}
case SEQ_TYPE_MASK:
{
/* ibuf is alwats new */
ibuf = seq_render_mask_strip(context, seq, nr);
copy_to_ibuf_still(context, seq, nr, ibuf);
break;
}
}
return ibuf;
}
static ImBuf *seq_render_strip(SeqRenderData context, Sequence *seq, float cfra)
{
ImBuf *ibuf = NULL;
char name[FILE_MAX];
int use_preprocess = BKE_sequencer_input_have_to_preprocess(context, seq, cfra);
int is_proxy_image = FALSE;
float nr = give_stripelem_index(seq, cfra);
@ -2348,147 +2556,22 @@ static ImBuf *seq_render_strip(SeqRenderData context, Sequence *seq, float cfra)
if (ibuf == NULL)
ibuf = copy_from_ibuf_still(context, seq, nr);
/* MOVIECLIPs have their own proxy management */
if (ibuf == NULL && seq->type != SEQ_TYPE_MOVIECLIP) {
ibuf = seq_proxy_fetch(context, seq, cfra);
is_proxy_image = (ibuf != NULL);
}
if (ibuf == NULL) switch (type) {
case SEQ_TYPE_META:
{
ImBuf *meta_ibuf = NULL;
if (ibuf == NULL) {
ibuf = BKE_sequencer_preprocessed_cache_get(context, seq, cfra, SEQ_STRIPELEM_IBUF);
if (seq->seqbase.first)
meta_ibuf = seq_render_strip_stack(
context, &seq->seqbase,
seq->start + nr, 0);
if (meta_ibuf) {
ibuf = meta_ibuf;
if (ibuf && use_preprocess) {
ImBuf *i = IMB_dupImBuf(ibuf);
IMB_freeImBuf(ibuf);
ibuf = i;
}
}
break;
if (ibuf == NULL) {
/* MOVIECLIPs have their own proxy management */
if (ibuf == NULL && seq->type != SEQ_TYPE_MOVIECLIP) {
ibuf = seq_proxy_fetch(context, seq, cfra);
is_proxy_image = (ibuf != NULL);
}
case SEQ_TYPE_SPEED:
{
ImBuf *child_ibuf = NULL;
float f_cfra;
SpeedControlVars *s = (SpeedControlVars *)seq->effectdata;
if (ibuf == NULL)
ibuf = do_render_strip_uncached(context, seq, cfra);
BKE_sequence_effect_speed_rebuild_map(context.scene, seq, 0);
/* weeek! */
f_cfra = seq->start + s->frameMap[(int)nr];
child_ibuf = seq_render_strip(context, seq->seq1, f_cfra);
if (child_ibuf) {
ibuf = child_ibuf;
if (ibuf && use_preprocess) {
ImBuf *i = IMB_dupImBuf(ibuf);
IMB_freeImBuf(ibuf);
ibuf = i;
}
}
break;
}
case SEQ_TYPE_EFFECT:
{
ibuf = seq_render_effect_strip_impl(context, seq, seq->start + nr);
break;
}
case SEQ_TYPE_IMAGE:
{
StripElem *s_elem = BKE_sequencer_give_stripelem(seq, cfra);
if (s_elem) {
BLI_join_dirfile(name, sizeof(name), seq->strip->dir, s_elem->name);
BLI_path_abs(name, G.main->name);
}
if (s_elem && (ibuf = IMB_loadiffname(name, IB_rect))) {
/* we don't need both (speed reasons)! */
if (ibuf->rect_float && ibuf->rect)
imb_freerectImBuf(ibuf);
/* all sequencer color is done in SRGB space, linear gives odd crossfades */
if (ibuf->profile == IB_PROFILE_LINEAR_RGB)
IMB_convert_profile(ibuf, IB_PROFILE_NONE);
copy_to_ibuf_still(context, seq, nr, ibuf);
s_elem->orig_width = ibuf->x;
s_elem->orig_height = ibuf->y;
}
break;
}
case SEQ_TYPE_MOVIE:
{
seq_open_anim_file(seq);
if (seq->anim) {
IMB_anim_set_preseek(seq->anim, seq->anim_preseek);
ibuf = IMB_anim_absolute(seq->anim, nr + seq->anim_startofs,
seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN,
seq_rendersize_to_proxysize(context.preview_render_size));
/* we don't need both (speed reasons)! */
if (ibuf && ibuf->rect_float && ibuf->rect)
imb_freerectImBuf(ibuf);
if (ibuf) {
seq->strip->stripdata->orig_width = ibuf->x;
seq->strip->stripdata->orig_height = ibuf->y;
}
}
copy_to_ibuf_still(context, seq, nr, ibuf);
break;
}
case SEQ_TYPE_SCENE:
{
/* scene can be NULL after deletions */
ibuf = seq_render_scene_strip(context, seq, nr);
/* Scene strips update all animation, so we need to restore original state.*/
BKE_animsys_evaluate_all_animation(context.bmain, context.scene, cfra);
copy_to_ibuf_still(context, seq, nr, ibuf);
break;
}
case SEQ_TYPE_MOVIECLIP:
{
ibuf = seq_render_movieclip_strip(context, seq, nr);
if (ibuf && use_preprocess) {
ImBuf *i = IMB_dupImBuf(ibuf);
IMB_freeImBuf(ibuf);
ibuf = i;
}
copy_to_ibuf_still(context, seq, nr, ibuf);
break;
}
case SEQ_TYPE_MASK:
{
/* ibuf is alwats new */
ibuf = seq_render_mask_strip(context, seq, nr);
copy_to_ibuf_still(context, seq, nr, ibuf);
break;
if (ibuf)
BKE_sequencer_preprocessed_cache_put(context, seq, cfra, SEQ_STRIPELEM_IBUF, ibuf);
}
}
@ -2855,6 +2938,9 @@ static void free_anim_seq(Sequence *seq)
/* check whether sequence cur depends on seq */
int BKE_sequence_check_depend(Sequence *seq, Sequence *cur)
{
if (cur->seq1 == seq || cur->seq2 == seq || cur->seq3 == seq)
return TRUE;
/* sequences are not intersecting in time, assume no dependency exists between them */
if (cur->enddisp < seq->startdisp || cur->startdisp > seq->enddisp)
return FALSE;
@ -2876,7 +2962,7 @@ int BKE_sequence_check_depend(Sequence *seq, Sequence *cur)
return TRUE;
}
void BKE_sequence_invalidate_cache(Scene *scene, Sequence *seq)
static void sequence_invalidate_cache(Scene *scene, Sequence *seq, int invalidate_preprocess)
{
Editing *ed = scene->ed;
Sequence *cur;
@ -2884,18 +2970,33 @@ void BKE_sequence_invalidate_cache(Scene *scene, Sequence *seq)
/* invalidate cache for current sequence */
BKE_sequencer_cache_cleanup_sequence(seq);
if (invalidate_preprocess)
BKE_sequencer_preprocessed_cache_cleanup_sequence(seq);
/* invalidate cache for all dependent sequences */
SEQ_BEGIN (ed, cur)
{
if (cur == seq)
continue;
if (BKE_sequence_check_depend(seq, cur))
if (BKE_sequence_check_depend(seq, cur)) {
BKE_sequencer_cache_cleanup_sequence(cur);
BKE_sequencer_preprocessed_cache_cleanup_sequence(cur);
}
}
SEQ_END
}
void BKE_sequence_invalidate_cache(Scene *scene, Sequence *seq)
{
sequence_invalidate_cache(scene, seq, TRUE);
}
void BKE_sequence_invalidate_cache_for_modifier(Scene *scene, Sequence *seq)
{
sequence_invalidate_cache(scene, seq, FALSE);
}
void BKE_sequencer_free_imbuf(Scene *scene, ListBase *seqbase, int check_mem_usage, int keep_file_handles)
{
Sequence *seq;
@ -3531,8 +3632,8 @@ int BKE_sequence_swap(Sequence *seq_a, Sequence *seq_b, const char **error_str)
SWAP(float, seq_a->blend_opacity, seq_b->blend_opacity);
SWAP(void *, seq_a->prev, seq_b->prev);
SWAP(void *, seq_a->next, seq_b->next);
SWAP(Sequence *, seq_a->prev, seq_b->prev);
SWAP(Sequence *, seq_a->next, seq_b->next);
SWAP(int, seq_a->start, seq_b->start);
SWAP(int, seq_a->startofs, seq_b->startofs);
SWAP(int, seq_a->endofs, seq_b->endofs);
@ -3941,6 +4042,12 @@ static Sequence *seq_dupli(Scene *scene, Scene *scene_to, Sequence *seq, int dup
seqn->strip->color_balance = MEM_dupallocN(seq->strip->color_balance);
}
if (seqn->modifiers.first) {
seqn->modifiers.first = seqn->modifiers.last = NULL;
BKE_sequence_modifier_list_copy(seqn, seq);
}
if (seq->type == SEQ_TYPE_META) {
seqn->strip->stripdata = NULL;
@ -4060,3 +4167,4 @@ int BKE_seqence_is_valid_check(Sequence *seq)
return TRUE;
}

@ -774,37 +774,37 @@ void sound_force_device(int UNUSED(device)) {}
void sound_init_once(void) {}
void sound_init(struct Main *UNUSED(bmain)) {}
void sound_exit(void) {}
void sound_cache(struct bSound* UNUSED(sound)) { }
void sound_delete_cache(struct bSound* UNUSED(sound)) {}
void sound_load(struct Main *UNUSED(bmain), struct bSound* UNUSED(sound)) {}
void sound_cache(struct bSound *UNUSED(sound)) { }
void sound_delete_cache(struct bSound *UNUSED(sound)) {}
void sound_load(struct Main *UNUSED(bmain), struct bSound *UNUSED(sound)) {}
void sound_create_scene(struct Scene *UNUSED(scene)) {}
void sound_destroy_scene(struct Scene *UNUSED(scene)) {}
void sound_mute_scene(struct Scene *UNUSED(scene), int UNUSED(muted)) {}
void* sound_scene_add_scene_sound(struct Scene *UNUSED(scene), struct Sequence* UNUSED(sequence), int UNUSED(startframe), int UNUSED(endframe), int UNUSED(frameskip)) { return NULL; }
void* sound_scene_add_scene_sound_defaults(struct Scene *UNUSED(scene), struct Sequence* UNUSED(sequence)) { return NULL; }
void* sound_add_scene_sound(struct Scene *UNUSED(scene), struct Sequence* UNUSED(sequence), int UNUSED(startframe), int UNUSED(endframe), int UNUSED(frameskip)) { return NULL; }
void* sound_add_scene_sound_defaults(struct Scene *UNUSED(scene), struct Sequence* UNUSED(sequence)) { return NULL; }
void sound_remove_scene_sound(struct Scene *UNUSED(scene), void* UNUSED(handle)) {}
void sound_mute_scene_sound(void* UNUSED(handle), char UNUSED(mute)) {}
void sound_move_scene_sound(struct Scene *UNUSED(scene), void* UNUSED(handle), int UNUSED(startframe), int UNUSED(endframe), int UNUSED(frameskip)) {}
void *sound_scene_add_scene_sound(struct Scene *UNUSED(scene), struct Sequence *UNUSED(sequence), int UNUSED(startframe), int UNUSED(endframe), int UNUSED(frameskip)) { return NULL; }
void *sound_scene_add_scene_sound_defaults(struct Scene *UNUSED(scene), struct Sequence *UNUSED(sequence)) { return NULL; }
void *sound_add_scene_sound(struct Scene *UNUSED(scene), struct Sequence *UNUSED(sequence), int UNUSED(startframe), int UNUSED(endframe), int UNUSED(frameskip)) { return NULL; }
void *sound_add_scene_sound_defaults(struct Scene *UNUSED(scene), struct Sequence *UNUSED(sequence)) { return NULL; }
void sound_remove_scene_sound(struct Scene *UNUSED(scene), void *UNUSED(handle)) {}
void sound_mute_scene_sound(void *UNUSED(handle), char UNUSED(mute)) {}
void sound_move_scene_sound(struct Scene *UNUSED(scene), void *UNUSED(handle), int UNUSED(startframe), int UNUSED(endframe), int UNUSED(frameskip)) {}
void sound_move_scene_sound_defaults(struct Scene *UNUSED(scene), struct Sequence *UNUSED(sequence)) {}
void sound_play_scene(struct Scene *UNUSED(scene)) {}
void sound_stop_scene(struct Scene *UNUSED(scene)) {}
void sound_seek_scene(struct Main *UNUSED(bmain), struct Scene *UNUSED(scene)) {}
float sound_sync_scene(struct Scene *UNUSED(scene)) { return NAN_FLT; }
int sound_scene_playing(struct Scene *UNUSED(scene)) { return -1; }
int sound_read_sound_buffer(struct bSound* UNUSED(sound), float* UNUSED(buffer), int UNUSED(length), float UNUSED(start), float UNUSED(end)) { return 0; }
void sound_read_waveform(struct bSound* sound) { (void)sound; }
int sound_read_sound_buffer(struct bSound *UNUSED(sound), float *UNUSED(buffer), int UNUSED(length), float UNUSED(start), float UNUSED(end)) { return 0; }
void sound_read_waveform(struct bSound *sound) { (void)sound; }
void sound_init_main(struct Main *bmain) { (void)bmain; }
void sound_set_cfra(int cfra) { (void)cfra; }
void sound_update_sequencer(struct Main* main, struct bSound* sound) { (void)main; (void)sound; }
void sound_update_scene(struct Scene* scene) { (void)scene; }
void sound_update_scene_sound(void* handle, struct bSound* sound) { (void)handle; (void)sound; }
void sound_update_sequencer(struct Main *main, struct bSound *sound) { (void)main; (void)sound; }
void sound_update_scene(struct Scene *scene) { (void)scene; }
void sound_update_scene_sound(void *handle, struct bSound *sound) { (void)handle; (void)sound; }
void sound_update_scene_listener(struct Scene *scene) { (void)scene; }
void sound_update_fps(struct Scene *scene) { (void)scene; }
void sound_set_scene_sound_volume(void* handle, float volume, char animated) { (void)handle; (void)volume; (void)animated; }
void sound_set_scene_sound_pan(void* handle, float pan, char animated) { (void)handle; (void)pan; (void)animated; }
void sound_set_scene_sound_volume(void *handle, float volume, char animated) { (void)handle; (void)volume; (void)animated; }
void sound_set_scene_sound_pan(void *handle, float pan, char animated) { (void)handle; (void)pan; (void)animated; }
void sound_set_scene_volume(struct Scene *scene, float volume) { (void)scene; (void)volume; }
void sound_set_scene_sound_pitch(void* handle, float pitch, char animated) { (void)handle; (void)pitch; (void)animated; }
float sound_get_length(struct bSound* sound) { (void)sound; return 0; }
void sound_set_scene_sound_pitch(void *handle, float pitch, char animated) { (void)handle; (void)pitch; (void)animated; }
float sound_get_length(struct bSound *sound) { (void)sound; return 0; }
#endif // WITH_AUDASPACE

@ -113,7 +113,8 @@ typedef enum {
CCG_USE_ARENA = 2,
CCG_CALC_NORMALS = 4,
/* add an extra four bytes for a mask layer */
CCG_ALLOC_MASK = 8
CCG_ALLOC_MASK = 8,
CCG_SIMPLE_SUBDIV = 16
} CCGFlags;
static CCGSubSurf *_getSubSurf(CCGSubSurf *prevSS, int subdivLevels,
@ -133,7 +134,10 @@ static CCGSubSurf *_getSubSurf(CCGSubSurf *prevSS, int subdivLevels,
ccgSubSurf_getUseAgeCounts(prevSS, &oldUseAging, NULL, NULL, NULL);
if (oldUseAging != useAging) {
if ((oldUseAging != useAging) ||
(ccgSubSurf_getSimpleSubdiv(prevSS) !=
!!(flags & CCG_SIMPLE_SUBDIV)))
{
ccgSubSurf_free(prevSS);
}
else {
@ -156,6 +160,7 @@ static CCGSubSurf *_getSubSurf(CCGSubSurf *prevSS, int subdivLevels,
ifc.vertDataSize += sizeof(float) * 3;
if (flags & CCG_ALLOC_MASK)
ifc.vertDataSize += sizeof(float);
ifc.simpleSubdiv = !!(flags & CCG_SIMPLE_SUBDIV);
if (useArena) {
CCGAllocatorIFC allocatorIFC;
@ -1463,9 +1468,9 @@ static void ccgdm_getVertCos(DerivedMesh *dm, float (*cos)[3])
}
static void ccgDM_foreachMappedVert(
DerivedMesh *dm,
void (*func)(void *userData, int index, const float co[3], const float no_f[3], const short no_s[3]),
void *userData)
DerivedMesh *dm,
void (*func)(void *userData, int index, const float co[3], const float no_f[3], const short no_s[3]),
void *userData)
{
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
CCGVertIterator *vi;
@ -1485,9 +1490,9 @@ static void ccgDM_foreachMappedVert(
}
static void ccgDM_foreachMappedEdge(
DerivedMesh *dm,
void (*func)(void *userData, int index, const float v0co[3], const float v1co[3]),
void *userData)
DerivedMesh *dm,
void (*func)(void *userData, int index, const float v0co[3], const float v1co[3]),
void *userData)
{
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
CCGSubSurf *ss = ccgdm->ss;
@ -2487,9 +2492,9 @@ static void ccgDM_drawMappedEdgesInterp(DerivedMesh *dm,
}
static void ccgDM_foreachMappedFaceCenter(
DerivedMesh *dm,
void (*func)(void *userData, int index, const float co[3], const float no[3]),
void *userData)
DerivedMesh *dm,
void (*func)(void *userData, int index, const float co[3], const float no[3]),
void *userData)
{
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
CCGSubSurf *ss = ccgdm->ss;
@ -3474,7 +3479,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
float (*vertCos)[3],
SubsurfFlags flags)
{
int useSimple = smd->subdivType == ME_SIMPLE_SUBSURF;
int useSimple = (smd->subdivType == ME_SIMPLE_SUBSURF) ? CCG_SIMPLE_SUBDIV : 0;
CCGFlags useAging = smd->flags & eSubsurfModifierFlag_DebugIncr ? CCG_USE_AGING : 0;
int useSubsurfUv = smd->flags & eSubsurfModifierFlag_SubsurfUv;
int drawInteriorEdges = !(smd->flags & eSubsurfModifierFlag_ControlEdges);
@ -3483,7 +3488,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
if (flags & SUBSURF_FOR_EDIT_MODE) {
int levels = (smd->modifier.scene) ? get_render_subsurf_level(&smd->modifier.scene->r, smd->levels) : smd->levels;
smd->emCache = _getSubSurf(smd->emCache, levels, 3, useAging | CCG_CALC_NORMALS);
smd->emCache = _getSubSurf(smd->emCache, levels, 3, useSimple | useAging | CCG_CALC_NORMALS);
ss_sync_from_derivedmesh(smd->emCache, dm, vertCos, useSimple);
result = getCCGDerivedMesh(smd->emCache,
@ -3498,7 +3503,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
if (levels == 0)
return dm;
ss = _getSubSurf(NULL, levels, 3, CCG_USE_ARENA | CCG_CALC_NORMALS);
ss = _getSubSurf(NULL, levels, 3, useSimple | CCG_USE_ARENA | CCG_CALC_NORMALS);
ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple);
@ -3529,7 +3534,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
}
if (useIncremental && (flags & SUBSURF_IS_FINAL_CALC)) {
smd->mCache = ss = _getSubSurf(smd->mCache, levels, 3, useAging | CCG_CALC_NORMALS);
smd->mCache = ss = _getSubSurf(smd->mCache, levels, 3, useSimple | useAging | CCG_CALC_NORMALS);
ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple);
@ -3538,7 +3543,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
useSubsurfUv, dm);
}
else {
CCGFlags ccg_flags = CCG_USE_ARENA | CCG_CALC_NORMALS;
CCGFlags ccg_flags = useSimple | CCG_USE_ARENA | CCG_CALC_NORMALS;
if (smd->mCache && (flags & SUBSURF_IS_FINAL_CALC)) {
ccgSubSurf_free(smd->mCache);

@ -1292,7 +1292,7 @@ PointDensity *BKE_add_pointdensity(void)
pd->falloff_curve->preset = CURVE_PRESET_LINE;
pd->falloff_curve->cm->flag &= ~CUMA_EXTEND_EXTRAPOLATE;
curvemap_reset(pd->falloff_curve->cm, &pd->falloff_curve->clipr, pd->falloff_curve->preset, CURVEMAP_SLOPE_POSITIVE);
curvemapping_changed(pd->falloff_curve, 0);
curvemapping_changed(pd->falloff_curve, FALSE);
return pd;
}

@ -128,8 +128,9 @@ World *BKE_world_copy(World *wrld)
}
}
if (wrld->nodetree)
if (wrld->nodetree) {
wrldn->nodetree = ntreeCopyTree(wrld->nodetree);
}
if (wrld->preview)
wrldn->preview = BKE_previewimg_copy(wrld->preview);

@ -69,8 +69,6 @@
#include "ffmpeg_compat.h"
extern void do_init_ffmpeg(void);
static int ffmpeg_type = 0;
static int ffmpeg_codec = CODEC_ID_MPEG4;
static int ffmpeg_audio_codec = CODEC_ID_NONE;
@ -101,6 +99,8 @@ static AUD_Device *audio_mixdown_device = 0;
#define FFMPEG_AUTOSPLIT_SIZE 2000000000
#define PRINT if (G.debug & G_DEBUG_FFMPEG) printf
/* Delete a picture buffer */
static void delete_picture(AVFrame *f)
@ -125,9 +125,7 @@ static int write_audio_frame(void)
AUD_readDevice(audio_mixdown_device, audio_input_buffer, audio_input_samples);
audio_time += (double) audio_input_samples / (double) c->sample_rate;
pkt.size = avcodec_encode_audio(c, audio_output_buffer,
audio_outbuf_size,
(short *)audio_input_buffer);
pkt.size = avcodec_encode_audio(c, audio_output_buffer, audio_outbuf_size, (short *) audio_input_buffer);
if (pkt.size < 0) {
// XXX error("Error writing audio packet");
@ -137,9 +135,8 @@ static int write_audio_frame(void)
pkt.data = audio_output_buffer;
if (c->coded_frame && c->coded_frame->pts != AV_NOPTS_VALUE) {
pkt.pts = av_rescale_q(c->coded_frame->pts,
c->time_base, audio_stream->time_base);
fprintf(stderr, "Audio Frame PTS: %d\n", (int)pkt.pts);
pkt.pts = av_rescale_q(c->coded_frame->pts, c->time_base, audio_stream->time_base);
PRINT("Audio Frame PTS: %d\n", (int) pkt.pts);
}
pkt.stream_index = audio_stream->index;
@ -189,8 +186,7 @@ static const char **get_file_extensions(int format)
return rv;
}
case FFMPEG_MPEG2: {
static const char *rv[] = { ".dvd", ".vob", ".mpg", ".mpeg",
NULL };
static const char *rv[] = { ".dvd", ".vob", ".mpg", ".mpeg", NULL };
return rv;
}
case FFMPEG_MPEG4: {
@ -254,21 +250,18 @@ static int write_video_frame(RenderData *rd, int cfra, AVFrame *frame, ReportLis
frame->top_field_first = ((rd->mode & R_ODDFIELD) != 0);
}
outsize = avcodec_encode_video(c, video_buffer, video_buffersize,
frame);
outsize = avcodec_encode_video(c, video_buffer, video_buffersize, frame);
if (outsize > 0) {
AVPacket packet;
av_init_packet(&packet);
if (c->coded_frame->pts != AV_NOPTS_VALUE) {
packet.pts = av_rescale_q(c->coded_frame->pts,
c->time_base,
video_stream->time_base);
fprintf(stderr, "Video Frame PTS: %d\n", (int)packet.pts);
packet.pts = av_rescale_q(c->coded_frame->pts, c->time_base, video_stream->time_base);
PRINT("Video Frame PTS: %d\n", (int)packet.pts);
}
else {
fprintf(stderr, "Video Frame PTS: not set\n");
PRINT("Video Frame PTS: not set\n");
}
if (c->coded_frame->key_frame)
packet.flags |= AV_PKT_FLAG_KEY;
@ -364,7 +357,7 @@ static void set_ffmpeg_property_option(AVCodecContext *c, IDProperty *prop)
char *param;
const AVOption *rv = NULL;
fprintf(stderr, "FFMPEG expert option: %s: ", prop->name);
PRINT("FFMPEG expert option: %s: ", prop->name);
BLI_strncpy(name, prop->name, sizeof(name));
@ -376,15 +369,15 @@ static void set_ffmpeg_property_option(AVCodecContext *c, IDProperty *prop)
switch (prop->type) {
case IDP_STRING:
fprintf(stderr, "%s.\n", IDP_String(prop));
PRINT("%s.\n", IDP_String(prop));
av_set_string3(c, prop->name, IDP_String(prop), 1, &rv);
break;
case IDP_FLOAT:
fprintf(stderr, "%g.\n", IDP_Float(prop));
PRINT("%g.\n", IDP_Float(prop));
rv = av_set_double(c, prop->name, IDP_Float(prop));
break;
case IDP_INT:
fprintf(stderr, "%d.\n", IDP_Int(prop));
PRINT("%d.\n", IDP_Int(prop));
if (param) {
if (IDP_Int(prop)) {
@ -401,8 +394,7 @@ static void set_ffmpeg_property_option(AVCodecContext *c, IDProperty *prop)
}
if (!rv) {
fprintf(stderr, "ffmpeg-option not supported: %s! Skipping.\n",
prop->name);
PRINT("ffmpeg-option not supported: %s! Skipping.\n", prop->name);
}
}
@ -446,11 +438,14 @@ 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,
int rectx, int recty)
int rectx, int recty, char *error, int error_size)
{
AVStream *st;
AVCodecContext *c;
AVCodec *codec;
error[0] = '\0';
st = av_new_stream(of, 0);
if (!st) return NULL;
@ -460,7 +455,6 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
c->codec_id = codec_id;
c->codec_type = AVMEDIA_TYPE_VIDEO;
/* Get some values from the current render settings */
c->width = rectx;
@ -492,7 +486,8 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
c->me_method = ME_EPZS;
codec = avcodec_find_encoder(c->codec_id);
if (!codec) return NULL;
if (!codec)
return NULL;
/* Be sure to use the correct pixel format(e.g. RGB, YUV) */
@ -547,27 +542,25 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
// || !strcmp(of->oformat->name, "3gp")
)
{
fprintf(stderr, "Using global header\n");
PRINT("Using global header\n");
c->flags |= CODEC_FLAG_GLOBAL_HEADER;
}
/* Determine whether we are encoding interlaced material or not */
if (rd->mode & R_FIELDS) {
fprintf(stderr, "Encoding interlaced video\n");
PRINT("Encoding interlaced video\n");
c->flags |= CODEC_FLAG_INTERLACED_DCT;
c->flags |= CODEC_FLAG_INTERLACED_ME;
}
/* xasp & yasp got float lately... */
st->sample_aspect_ratio = c->sample_aspect_ratio = av_d2q(
((double) rd->xasp / (double) rd->yasp), 255);
st->sample_aspect_ratio = c->sample_aspect_ratio = av_d2q(((double) rd->xasp / (double) rd->yasp), 255);
set_ffmpeg_properties(rd, c, "video");
if (avcodec_open(c, codec) < 0) {
//
//XXX error("Couldn't initialize codec");
BLI_strncpy(error, IMB_ffmpeg_last_error(), error_size);
return NULL;
}
@ -584,16 +577,11 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
else
video_buffersize = avpicture_get_size(c->pix_fmt, c->width, c->height);
video_buffer = (uint8_t *)MEM_mallocN(video_buffersize * sizeof(uint8_t),
"FFMPEG video buffer");
video_buffer = (uint8_t *)MEM_mallocN(video_buffersize * sizeof(uint8_t), "FFMPEG video buffer");
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,
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;
}
@ -645,11 +633,9 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex
audio_outbuf_size = c->frame_size * c->channels * sizeof(int16_t) * 4;
}
audio_output_buffer = (uint8_t *)av_malloc(
audio_outbuf_size);
audio_output_buffer = (uint8_t *) av_malloc(audio_outbuf_size);
audio_input_buffer = (uint8_t *)av_malloc(
audio_input_samples * c->channels * sizeof(int16_t));
audio_input_buffer = (uint8_t *) av_malloc(audio_input_samples * c->channels * sizeof(int16_t));
audio_time = 0.0f;
@ -672,7 +658,7 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
AVFormatContext *of;
AVOutputFormat *fmt;
AVDictionary *opts = NULL;
char name[256];
char name[256], error[1024];
const char **exts;
ffmpeg_type = rd->ffcodecdata.type;
@ -681,14 +667,11 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
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;
ffmpeg_autosplit = rd->ffcodecdata.flags & FFMPEG_AUTOSPLIT_OUTPUT;
do_init_ffmpeg();
/* Determine the correct filename */
BKE_ffmpeg_filepath_get(name, rd);
fprintf(stderr, "Starting output to %s(ffmpeg)...\n"
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"
@ -793,10 +776,14 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
}
if (fmt->video_codec != CODEC_ID_NONE) {
video_stream = alloc_video_stream(rd, fmt->video_codec, of, rectx, recty);
printf("alloc video stream %p\n", video_stream);
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) {
BKE_report(reports, RPT_ERROR, "Error initializing video stream.");
if (error[0])
BKE_report(reports, RPT_ERROR, error);
else
BKE_report(reports, RPT_ERROR, "Error initializing video stream.");
av_dict_free(&opts);
return 0;
}
@ -867,13 +854,11 @@ void flush_ffmpeg(void)
break;
}
if (c->coded_frame->pts != AV_NOPTS_VALUE) {
packet.pts = av_rescale_q(c->coded_frame->pts,
c->time_base,
video_stream->time_base);
fprintf(stderr, "Video Frame PTS: %d\n", (int)packet.pts);
packet.pts = av_rescale_q(c->coded_frame->pts, c->time_base, video_stream->time_base);
PRINT("Video Frame PTS: %d\n", (int) packet.pts);
}
else {
fprintf(stderr, "Video Frame PTS: not set\n");
PRINT("Video Frame PTS: not set\n");
}
if (c->coded_frame->key_frame) {
packet.flags |= AV_PKT_FLAG_KEY;
@ -916,8 +901,7 @@ void BKE_ffmpeg_filepath_get(char *string, RenderData *rd)
}
while (*fe) {
if (BLI_strcasecmp(string + strlen(string) - strlen(*fe),
*fe) == 0)
if (BLI_strcasecmp(string + strlen(string) - strlen(*fe), *fe) == 0)
{
break;
}
@ -983,9 +967,7 @@ int BKE_ffmpeg_append(RenderData *rd, int start_frame, int frame, int *pixels, i
AVFrame *avframe;
int success = 1;
fprintf(stderr, "Writing frame %i, "
"render width=%d, render height=%d\n", frame,
rectx, recty);
PRINT("Writing frame %i, render width=%d, render height=%d\n", frame, rectx, recty);
// 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));
@ -1013,7 +995,7 @@ void BKE_ffmpeg_end(void)
{
unsigned int i;
fprintf(stderr, "Closing ffmpeg...\n");
PRINT("Closing ffmpeg...\n");
#if 0
if (audio_stream) { /* SEE UPPER */
@ -1029,7 +1011,7 @@ void BKE_ffmpeg_end(void)
#endif
if (video_stream && video_stream->codec) {
fprintf(stderr, "Flushing delayed frames...\n");
PRINT("Flushing delayed frames...\n");
flush_ffmpeg();
}
@ -1041,7 +1023,7 @@ void BKE_ffmpeg_end(void)
if (video_stream && video_stream->codec) {
avcodec_close(video_stream->codec);
printf("zero video stream %p\n", video_stream);
PRINT("zero video stream %p\n", video_stream);
video_stream = 0;
}
@ -1142,8 +1124,7 @@ IDProperty *BKE_ffmpeg_property_add(RenderData *rd, const char *type, int opt_in
BLI_strncpy(name, o->name, sizeof(name));
}
fprintf(stderr, "ffmpeg_property_add: %s %d %d %s\n",
type, parent_index, opt_index, name);
PRINT("ffmpeg_property_add: %s %d %d %s\n", type, parent_index, opt_index, name);
prop = IDP_GetPropertyFromGroup(group, name);
if (prop) {
@ -1181,8 +1162,7 @@ IDProperty *BKE_ffmpeg_property_add(RenderData *rd, const char *type, int opt_in
/* not all versions of ffmpeg include that, so here we go ... */
static const AVOption *my_av_find_opt(void *v, const char *name,
const char *unit, int mask, int flags)
static const AVOption *my_av_find_opt(void *v, const char *name, const char *unit, int mask, int flags)
{
AVClass *c = *(AVClass **)v;
const AVOption *o = c->option;
@ -1235,14 +1215,11 @@ int BKE_ffmpeg_property_add_string(RenderData *rd, const char *type, const char
if (param && o->type != FF_OPT_TYPE_CONST && o->unit) {
p = my_av_find_opt(&c, param, o->unit, 0, 0);
if (p) {
prop = BKE_ffmpeg_property_add(rd,
(char *) type, p - c.av_class->option,
o - c.av_class->option);
prop = BKE_ffmpeg_property_add(rd, (char *) type, p - c.av_class->option, o - c.av_class->option);
}
}
else {
prop = BKE_ffmpeg_property_add(rd,
(char *) type, o - c.av_class->option, 0);
prop = BKE_ffmpeg_property_add(rd, (char *) type, o - c.av_class->option, 0);
}
@ -1316,12 +1293,10 @@ static void ffmpeg_set_expert_options(RenderData *rd)
if (rd->ffcodecdata.flags & FFMPEG_LOSSLESS_OUTPUT)
BKE_ffmpeg_property_add_string(rd, "video", "cqp:0");
}
#if 0 /* disabled for after release */
else if (codec_id == CODEC_ID_DNXHD) {
if (rd->ffcodecdata.flags & FFMPEG_LOSSLESS_OUTPUT)
ffmpeg_property_add_string(rd, "video", "mbd:rd");
BKE_ffmpeg_property_add_string(rd, "video", "mbd:rd");
}
#endif
}
void BKE_ffmpeg_preset_set(RenderData *rd, int preset)

@ -48,11 +48,13 @@ int BLI_findstringindex(const struct ListBase *listbase, const char *id, const i
void *BLI_findlink(const struct ListBase *listbase, int number);
void *BLI_findstring(const struct ListBase *listbase, const char *id, const int offset);
void *BLI_findstring_ptr(const struct ListBase *listbase, const char *id, const int offset);
void *BLI_findptr(const struct ListBase *listbase, const void *ptr, const int offset);
/* find backwards */
void *BLI_rfindlink(const struct ListBase *listbase, int number);
void *BLI_rfindstring(const struct ListBase *listbase, const char *id, const int offset);
void *BLI_rfindstring_ptr(const struct ListBase *listbase, const char *id, const int offset);
void *BLI_rfindptr(const struct ListBase *listbase, const void *ptr, const int offset);
void BLI_freelistN(struct ListBase *listbase);
void BLI_addtail(struct ListBase *listbase, void *vlink);

@ -137,8 +137,30 @@
# endif
#endif
/* Causes warning:
* incompatible types when assigning to type 'Foo' from type 'Bar'
* ... the compiler optimizes away the temp var */
#ifndef CHECK_TYPE
#ifdef __GNUC__
#define CHECK_TYPE(var, type) { \
__typeof(var) *__tmp; \
__tmp = (type *)NULL; \
(void)__tmp; \
} (void)0
#else
#define CHECK_TYPE(var, type)
#endif
#endif
#ifndef SWAP
# define SWAP(type, a, b) { type sw_ap; sw_ap = (a); (a) = (b); (b) = sw_ap; } (void)0
# define SWAP(type, a, b) { \
type sw_ap; \
CHECK_TYPE(a, type); \
CHECK_TYPE(b, type); \
sw_ap = (a); \
(a) = (b); \
(b) = sw_ap; \
} (void)0
#endif
#ifndef CLAMP

@ -60,6 +60,7 @@ void sub_qt_qtqt(float q[4], const float a[4], const float b[4]);
void invert_qt(float q[4]);
void invert_qt_qt(float q1[4], const float q2[4]);
void conjugate_qt(float q[4]);
void conjugate_qt_qt(float q1[4], const float q2[4]);
float dot_qtqt(const float a[4], const float b[4]);
float normalize_qt(float q[4]);
float normalize_qt_qt(float q1[4], const float q2[4]);
@ -151,10 +152,10 @@ void mat3_to_eulO(float eul[3], const short order, float mat[3][3]);
void mat4_to_eulO(float eul[3], const short order, float mat[4][4]);
void axis_angle_to_eulO(float eul[3], const short order, const float axis[3], const float angle);
void mat3_to_compatible_eulO(float eul[3], float old[3], short order, float mat[3][3]);
void mat4_to_compatible_eulO(float eul[3], float old[3], short order, float mat[4][4]);
void mat3_to_compatible_eulO(float eul[3], float old[3], const short order, float mat[3][3]);
void mat4_to_compatible_eulO(float eul[3], float old[3], const short order, float mat[4][4]);
void rotate_eulO(float eul[3], short order, char axis, float angle);
void rotate_eulO(float eul[3], const short order, char axis, float angle);
/******************************* Dual Quaternions ****************************/

@ -220,6 +220,9 @@ MINLINE void normal_float_to_short_v3(short r[3], const float n[3]);
void minmax_v3v3_v3(float min[3], float max[3], const float vec[3]);
void dist_ensure_v3_v3fl(float v1[3], const float v2[3], const float dist);
void dist_ensure_v2_v2fl(float v1[2], const float v2[2], const float dist);
/***************************** Array Functions *******************************/
/* attempted to follow fixed length vertex functions. names could be improved*/
double dot_vn_vn(const float *array_src_a, const float *array_src_b, const int size);

@ -260,8 +260,8 @@ void BLI_pbvh_node_free_proxies(PBVHNode *node);
PBVHProxyNode *BLI_pbvh_node_add_proxy(PBVH *bvh, PBVHNode *node);
void BLI_pbvh_gather_proxies(PBVH *pbvh, PBVHNode ***nodes, int *totnode);
//void BLI_pbvh_node_BB_reset(PBVHNode* node);
//void BLI_pbvh_node_BB_expand(PBVHNode* node, float co[3]);
//void BLI_pbvh_node_BB_reset(PBVHNode *node);
//void BLI_pbvh_node_BB_expand(PBVHNode *node, float co[3]);
#endif /* __BLI_PBVH_H__ */

@ -57,25 +57,35 @@ void BLI_rctf_interp(struct rctf *rect, const struct rctf *rect_a, const struct
//void BLI_rcti_interp(struct rctf *rect, struct rctf *rect_a, struct rctf *rect_b, float fac);
int BLI_rctf_compare(const struct rctf *rect_a, const struct rctf *rect_b, const float limit);
int BLI_rcti_compare(const struct rcti *rect_a, const struct rcti *rect_b);
int BLI_in_rcti(const struct rcti *rect, const int x, const int y);
int BLI_in_rcti_v(const struct rcti *rect, const int xy[2]);
int BLI_in_rctf(const struct rctf *rect, const float x, const float y);
int BLI_in_rctf_v(const struct rctf *rect, const float xy[2]);
int BLI_rctf_isect(const struct rctf *src1, const struct rctf *src2, struct rctf *dest);
int BLI_rcti_isect(const struct rcti *src1, const struct rcti *src2, struct rcti *dest);
int BLI_rcti_isect_pt(const struct rcti *rect, const int x, const int y);
int BLI_rcti_isect_pt_v(const struct rcti *rect, const int xy[2]);
int BLI_rctf_isect_pt(const struct rctf *rect, const float x, const float y);
int BLI_rctf_isect_pt_v(const struct rctf *rect, const float xy[2]);
int BLI_rcti_isect_segment(const struct rcti *rect, const int s1[2], const int s2[2]);
#if 0 /* NOT NEEDED YET */
int BLI_rctf_isect_segment(struct rcti *rect, int s1[2], int s2[2]);
#endif
int BLI_rctf_isect(const struct rctf *src1, const struct rctf *src2, struct rctf *dest);
int BLI_rcti_isect(const struct rcti *src1, const struct rcti *src2, struct rcti *dest);
void BLI_rctf_union(struct rctf *rctf1, const struct rctf *rctf2);
void BLI_rcti_union(struct rcti *rcti1, const struct rcti *rcti2);
void BLI_rcti_rctf_copy(struct rcti *tar, const struct rctf *src);
void BLI_rcti_rctf_copy(struct rcti *dst, const struct rctf *src);
void BLI_rctf_rcti_copy(struct rctf *dst, const struct rcti *src);
void print_rctf(const char *str, const struct rctf *rect);
void print_rcti(const char *str, const struct rcti *rect);
#define BLI_RCT_SIZE_X(rct) ((rct)->xmax - (rct)->xmin)
#define BLI_RCT_SIZE_Y(rct) ((rct)->ymax - (rct)->ymin)
#define BLI_RCT_CENTER_X(rct) (((rct)->xmin + (rct)->xmax) / 2)
#define BLI_RCT_CENTER_Y(rct) (((rct)->ymin + (rct)->ymax) / 2)
#define BLI_RCT_CENTER_X_FL(rct) ((float)((rct)->xmin + (rct)->xmax) / 2.0f)
#define BLI_RCT_CENTER_Y_FL(rct) ((float)((rct)->ymin + (rct)->ymax) / 2.0f)
#ifdef __cplusplus
}
#endif
#endif
#endif /* __BLI_RECT_H__ */

@ -32,6 +32,8 @@
* \ingroup bli
*/
#include <stdarg.h>
#ifdef __cplusplus
extern "C" {
#endif
@ -139,6 +141,11 @@ __attribute__((nonnull))
#endif
;
/*
* Replacement for vsnprintf
*/
size_t BLI_vsnprintf(char *buffer, size_t count, const char *format, va_list arg);
/*
* Print formatted string into a newly mallocN'd string
* and return it.

@ -113,8 +113,30 @@
/* some math and copy defines */
/* Causes warning:
* incompatible types when assigning to type 'Foo' from type 'Bar'
* ... the compiler optimizes away the temp var */
#ifndef CHECK_TYPE
#ifdef __GNUC__
#define CHECK_TYPE(var, type) { \
__typeof(var) *__tmp; \
__tmp = (type *)NULL; \
(void)__tmp; \
} (void)0
#else
#define CHECK_TYPE(var, type)
#endif
#endif
#ifndef SWAP
# define SWAP(type, a, b) { type sw_ap; sw_ap = (a); (a) = (b); (b) = sw_ap; } (void)0
# define SWAP(type, a, b) { \
type sw_ap; \
CHECK_TYPE(a, type); \
CHECK_TYPE(b, type); \
sw_ap = (a); \
(a) = (b); \
(b) = sw_ap; \
} (void)0
#endif
#define ABS(a) ( (a) < 0 ? (-(a)) : (a) )

@ -39,14 +39,8 @@
struct PackedFile;
struct VFont;
#define MAX_VF_CHARS 256
typedef struct VFontData {
ListBase characters;
// ListBase nurbsbase[MAX_VF_CHARS];
// float resol[MAX_VF_CHARS];
// float width[MAX_VF_CHARS];
// float *points[MAX_VF_CHARS];
char name[128];
} VFontData;
@ -59,12 +53,6 @@ typedef struct VChar {
float *points;
} VChar;
struct TmpFont {
struct TmpFont *next, *prev;
struct PackedFile *pf;
struct VFont *vfont;
};
/**
* Construct a new VFontData structure from
* Freetype font data in a PackedFile.

@ -293,19 +293,12 @@ static int objchr_to_ftvfontdata(VFont *vfont, FT_ULong charcode)
{
/* Freetype2 */
FT_Face face;
struct TmpFont *tf;
/* Find the correct FreeType font */
tf = BKE_vfont_tmpfont_find(vfont);
/* What, no font found. Something strange here */
if (!tf) return FALSE;
/* Load the font to memory */
if (tf->pf) {
if (vfont->temp_pf) {
err = FT_New_Memory_Face(library,
tf->pf->data,
tf->pf->size,
vfont->temp_pf->data,
vfont->temp_pf->size,
0,
&face);
if (err) return FALSE;

@ -439,6 +439,44 @@ void *BLI_rfindstring_ptr(const ListBase *listbase, const char *id, const int of
return NULL;
}
void *BLI_findptr(const ListBase *listbase, const void *ptr, const int offset)
{
Link *link = NULL;
const void *ptr_iter;
if (listbase == NULL) return NULL;
for (link = listbase->first; link; link = link->next) {
/* exact copy of BLI_findstring(), except for this line */
ptr_iter = *((const char **)(((const char *)link) + offset));
if (ptr == ptr_iter) {
return link;
}
}
return NULL;
}
/* same as above but find reverse */
void *BLI_rfindptr(const ListBase *listbase, const void *ptr, const int offset)
{
Link *link = NULL;
const void *ptr_iter;
if (listbase == NULL) return NULL;
for (link = listbase->last; link; link = link->prev) {
/* exact copy of BLI_rfindstring(), except for this line */
ptr_iter = *((const char **)(((const char *)link) + offset));
if (ptr == ptr_iter) {
return link;
}
}
return NULL;
}
int BLI_findstringindex(const ListBase *listbase, const char *id, const int offset)
{
Link *link = NULL;

@ -34,7 +34,7 @@
/******************************** Quaternions ********************************/
/* used to test is a quat is not normalized */
/* used to test is a quat is not normalized (only used for debug prints) */
#define QUAT_EPSILON 0.0001
/* convenience, avoids setting Y axis everywhere */
@ -113,6 +113,14 @@ void mul_qt_v3(const float q[4], float v[3])
v[1] = t2;
}
void conjugate_qt_qt(float q1[4], const float q2[4])
{
q1[0] = q2[0];
q1[1] = -q2[1];
q1[2] = -q2[2];
q1[3] = -q2[3];
}
void conjugate_qt(float q[4])
{
q[1] = -q[1];
@ -370,7 +378,7 @@ float normalize_qt(float q[4])
{
float len;
len = (float)sqrt(dot_qtqt(q, q));
len = sqrtf(dot_qtqt(q, q));
if (len != 0.0f) {
mul_qt_fl(q, 1.0f / len);
}
@ -404,80 +412,75 @@ void rotation_between_vecs_to_quat(float q[4], const float v1[3], const float v2
void rotation_between_quats_to_quat(float q[4], const float q1[4], const float q2[4])
{
float tquat[4];
double dot = 0.0f;
int x;
copy_qt_qt(tquat, q1);
conjugate_qt(tquat);
dot = 1.0f / dot_qtqt(tquat, tquat);
conjugate_qt_qt(tquat, q1);
for (x = 0; x < 4; x++)
tquat[x] *= dot;
mul_qt_fl(tquat, 1.0f / dot_qtqt(tquat, tquat));
mul_qt_qtqt(q, tquat, q2);
}
void vec_to_quat(float q[4], const float vec[3], short axis, const short upflag)
{
float q2[4], nor[3], *fp, mat[3][3], angle, si, co, x2, y2, z2, len1;
float nor[3], tvec[3];
float angle, si, co, len;
assert(axis >= 0 && axis <= 5);
assert(upflag >= 0 && upflag <= 2);
/* first rotate to axis */
/* first set the quat to unit */
unit_qt(q);
len = len_v3(vec);
if (UNLIKELY(len == 0.0f)) {
return;
}
/* rotate to axis */
if (axis > 2) {
x2 = vec[0];
y2 = vec[1];
z2 = vec[2];
copy_v3_v3(tvec, vec);
axis -= 3;
}
else {
x2 = -vec[0];
y2 = -vec[1];
z2 = -vec[2];
negate_v3_v3(tvec, vec);
}
q[0] = 1.0;
q[1] = q[2] = q[3] = 0.0;
len1 = (float)sqrt(x2 * x2 + y2 * y2 + z2 * z2);
if (len1 == 0.0f) return;
/* nasty! I need a good routine for this...
* problem is a rotation of an Y axis to the negative Y-axis for example.
*/
if (axis == 0) { /* x-axis */
nor[0] = 0.0;
nor[1] = -z2;
nor[2] = y2;
nor[0] = 0.0;
nor[1] = -tvec[2];
nor[2] = tvec[1];
if (fabsf(y2) + fabsf(z2) < 0.0001f)
nor[1] = 1.0;
if (fabsf(tvec[1]) + fabsf(tvec[2]) < 0.0001f)
nor[1] = 1.0f;
co = x2;
co = tvec[0];
}
else if (axis == 1) { /* y-axis */
nor[0] = z2;
nor[1] = 0.0;
nor[2] = -x2;
nor[0] = tvec[2];
nor[1] = 0.0;
nor[2] = -tvec[0];
if (fabsf(x2) + fabsf(z2) < 0.0001f)
nor[2] = 1.0;
if (fabsf(tvec[0]) + fabsf(tvec[2]) < 0.0001f)
nor[2] = 1.0f;
co = y2;
co = tvec[1];
}
else { /* z-axis */
nor[0] = -y2;
nor[1] = x2;
nor[2] = 0.0;
nor[0] = -tvec[1];
nor[1] = tvec[0];
nor[2] = 0.0;
if (fabsf(x2) + fabsf(y2) < 0.0001f)
nor[0] = 1.0;
if (fabsf(tvec[0]) + fabsf(tvec[1]) < 0.0001f)
nor[0] = 1.0f;
co = z2;
co = tvec[2];
}
co /= len1;
co /= len;
normalize_v3(nor);
@ -489,28 +492,30 @@ void vec_to_quat(float q[4], const float vec[3], short axis, const short upflag)
q[3] = nor[2] * si;
if (axis != upflag) {
float mat[3][3];
float q2[4];
const float *fp = mat[2];
quat_to_mat3(mat, q);
fp = mat[2];
if (axis == 0) {
if (upflag == 1) angle = (float)(0.5 * atan2(fp[2], fp[1]));
else angle = (float)(-0.5 * atan2(fp[1], fp[2]));
if (upflag == 1) angle = 0.5f * atan2f(fp[2], fp[1]);
else angle = -0.5f * atan2f(fp[1], fp[2]);
}
else if (axis == 1) {
if (upflag == 0) angle = (float)(-0.5 * atan2(fp[2], fp[0]));
else angle = (float)(0.5 * atan2(fp[0], fp[2]));
if (upflag == 0) angle = -0.5f * atan2f(fp[2], fp[0]);
else angle = 0.5f * atan2f(fp[0], fp[2]);
}
else {
if (upflag == 0) angle = (float)(0.5 * atan2(-fp[1], -fp[0]));
else angle = (float)(-0.5 * atan2(-fp[0], -fp[1]));
if (upflag == 0) angle = 0.5f * atan2f(-fp[1], -fp[0]);
else angle = -0.5f * atan2f(-fp[0], -fp[1]);
}
co = cosf(angle);
si = sinf(angle) / len1;
si = sinf(angle) / len;
q2[0] = co;
q2[1] = x2 * si;
q2[2] = y2 * si;
q2[3] = z2 * si;
q2[1] = tvec[0] * si;
q2[2] = tvec[1] * si;
q2[3] = tvec[2] * si;
mul_qt_qtqt(q, q2, q);
}
@ -1040,84 +1045,46 @@ void rotate_eul(float *beul, const char axis, const float ang)
}
/* exported to transform.c */
/* order independent! */
void compatible_eul(float eul[3], const float oldrot[3])
{
float dx, dy, dz;
/* we could use M_PI as pi_thresh: which is correct but 5.1 gives better results.
* Checked with baking actions to fcurves - campbell */
const float pi_thresh = (5.1f);
const float pi_x2 = (2.0f * (float)M_PI);
float deul[3];
unsigned int i;
/* correct differences of about 360 degrees first */
dx = eul[0] - oldrot[0];
dy = eul[1] - oldrot[1];
dz = eul[2] - oldrot[2];
while (fabsf(dx) > 5.1f) {
if (dx > 0.0f) eul[0] -= 2.0f * (float)M_PI;
else eul[0] += 2.0f * (float)M_PI;
dx = eul[0] - oldrot[0];
}
while (fabsf(dy) > 5.1f) {
if (dy > 0.0f) eul[1] -= 2.0f * (float)M_PI;
else eul[1] += 2.0f * (float)M_PI;
dy = eul[1] - oldrot[1];
}
while (fabsf(dz) > 5.1f) {
if (dz > 0.0f) eul[2] -= 2.0f * (float)M_PI;
else eul[2] += 2.0f * (float)M_PI;
dz = eul[2] - oldrot[2];
for (i = 0; i < 3; i++) {
deul[i] = eul[i] - oldrot[i];
if (deul[i] > pi_thresh) {
eul[i] -= floorf(( deul[i] / pi_x2) + 0.5) * pi_x2;
deul[i] = eul[i] - oldrot[i];
}
else if (deul[i] < -pi_thresh) {
eul[i] += floorf((-deul[i] / pi_x2) + 0.5) * pi_x2;
deul[i] = eul[i] - oldrot[i];
}
}
/* is 1 of the axis rotations larger than 180 degrees and the other small? NO ELSE IF!! */
if (fabsf(dx) > 3.2f && fabsf(dy) < 1.6f && fabsf(dz) < 1.6f) {
if (dx > 0.0f) eul[0] -= 2.0f * (float)M_PI;
else eul[0] += 2.0f * (float)M_PI;
if (fabsf(deul[0]) > 3.2f && fabsf(deul[1]) < 1.6f && fabsf(deul[2]) < 1.6f) {
if (deul[0] > 0.0f) eul[0] -= pi_x2;
else eul[0] += pi_x2;
}
if (fabsf(dy) > 3.2f && fabsf(dz) < 1.6f && fabsf(dx) < 1.6f) {
if (dy > 0.0f) eul[1] -= 2.0f * (float)M_PI;
else eul[1] += 2.0f * (float)M_PI;
if (fabsf(deul[1]) > 3.2f && fabsf(deul[2]) < 1.6f && fabsf(deul[0]) < 1.6f) {
if (deul[1] > 0.0f) eul[1] -= pi_x2;
else eul[1] += pi_x2;
}
if (fabsf(dz) > 3.2f && fabsf(dx) < 1.6f && fabsf(dy) < 1.6f) {
if (dz > 0.0f) eul[2] -= 2.0f * (float)M_PI;
else eul[2] += 2.0f * (float)M_PI;
if (fabsf(deul[2]) > 3.2f && fabsf(deul[0]) < 1.6f && fabsf(deul[1]) < 1.6f) {
if (deul[2] > 0.0f) eul[2] -= pi_x2;
else eul[2] += pi_x2;
}
/* the method below was there from ancient days... but why! probably because the code sucks :)
*/
#if 0
/* calc again */
dx = eul[0] - oldrot[0];
dy = eul[1] - oldrot[1];
dz = eul[2] - oldrot[2];
/* special case, tested for x-z */
if ((fabsf(dx) > 3.1f && fabsf(dz) > 1.5f) || (fabsf(dx) > 1.5f && fabsf(dz) > 3.1f)) {
if (dx > 0.0f) eul[0] -= M_PI;
else eul[0] += M_PI;
if (eul[1] > 0.0) eul[1] = M_PI - eul[1];
else eul[1] = -M_PI - eul[1];
if (dz > 0.0f) eul[2] -= M_PI;
else eul[2] += M_PI;
}
else if ((fabsf(dx) > 3.1f && fabsf(dy) > 1.5f) || (fabsf(dx) > 1.5f && fabsf(dy) > 3.1f)) {
if (dx > 0.0f) eul[0] -= M_PI;
else eul[0] += M_PI;
if (dy > 0.0f) eul[1] -= M_PI;
else eul[1] += M_PI;
if (eul[2] > 0.0f) eul[2] = M_PI - eul[2];
else eul[2] = -M_PI - eul[2];
}
else if ((fabsf(dy) > 3.1f && fabsf(dz) > 1.5f) || (fabsf(dy) > 1.5f && fabsf(dz) > 3.f1)) {
if (eul[0] > 0.0f) eul[0] = M_PI - eul[0];
else eul[0] = -M_PI - eul[0];
if (dy > 0.0f) eul[1] -= M_PI;
else eul[1] += M_PI;
if (dz > 0.0f) eul[2] -= M_PI;
else eul[2] += M_PI;
}
#endif
#undef PI_THRESH
#undef PI_2F
}
/* uses 2 methods to retrieve eulers, and picks the closest */
@ -1166,7 +1133,7 @@ typedef struct RotOrderInfo {
/* Array of info for Rotation Order calculations
* WARNING: must be kept in same order as eEulerRotationOrders
*/
static RotOrderInfo rotOrders[] = {
static const RotOrderInfo rotOrders[] = {
/* i, j, k, n */
{{0, 1, 2}, 0}, /* XYZ */
{{0, 2, 1}, 1}, /* XZY */
@ -1185,7 +1152,7 @@ static RotOrderInfo rotOrders[] = {
/* Construct quaternion from Euler angles (in radians). */
void eulO_to_quat(float q[4], const float e[3], const short order)
{
RotOrderInfo *R = GET_ROTATIONORDER_INFO(order);
const RotOrderInfo *R = GET_ROTATIONORDER_INFO(order);
short i = R->axis[0], j = R->axis[1], k = R->axis[2];
double ti, tj, th, ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
double a[3];
@ -1230,7 +1197,7 @@ void quat_to_eulO(float e[3], short const order, const float q[4])
/* Construct 3x3 matrix from Euler angles (in radians). */
void eulO_to_mat3(float M[3][3], const float e[3], const short order)
{
RotOrderInfo *R = GET_ROTATIONORDER_INFO(order);
const RotOrderInfo *R = GET_ROTATIONORDER_INFO(order);
short i = R->axis[0], j = R->axis[1], k = R->axis[2];
double ti, tj, th, ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
@ -1269,9 +1236,9 @@ void eulO_to_mat3(float M[3][3], const float e[3], const short order)
}
/* returns two euler calculation methods, so we can pick the best */
static void mat3_to_eulo2(float M[3][3], float *e1, float *e2, short order)
static void mat3_to_eulo2(float M[3][3], float *e1, float *e2, const short order)
{
RotOrderInfo *R = GET_ROTATIONORDER_INFO(order);
const RotOrderInfo *R = GET_ROTATIONORDER_INFO(order);
short i = R->axis[0], j = R->axis[1], k = R->axis[2];
float m[3][3];
double cy;
@ -1349,7 +1316,7 @@ void mat4_to_eulO(float e[3], const short order, float M[4][4])
}
/* uses 2 methods to retrieve eulers, and picks the closest */
void mat3_to_compatible_eulO(float eul[3], float oldrot[3], short order, float mat[3][3])
void mat3_to_compatible_eulO(float eul[3], float oldrot[3], const short order, float mat[3][3])
{
float eul1[3], eul2[3];
float d1, d2;
@ -1369,7 +1336,7 @@ void mat3_to_compatible_eulO(float eul[3], float oldrot[3], short order, float m
copy_v3_v3(eul, eul1);
}
void mat4_to_compatible_eulO(float eul[3], float oldrot[3], short order, float M[4][4])
void mat4_to_compatible_eulO(float eul[3], float oldrot[3], const short order, float M[4][4])
{
float m[3][3];
@ -1381,7 +1348,7 @@ void mat4_to_compatible_eulO(float eul[3], float oldrot[3], short order, float M
/* rotate the given euler by the given angle on the specified axis */
// NOTE: is this safe to do with different axis orders?
void rotate_eulO(float beul[3], short order, char axis, float ang)
void rotate_eulO(float beul[3], const short order, char axis, float ang)
{
float eul[3], mat1[3][3], mat2[3][3], totmat[3][3];
@ -1406,7 +1373,7 @@ void rotate_eulO(float beul[3], short order, char axis, float ang)
/* the matrix is written to as 3 axis vectors */
void eulO_to_gimbal_axis(float gmat[][3], const float eul[3], const short order)
{
RotOrderInfo *R = GET_ROTATIONORDER_INFO(order);
const RotOrderInfo *R = GET_ROTATIONORDER_INFO(order);
float mat[3][3];
float teul[3];
@ -1474,10 +1441,9 @@ void mat4_to_dquat(DualQuat *dq, float basemat[][4], float mat[][4])
mult_m4_m4m4(baseRS, mat, basemat);
mat4_to_size(scale, baseRS);
copy_v3_v3(dscale, scale);
dscale[0] -= 1.0f;
dscale[1] -= 1.0f;
dscale[2] -= 1.0f;
dscale[0] = scale[0] - 1.0f;
dscale[1] = scale[1] - 1.0f;
dscale[2] = scale[2] - 1.0f;
if ((determinant_m4(mat) < 0.0f) || len_v3(dscale) > 1e-4f) {
/* extract R and S */
@ -1513,10 +1479,10 @@ void mat4_to_dquat(DualQuat *dq, float basemat[][4], float mat[][4])
/* dual part */
t = R[3];
q = dq->quat;
dq->trans[0] = -0.5f * (t[0] * q[1] + t[1] * q[2] + t[2] * q[3]);
dq->trans[1] = 0.5f * (t[0] * q[0] + t[1] * q[3] - t[2] * q[2]);
dq->trans[2] = 0.5f * (-t[0] * q[3] + t[1] * q[0] + t[2] * q[1]);
dq->trans[3] = 0.5f * (t[0] * q[2] - t[1] * q[1] + t[2] * q[0]);
dq->trans[0] = -0.5f * ( t[0] * q[1] + t[1] * q[2] + t[2] * q[3]);
dq->trans[1] = 0.5f * ( t[0] * q[0] + t[1] * q[3] - t[2] * q[2]);
dq->trans[2] = 0.5f * (-t[0] * q[3] + t[1] * q[0] + t[2] * q[1]);
dq->trans[3] = 0.5f * ( t[0] * q[2] - t[1] * q[1] + t[2] * q[0]);
}
void dquat_to_mat4(float mat[][4], DualQuat *dq)
@ -1527,7 +1493,7 @@ void dquat_to_mat4(float mat[][4], DualQuat *dq)
copy_qt_qt(q0, dq->quat);
/* normalize */
len = (float)sqrt(dot_qtqt(q0, q0));
len = sqrtf(dot_qtqt(q0, q0));
if (len != 0.0f)
mul_qt_fl(q0, 1.0f / len);

@ -451,6 +451,29 @@ void minmax_v3v3_v3(float min[3], float max[3], const float vec[3])
if (max[2] < vec[2]) max[2] = vec[2];
}
/** ensure \a v1 is \a dist from \a v2 */
void dist_ensure_v3_v3fl(float v1[3], const float v2[3], const float dist)
{
if (!equals_v3v3(v2, v1)) {
float nor[3];
sub_v3_v3v3(nor, v1, v2);
normalize_v3(nor);
madd_v3_v3v3fl(v1, v2, nor, dist);
}
}
void dist_ensure_v2_v2fl(float v1[2], const float v2[2], const float dist)
{
if (!equals_v2v2(v2, v1)) {
float nor[2];
sub_v2_v2v2(nor, v1, v2);
normalize_v2(nor);
madd_v2_v2v2fl(v1, v2, nor, dist);
}
}
/***************************** Array Functions *******************************/
double dot_vn_vn(const float *array_src_a, const float *array_src_b, const int size)

@ -260,12 +260,12 @@ static void update_node_vb(PBVH *bvh, PBVHNode *node)
node->vb = vb;
}
//void BLI_pbvh_node_BB_reset(PBVHNode* node)
//void BLI_pbvh_node_BB_reset(PBVHNode *node)
//{
// BB_reset(&node->vb);
//}
//
//void BLI_pbvh_node_BB_expand(PBVHNode* node, float co[3])
//void BLI_pbvh_node_BB_expand(PBVHNode *node, float co[3])
//{
// BB_expand(&node->vb, co);
//}

@ -58,7 +58,7 @@ int BLI_rctf_is_empty(const rctf *rect)
return ((rect->xmax <= rect->xmin) || (rect->ymax <= rect->ymin));
}
int BLI_in_rcti(const rcti *rect, const int x, const int y)
int BLI_rcti_isect_pt(const rcti *rect, const int x, const int y)
{
if (x < rect->xmin) return 0;
if (x > rect->xmax) return 0;
@ -74,7 +74,7 @@ int BLI_in_rcti(const rcti *rect, const int x, const int y)
*
* \return True if \a rect is empty.
*/
int BLI_in_rcti_v(const rcti *rect, const int xy[2])
int BLI_rcti_isect_pt_v(const rcti *rect, const int xy[2])
{
if (xy[0] < rect->xmin) return 0;
if (xy[0] > rect->xmax) return 0;
@ -83,7 +83,7 @@ int BLI_in_rcti_v(const rcti *rect, const int xy[2])
return 1;
}
int BLI_in_rctf(const rctf *rect, const float x, const float y)
int BLI_rctf_isect_pt(const rctf *rect, const float x, const float y)
{
if (x < rect->xmin) return 0;
if (x > rect->xmax) return 0;
@ -92,7 +92,7 @@ int BLI_in_rctf(const rctf *rect, const float x, const float y)
return 1;
}
int BLI_in_rctf_v(const rctf *rect, const float xy[2])
int BLI_rctf_isect_pt_v(const rctf *rect, const float xy[2])
{
if (xy[0] < rect->xmin) return 0;
if (xy[0] > rect->xmax) return 0;
@ -124,7 +124,7 @@ int BLI_rcti_isect_segment(const rcti *rect, const int s1[2], const int s2[2])
if (s1[1] > rect->ymax && s2[1] > rect->ymax) return 0;
/* if either points intersect then we definetly intersect */
if (BLI_in_rcti_v(rect, s1) || BLI_in_rcti_v(rect, s2)) {
if (BLI_rcti_isect_pt_v(rect, s1) || BLI_rcti_isect_pt_v(rect, s2)) {
return 1;
}
else {
@ -252,8 +252,8 @@ void BLI_rctf_translate(rctf *rect, float x, float y)
/* change width & height around the central location */
void BLI_rcti_resize(rcti *rect, int x, int y)
{
rect->xmin = rect->xmax = (rect->xmax + rect->xmin) / 2;
rect->ymin = rect->ymax = (rect->ymax + rect->ymin) / 2;
rect->xmin = rect->xmax = BLI_RCT_CENTER_X(rect);
rect->ymin = rect->ymax = BLI_RCT_CENTER_Y(rect);
rect->xmin -= x / 2;
rect->ymin -= y / 2;
rect->xmax = rect->xmin + x;
@ -262,8 +262,8 @@ void BLI_rcti_resize(rcti *rect, int x, int y)
void BLI_rctf_resize(rctf *rect, float x, float y)
{
rect->xmin = rect->xmax = (rect->xmax + rect->xmin) * 0.5f;
rect->ymin = rect->ymax = (rect->ymax + rect->ymin) * 0.5f;
rect->xmin = rect->xmax = BLI_RCT_CENTER_X(rect);
rect->ymin = rect->ymax = BLI_RCT_CENTER_Y(rect);
rect->xmin -= x * 0.5f;
rect->ymin -= y * 0.5f;
rect->xmax = rect->xmin + x;
@ -363,22 +363,30 @@ int BLI_rcti_isect(const rcti *src1, const rcti *src2, rcti *dest)
}
}
void BLI_rcti_rctf_copy(rcti *tar, const rctf *src)
void BLI_rcti_rctf_copy(rcti *dst, const rctf *src)
{
tar->xmin = floorf(src->xmin + 0.5f);
tar->xmax = floorf((src->xmax - src->xmin) + 0.5f);
tar->ymin = floorf(src->ymin + 0.5f);
tar->ymax = floorf((src->ymax - src->ymin) + 0.5f);
dst->xmin = floorf(src->xmin + 0.5f);
dst->xmax = dst->xmin + floorf(BLI_RCT_SIZE_X(src) + 0.5f);
dst->ymin = floorf(src->ymin + 0.5f);
dst->ymax = dst->ymin + floorf(BLI_RCT_SIZE_Y(src) + 0.5f);
}
void BLI_rctf_rcti_copy(rctf *dst, const rcti *src)
{
dst->xmin = src->xmin;
dst->xmax = src->xmax;
dst->ymin = src->ymin;
dst->ymax = src->ymax;
}
void print_rctf(const char *str, const rctf *rect)
{
printf("%s: xmin %.3f, xmax %.3f, ymin %.3f, ymax %.3f (%.3fx%.3f)\n", str,
rect->xmin, rect->xmax, rect->ymin, rect->ymax, rect->xmax - rect->xmin, rect->ymax - rect->ymin);
rect->xmin, rect->xmax, rect->ymin, rect->ymax, BLI_RCT_SIZE_X(rect), BLI_RCT_SIZE_Y(rect));
}
void print_rcti(const char *str, const rcti *rect)
{
printf("%s: xmin %d, xmax %d, ymin %d, ymax %d (%dx%d)\n", str,
rect->xmin, rect->xmax, rect->ymin, rect->ymax, rect->xmax - rect->xmin, rect->ymax - rect->ymin);
rect->xmin, rect->xmax, rect->ymin, rect->ymax, BLI_RCT_SIZE_X(rect), BLI_RCT_SIZE_Y(rect));
}

@ -78,22 +78,31 @@ char *BLI_strncpy(char *dst, const char *src, const size_t maxncpy)
return dst;
}
size_t BLI_snprintf(char *buffer, size_t count, const char *format, ...)
size_t BLI_vsnprintf(char *buffer, size_t count, const char *format, va_list arg)
{
size_t n;
va_list arg;
va_start(arg, format);
n = vsnprintf(buffer, count, format, arg);
if (n != -1 && n < count) {
buffer[n] = '\0';
}
else {
buffer[count - 1] = '\0';
}
return n;
}
size_t BLI_snprintf(char *buffer, size_t count, const char *format, ...)
{
size_t n;
va_list arg;
va_start(arg, format);
n = BLI_vsnprintf(buffer, count, format, arg);
va_end(arg);
return n;
}

@ -2618,7 +2618,7 @@ static void lib_link_armature(FileData *fd, Main *main)
}
}
static void direct_link_bones(FileData *fd, Bone* bone)
static void direct_link_bones(FileData *fd, Bone *bone)
{
Bone *child;
@ -2914,6 +2914,7 @@ static void lib_link_vfont(FileData *UNUSED(fd), Main *main)
static void direct_link_vfont(FileData *fd, VFont *vf)
{
vf->data = NULL;
vf->temp_pf = NULL;
vf->packedfile = direct_link_packedfile(fd, vf->packedfile);
}
@ -4786,6 +4787,16 @@ static void link_paint(FileData *fd, Scene *sce, Paint *p)
}
}
static void lib_link_sequence_modifiers(FileData *fd, Scene *scene, ListBase *lb)
{
SequenceModifierData *smd;
for (smd = lb->first; smd; smd = smd->next) {
if (smd->mask_id)
smd->mask_id = newlibadr_us(fd, scene->id.lib, smd->mask_id);
}
}
static void lib_link_scene(FileData *fd, Main *main)
{
Scene *sce;
@ -4871,6 +4882,8 @@ static void lib_link_scene(FileData *fd, Main *main)
}
}
seq->anim = NULL;
lib_link_sequence_modifiers(fd, sce, &seq->modifiers);
}
SEQ_END
@ -4931,6 +4944,29 @@ static void direct_link_paint(FileData *fd, Paint **paint)
(*paint)->num_input_samples = 1;
}
static void direct_link_sequence_modifiers(FileData *fd, ListBase *lb)
{
SequenceModifierData *smd;
link_list(fd, lb);
for (smd = lb->first; smd; smd = smd->next) {
if (smd->mask_sequence)
smd->mask_sequence = newdataadr(fd, smd->mask_sequence);
if (smd->type == seqModifierType_Curves) {
CurvesModifierData *cmd = (CurvesModifierData *) smd;
direct_link_curvemapping(fd, &cmd->curve_mapping);
}
else if (smd->type == seqModifierType_HueCorrect) {
HueCorrectModifierData *hcmd = (HueCorrectModifierData *) smd;
direct_link_curvemapping(fd, &hcmd->curve_mapping);
}
}
}
static void direct_link_scene(FileData *fd, Scene *sce)
{
Editing *ed;
@ -5044,6 +5080,8 @@ static void direct_link_scene(FileData *fd, Scene *sce)
// seq->strip->color_balance->gui = 0; // XXX - peter, is this relevant in 2.5?
}
}
direct_link_sequence_modifiers(fd, &seq->modifiers);
}
SEQ_END
@ -8076,10 +8114,17 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 14)) {
ParticleSettings *part;
bNodeTreeType *ntreetype = ntreeGetType(NTREE_COMPOSIT);
if (ntreetype && ntreetype->foreach_nodetree)
ntreetype->foreach_nodetree(main, NULL, do_version_ntree_keying_despill_balance);
/* keep compatibility for dupliobject particle size */
for (part=main->particle.first; part; part=part->id.next)
if (ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR))
if ((part->draw & PART_DRAW_ROTATE_OB) == 0)
part->draw |= PART_DRAW_NO_SCALE_OB;
}
if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 17)) {

@ -129,7 +129,7 @@ static void area_add_header_region(ScrArea *sa, ListBase *lb)
ar->v2d.flag = (V2D_PIXELOFS_X|V2D_PIXELOFS_Y);
}
static void sequencer_init_preview_region(ARegion* ar)
static void sequencer_init_preview_region(ARegion *ar)
{
// XXX a bit ugly still, copied from space_sequencer
/* NOTE: if you change values here, also change them in space_sequencer.c, sequencer_new */
@ -1787,7 +1787,7 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
SpaceLink *sl;
for (sl = sa->spacedata.first; sl; sl = sl->next) {
if (sl->spacetype == SPACE_VIEW3D) {
View3D* v3d = (View3D *)sl;
View3D *v3d = (View3D *)sl;
v3d->flag2 &= ~V3D_RENDER_OVERRIDE;
}
}
@ -2206,7 +2206,7 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
bActuator *act;
for (act = ob->actuators.first; act; act = act->next) {
if (act->type == ACT_STEERING) {
bSteeringActuator* stact = act->data;
bSteeringActuator *stact = act->data;
if (stact->facingaxis == 0) {
stact->facingaxis = 1;
}
@ -2435,7 +2435,7 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
tex->pd->falloff_curve->preset = CURVE_PRESET_LINE;
tex->pd->falloff_curve->cm->flag &= ~CUMA_EXTEND_EXTRAPOLATE;
curvemap_reset(tex->pd->falloff_curve->cm, &tex->pd->falloff_curve->clipr, tex->pd->falloff_curve->preset, CURVEMAP_SLOPE_POSITIVE);
curvemapping_changed(tex->pd->falloff_curve, 0);
curvemapping_changed(tex->pd->falloff_curve, FALSE);
}
}
}

@ -1141,7 +1141,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
}
if (main->versionfile <= 212) {
bSound* sound;
bSound *sound;
bProperty *prop;
Object *ob;
Mesh *me;
@ -1307,7 +1307,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
}
if (main->versionfile <= 224) {
bSound* sound;
bSound *sound;
Scene *sce;
Mesh *me;
bScreen *sc;

@ -647,15 +647,21 @@ static void write_animdata(WriteData *wd, AnimData *adt)
write_nladata(wd, &adt->nla_tracks);
}
static void write_curvemapping(WriteData *wd, CurveMapping *cumap)
static void write_curvemapping_curves(WriteData *wd, CurveMapping *cumap)
{
int a;
writestruct(wd, DATA, "CurveMapping", 1, cumap);
for (a=0; a<CM_TOT; a++)
for (a = 0; a < CM_TOT; a++)
writestruct(wd, DATA, "CurveMapPoint", cumap->cm[a].totpoint, cumap->cm[a].curve);
}
static void write_curvemapping(WriteData *wd, CurveMapping *cumap)
{
writestruct(wd, DATA, "CurveMapping", 1, cumap);
write_curvemapping_curves(wd, cumap);
}
static void write_node_socket(WriteData *wd, bNodeSocket *sock)
{
bNodeSocketType *stype= ntreeGetSocketType(sock->type);
@ -2087,6 +2093,32 @@ static void write_lamps(WriteData *wd, ListBase *idbase)
}
}
static void write_sequence_modifiers(WriteData *wd, ListBase *modbase)
{
SequenceModifierData *smd;
for (smd = modbase->first; smd; smd = smd->next) {
SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type);
if (smti) {
writestruct(wd, DATA, smti->struct_name, 1, smd);
if (smd->type == seqModifierType_Curves) {
CurvesModifierData *cmd = (CurvesModifierData *) smd;
write_curvemapping(wd, &cmd->curve_mapping);
}
else if (smd->type == seqModifierType_HueCorrect) {
HueCorrectModifierData *hcmd = (HueCorrectModifierData *) smd;
write_curvemapping(wd, &hcmd->curve_mapping);
}
}
else {
writestruct(wd, DATA, "SequenceModifierData", 1, smd);
}
}
}
static void write_scenes(WriteData *wd, ListBase *scebase)
{
@ -2195,6 +2227,8 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
strip->done = TRUE;
}
write_sequence_modifiers(wd, &seq->modifiers);
}
SEQ_END
@ -2504,7 +2538,7 @@ static void write_libraries(WriteData *wd, Main *main)
}
}
static void write_bone(WriteData *wd, Bone* bone)
static void write_bone(WriteData *wd, Bone *bone)
{
Bone* cbone;

@ -80,7 +80,14 @@ BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example)
CustomData_bmesh_set_default(&bm->vdata, &v->head.data);
if (example) {
int *keyi;
BM_elem_attrs_copy(bm, bm, example, v);
/* exception: don't copy the original shapekey index */
keyi = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_SHAPE_KEYINDEX);
if(keyi)
*keyi = ORIGINDEX_NONE;
}
BM_CHECK_ELEMENT(v);

@ -84,8 +84,8 @@ void BMO_error_clear(BMesh *bm);
(void)((!(a)) ? ( \
( \
fprintf(stderr, \
"BMESH_ASSERT failed: %s, %s(), %d at \'%s\'\n", \
__FILE__, __func__, __LINE__, STRINGIFY(a)), \
"BMESH_ASSERT failed: %s, %s(), %d at \'%s\'\n", \
__FILE__, __func__, __LINE__, STRINGIFY(a)), \
_BMESH_DUMMY_ABORT(), \
NULL)) : NULL)

Some files were not shown because too many files have changed in this diff Show More