Merge from 2.5 -r 21285:21515. Thanks Joshua!

This commit is contained in:
Arystanbek Dyussenov 2009-07-11 09:14:12 +00:00
commit 3ad64726ee
322 changed files with 30831 additions and 19510 deletions

@ -87,7 +87,7 @@ INCLUDE(CMake/macros.cmake)
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
#Platform specifics #Platform specifics
IF(UNIX) IF(UNIX AND NOT APPLE)
IF(WITH_OPENAL) IF(WITH_OPENAL)
FIND_PACKAGE(OpenAL) FIND_PACKAGE(OpenAL)
IF(OPENAL_FOUND) IF(OPENAL_FOUND)
@ -177,7 +177,7 @@ IF(UNIX)
SET(C_WARNINGS "-Wall -Wno-char-subscripts -Wpointer-arith -Wcast-align -Wnested-externs -Wdeclaration-after-statement") SET(C_WARNINGS "-Wall -Wno-char-subscripts -Wpointer-arith -Wcast-align -Wnested-externs -Wdeclaration-after-statement")
INCLUDE_DIRECTORIES(${JPEG_INCLUDE_DIR} ${PNG_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR} ) INCLUDE_DIRECTORIES(${JPEG_INCLUDE_DIR} ${PNG_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR} )
ENDIF(UNIX) ENDIF(UNIX AND NOT APPLE)
IF(WIN32) IF(WIN32)

@ -3,12 +3,16 @@ LIBDIR = "${LCGDIR}"
BF_PYTHON = LIBDIR + '/python' BF_PYTHON = LIBDIR + '/python'
BF_PYTHON_VERSION = '2.5' BF_PYTHON_VERSION = '2.5'
#BF_PYTHON_VERSION = '2.6'
WITH_BF_STATICPYTHON = False WITH_BF_STATICPYTHON = False
BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}' BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}'
BF_PYTHON_BINARY = 'python' BF_PYTHON_BINARY = 'python'
BF_PYTHON_LIB = 'python25' #BF_PYTHON_LIB = 'python25'
BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib/lib25_vs2005' #BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib/lib25_vs2005'
BF_PYTHON_LIB_STATIC = '${BF_PYTHON}/lib/lib25_vs2005/libpython25.a' #BF_PYTHON_LIB_STATIC = '${BF_PYTHON}/lib/lib25_vs2005/libpython25.a'
BF_PYTHON_LIB = 'python${BF_PYTHON_VERSION[0]}${BF_PYTHON_VERSION[2]}'
BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib'
BF_PYTHON_LIB_STATIC = '${BF_PYTHON}/lib/libpython${BF_PYTHON_VERSION[0]}${BF_PYTHON_VERSION[2]}.a'
WITH_BF_OPENAL = True WITH_BF_OPENAL = True
WITH_BF_STATICOPENAL = False WITH_BF_STATICOPENAL = False

@ -367,6 +367,17 @@ extern GHOST_TSuccess GHOST_SetCursorPosition(GHOST_SystemHandle systemhandle,
GHOST_TInt32 x, GHOST_TInt32 x,
GHOST_TInt32 y); GHOST_TInt32 y);
/**
* Grabs the cursor for a modal operation, to keep receiving
* events when the mouse is outside the window. X11 only, others
* do this automatically.
* @param windowhandle The handle to the window
* @param grab The new grab state of the cursor.
* @return Indication of success.
*/
extern GHOST_TSuccess GHOST_SetCursorGrab(GHOST_WindowHandle windowhandle,
int grab);
/*************************************************************************************** /***************************************************************************************
** Access to mouse button and keyboard states. ** Access to mouse button and keyboard states.
***************************************************************************************/ ***************************************************************************************/

@ -252,6 +252,14 @@ public:
* @return Indication of success. * @return Indication of success.
*/ */
virtual GHOST_TSuccess setCursorVisibility(bool visible) = 0; virtual GHOST_TSuccess setCursorVisibility(bool visible) = 0;
/**
* Grabs the cursor for a modal operation.
* @param grab The new grab state of the cursor.
* @return Indication of success.
*/
virtual GHOST_TSuccess setCursorGrab(bool grab) { return GHOST_kSuccess; };
}; };
#endif // _GHOST_IWINDOW_H_ #endif // _GHOST_IWINDOW_H_

@ -354,6 +354,14 @@ GHOST_TSuccess GHOST_SetCursorPosition(GHOST_SystemHandle systemhandle,
} }
GHOST_TSuccess GHOST_SetCursorGrab(GHOST_WindowHandle windowhandle,
int grab)
{
GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
return window->setCursorGrab(grab?true:false);
}
GHOST_TSuccess GHOST_GetModifierKeyState(GHOST_SystemHandle systemhandle, GHOST_TSuccess GHOST_GetModifierKeyState(GHOST_SystemHandle systemhandle,
GHOST_TModifierKeyMask mask, GHOST_TModifierKeyMask mask,

@ -550,11 +550,26 @@ GHOST_SystemX11::processEvent(XEvent *xe)
// We're not interested in the following things.(yet...) // We're not interested in the following things.(yet...)
case NoExpose : case NoExpose :
case GraphicsExpose : case GraphicsExpose :
break;
case EnterNotify: case EnterNotify:
case LeaveNotify: case LeaveNotify:
{
// XCrossingEvents pointer leave enter window. // XCrossingEvents pointer leave enter window.
// also do cursor move here, MotionNotify only
// happens when motion starts & ends inside window
XCrossingEvent &xce = xe->xcrossing;
g_event = new
GHOST_EventCursor(
getMilliSeconds(),
GHOST_kEventCursorMove,
window,
xce.x_root,
xce.y_root
);
break; break;
}
case MapNotify: case MapNotify:
/* /*
* From ICCCM: * From ICCCM:

@ -50,6 +50,7 @@ GHOST_Window::GHOST_Window(
: :
m_drawingContextType(type), m_drawingContextType(type),
m_cursorVisible(true), m_cursorVisible(true),
m_cursorGrabbed(true),
m_cursorShape(GHOST_kStandardCursorDefault), m_cursorShape(GHOST_kStandardCursorDefault),
m_stereoVisual(stereoVisual) m_stereoVisual(stereoVisual)
{ {
@ -93,6 +94,20 @@ GHOST_TSuccess GHOST_Window::setCursorVisibility(bool visible)
} }
} }
GHOST_TSuccess GHOST_Window::setCursorGrab(bool grab)
{
if(m_cursorGrabbed == grab)
return GHOST_kSuccess;
if (setWindowCursorGrab(grab)) {
m_cursorGrabbed = grab;
return GHOST_kSuccess;
}
else {
return GHOST_kFailure;
}
}
GHOST_TSuccess GHOST_Window::setCursorShape(GHOST_TStandardCursor cursorShape) GHOST_TSuccess GHOST_Window::setCursorShape(GHOST_TStandardCursor cursorShape)
{ {
if (setWindowCursorShape(cursorShape)) { if (setWindowCursorShape(cursorShape)) {

@ -166,6 +166,13 @@ public:
*/ */
virtual GHOST_TSuccess setCursorVisibility(bool visible); virtual GHOST_TSuccess setCursorVisibility(bool visible);
/**
* Sets the cursor grab.
* @param grab The new grab state of the cursor.
* @return Indication of success.
*/
virtual GHOST_TSuccess setCursorGrab(bool grab);
/** /**
* Returns the type of drawing context used in this window. * Returns the type of drawing context used in this window.
* @return The current type of drawing context. * @return The current type of drawing context.
@ -219,6 +226,12 @@ protected:
*/ */
virtual GHOST_TSuccess setWindowCursorVisibility(bool visible) = 0; virtual GHOST_TSuccess setWindowCursorVisibility(bool visible) = 0;
/**
* Sets the cursor grab on the window using
* native window system calls.
*/
virtual GHOST_TSuccess setWindowCursorGrab(bool grab) { return GHOST_kSuccess; };
/** /**
* Sets the cursor shape on the window using * Sets the cursor shape on the window using
* native window system calls. * native window system calls.
@ -243,6 +256,9 @@ protected:
/** The current visibility of the cursor */ /** The current visibility of the cursor */
bool m_cursorVisible; bool m_cursorVisible;
/** The current grabbed state of the cursor */
bool m_cursorGrabbed;
/** The current shape of the cursor */ /** The current shape of the cursor */
GHOST_TStandardCursor m_cursorShape; GHOST_TStandardCursor m_cursorShape;

@ -1271,6 +1271,21 @@ setWindowCursorVisibility(
GHOST_TSuccess GHOST_TSuccess
GHOST_WindowX11:: GHOST_WindowX11::
setWindowCursorGrab(
bool grab
){
if(grab)
XGrabPointer(m_display, m_window, True, ButtonPressMask| ButtonReleaseMask|PointerMotionMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
else
XUngrabPointer(m_display, CurrentTime);
XFlush(m_display);
return GHOST_kSuccess;
}
GHOST_TSuccess
GHOST_WindowX11::
setWindowCursorShape( setWindowCursorShape(
GHOST_TStandardCursor shape GHOST_TStandardCursor shape
){ ){

@ -249,6 +249,15 @@ protected:
bool visible bool visible
); );
/**
* Sets the cursor grab on the window using
* native window system calls.
*/
GHOST_TSuccess
setWindowCursorGrab(
bool grab
);
/** /**
* Sets the cursor shape on the window using * Sets the cursor shape on the window using
* native window system calls. * native window system calls.

@ -294,7 +294,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ED_editors", "editors\ED_ed
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RNA_makesrna", "makesrna\RNA_makesrna.vcproj", "{8C2BCCF8-4D9E-46D3-BABF-C1545A332CE6}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RNA_makesrna", "makesrna\RNA_makesrna.vcproj", "{8C2BCCF8-4D9E-46D3-BABF-C1545A332CE6}"
ProjectSection(ProjectDependencies) = postProject ProjectSection(ProjectDependencies) = postProject
{FB88301F-F725-401B-ACD7-D2ABBF333B71} = {FB88301F-F725-401B-ACD7-D2ABBF333B71}
{7495FE37-933A-4AC1-BB2A-B3FDB4DE4284} = {7495FE37-933A-4AC1-BB2A-B3FDB4DE4284} {7495FE37-933A-4AC1-BB2A-B3FDB4DE4284} = {7495FE37-933A-4AC1-BB2A-B3FDB4DE4284}
EndProjectSection EndProjectSection
EndProject EndProject

@ -181,14 +181,6 @@
RelativePath="..\..\..\source\blender\editors\include\BIF_glutil.h" RelativePath="..\..\..\source\blender\editors\include\BIF_glutil.h"
> >
</File> </File>
<File
RelativePath="..\..\..\source\blender\editors\include\BIF_retopo.h"
>
</File>
<File
RelativePath="..\..\..\source\blender\editors\include\BIF_transform.h"
>
</File>
<File <File
RelativePath="..\..\..\source\blender\editors\include\ED_anim_api.h" RelativePath="..\..\..\source\blender\editors\include\ED_anim_api.h"
> >
@ -261,6 +253,10 @@
RelativePath="..\..\..\source\blender\editors\include\ED_particle.h" RelativePath="..\..\..\source\blender\editors\include\ED_particle.h"
> >
</File> </File>
<File
RelativePath="..\..\..\source\blender\editors\include\ED_physics.h"
>
</File>
<File <File
RelativePath="..\..\..\source\blender\editors\include\ED_pointcache.h" RelativePath="..\..\..\source\blender\editors\include\ED_pointcache.h"
> >
@ -269,6 +265,10 @@
RelativePath="..\..\..\source\blender\editors\include\ED_previewrender.h" RelativePath="..\..\..\source\blender\editors\include\ED_previewrender.h"
> >
</File> </File>
<File
RelativePath="..\..\..\source\blender\editors\include\ED_retopo.h"
>
</File>
<File <File
RelativePath="..\..\..\source\blender\editors\include\ED_screen.h" RelativePath="..\..\..\source\blender\editors\include\ED_screen.h"
> >
@ -426,10 +426,6 @@
RelativePath="..\..\..\source\blender\editors\interface\interface_widgets.c" RelativePath="..\..\..\source\blender\editors\interface\interface_widgets.c"
> >
</File> </File>
<File
RelativePath="..\..\..\source\blender\editors\interface\keyval.c"
>
</File>
<File <File
RelativePath="..\..\..\source\blender\editors\interface\resources.c" RelativePath="..\..\..\source\blender\editors\interface\resources.c"
> >
@ -750,10 +746,6 @@
RelativePath="..\..\..\source\blender\editors\space_file\file_draw.c" RelativePath="..\..\..\source\blender\editors\space_file\file_draw.c"
> >
</File> </File>
<File
RelativePath="..\..\..\source\blender\editors\space_file\file_header.c"
>
</File>
<File <File
RelativePath="..\..\..\source\blender\editors\space_file\file_intern.h" RelativePath="..\..\..\source\blender\editors\space_file\file_intern.h"
> >
@ -1062,6 +1054,10 @@
RelativePath="..\..\..\source\blender\editors\object\object_ops.c" RelativePath="..\..\..\source\blender\editors\object\object_ops.c"
> >
</File> </File>
<File
RelativePath="..\..\..\source\blender\editors\object\object_vgroup.c"
>
</File>
</Filter> </Filter>
<Filter <Filter
Name="transform" Name="transform"
@ -1118,10 +1114,6 @@
<Filter <Filter
Name="mesh" Name="mesh"
> >
<File
RelativePath="..\..\..\source\blender\editors\mesh\editdeform.c"
>
</File>
<File <File
RelativePath="..\..\..\source\blender\editors\mesh\editface.c" RelativePath="..\..\..\source\blender\editors\mesh\editface.c"
> >
@ -1154,6 +1146,10 @@
RelativePath="..\..\..\source\blender\editors\mesh\mesh_intern.h" RelativePath="..\..\..\source\blender\editors\mesh\mesh_intern.h"
> >
</File> </File>
<File
RelativePath="..\..\..\source\blender\editors\mesh\mesh_layers.c"
>
</File>
<File <File
RelativePath="..\..\..\source\blender\editors\mesh\mesh_ops.c" RelativePath="..\..\..\source\blender\editors\mesh\mesh_ops.c"
> >

@ -27,6 +27,7 @@
> >
<Tool <Tool
Name="VCPreBuildEventTool" Name="VCPreBuildEventTool"
CommandLine="DEL ..\..\..\source\blender\makesrna\intern\*_gen.c"
/> />
<Tool <Tool
Name="VCCustomBuildTool" Name="VCCustomBuildTool"
@ -121,6 +122,7 @@
> >
<Tool <Tool
Name="VCPreBuildEventTool" Name="VCPreBuildEventTool"
CommandLine="DEL ..\..\..\source\blender\makesrna\intern\*_gen.c"
/> />
<Tool <Tool
Name="VCCustomBuildTool" Name="VCCustomBuildTool"
@ -199,7 +201,7 @@
<Tool <Tool
Name="VCPostBuildEventTool" Name="VCPostBuildEventTool"
Description="Building RNA" Description="Building RNA"
CommandLine="CD ..\..\..\source\blender\makesrna\intern&#x0D;&#x0A;RNA_makesrna.exe rna.c&#x0D;&#x0A;" CommandLine="CD ..\..\..\source\blender\makesrna\intern\&#x0D;&#x0A;RNA_makesrna.exe .\&#x0D;&#x0A;"
/> />
</Configuration> </Configuration>
<Configuration <Configuration
@ -214,6 +216,7 @@
> >
<Tool <Tool
Name="VCPreBuildEventTool" Name="VCPreBuildEventTool"
CommandLine="DEL ..\..\..\source\blender\makesrna\intern\*_gen.c"
/> />
<Tool <Tool
Name="VCCustomBuildTool" Name="VCCustomBuildTool"
@ -307,6 +310,7 @@
> >
<Tool <Tool
Name="VCPreBuildEventTool" Name="VCPreBuildEventTool"
CommandLine="del ..\..\..\source\blender\makesrna\intern\rna_*_gen.c"
/> />
<Tool <Tool
Name="VCCustomBuildTool" Name="VCCustomBuildTool"
@ -388,7 +392,7 @@
<Tool <Tool
Name="VCPostBuildEventTool" Name="VCPostBuildEventTool"
Description="Building RNA" Description="Building RNA"
CommandLine="CD ..\..\..\source\blender\makesrna\intern&#x0D;&#x0A;RNA_makesrna.exe rna.c&#x0D;&#x0A;" CommandLine="CD ..\..\..\source\blender\makesrna\intern\&#x0D;&#x0A;RNA_makesrna.exe .\&#x0D;&#x0A;"
/> />
</Configuration> </Configuration>
<Configuration <Configuration
@ -403,6 +407,7 @@
> >
<Tool <Tool
Name="VCPreBuildEventTool" Name="VCPreBuildEventTool"
CommandLine="DEL ..\..\..\source\blender\makesrna\intern\*_gen.c"
/> />
<Tool <Tool
Name="VCCustomBuildTool" Name="VCCustomBuildTool"
@ -484,7 +489,7 @@
<Tool <Tool
Name="VCPostBuildEventTool" Name="VCPostBuildEventTool"
Description="Building RNA" Description="Building RNA"
CommandLine="CD ..\..\..\source\blender\makesrna\intern&#x0D;&#x0A;RNA_makesrna.exe rna.c&#x0D;&#x0A;" CommandLine="CD ..\..\..\source\blender\makesrna\intern\&#x0D;&#x0A;RNA_makesrna.exe .\&#x0D;&#x0A;"
/> />
</Configuration> </Configuration>
<Configuration <Configuration
@ -499,6 +504,7 @@
> >
<Tool <Tool
Name="VCPreBuildEventTool" Name="VCPreBuildEventTool"
CommandLine=""
/> />
<Tool <Tool
Name="VCCustomBuildTool" Name="VCCustomBuildTool"
@ -577,7 +583,7 @@
<Tool <Tool
Name="VCPostBuildEventTool" Name="VCPostBuildEventTool"
Description="Building RNA" Description="Building RNA"
CommandLine="CD ..\..\..\source\blender\makesrna\intern&#x0D;&#x0A;RNA_makesrna.exe rna.c&#x0D;&#x0A;" CommandLine="CD ..\..\..\source\blender\makesrna\intern\&#x0D;&#x0A;RNA_makesrna.exe .\&#x0D;&#x0A;"
/> />
</Configuration> </Configuration>
</Configurations> </Configurations>

@ -166,210 +166,206 @@
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
> >
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_action_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_actuator_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_animation_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_armature_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.cRNA_blender_cpp.h"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_brush_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_camera_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_cloth_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_color_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_constraint_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_context_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_controller_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_curve_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_fcurve_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_fluidsim_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_group_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_ID_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_image_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_key_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_lamp_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_lattice_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_main_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_material_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_mesh_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_meta_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_modifier_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_nodetree_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_object_force_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_object_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_packedfile_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_particle_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_pose_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_property_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_rna_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_scene_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_screen_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_scriptlink_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_sensor_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_sequence_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_sound_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_space_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_text_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_texture_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_timeline_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_ui_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_userdef_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_vfont_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_vpaint_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_wm_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_world_gen.c"
>
</File>
<File <File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_access.c" RelativePath="..\..\..\source\blender\makesrna\intern\rna_access.c"
> >
</File> </File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_action_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_actuator_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_animation_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_armature_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_brush_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_camera_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_cloth_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_color_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_constraint_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_context_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_controller_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_curve_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_fcurve_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_fluidsim_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_group_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_ID_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_image_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_key_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_lamp_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_lattice_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_main_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_material_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_mesh_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_meta_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_modifier_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_nodetree_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_object_force_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_object_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_packedfile_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_particle_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_pose_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_property_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_rna_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_scene_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_screen_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_scriptlink_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_sensor_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_sequence_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_sound_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_space_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_text_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_texture_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_timeline_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_ui_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_userdef_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_vfont_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_vpaint_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_wm_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_world_gen.c"
>
</File>
</Filter> </Filter>
<Filter <Filter
Name="Header Files" Name="Header Files"

@ -45,11 +45,14 @@ will be exported as mesh data.
# ***** END GPL LICENCE BLOCK ***** # ***** END GPL LICENCE BLOCK *****
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------
# import math and other in functions that use them for the sake of fast Blender startup
# import math
import os # os.sep
import bpy import bpy
import os # os.sep
import Mathutils import Mathutils
# Returns a tuple - path,extension. # Returns a tuple - path,extension.
# 'hello.obj' > ('hello', '.obj') # 'hello.obj' > ('hello', '.obj')
def splitExt(path): def splitExt(path):
@ -300,6 +303,9 @@ def write(filename, objects, scene,
write( 'c:\\test\\foobar.obj', Blender.Object.GetSelected() ) # Using default options. write( 'c:\\test\\foobar.obj', Blender.Object.GetSelected() ) # Using default options.
''' '''
# XXX
import math
def veckey3d(v): def veckey3d(v):
return round(v.x, 6), round(v.y, 6), round(v.z, 6) return round(v.x, 6), round(v.y, 6), round(v.z, 6)
@ -362,7 +368,7 @@ def write(filename, objects, scene,
file.write('mtllib %s\n' % ( mtlfilename.split('\\')[-1].split('/')[-1] )) file.write('mtllib %s\n' % ( mtlfilename.split('\\')[-1].split('/')[-1] ))
if EXPORT_ROTX90: if EXPORT_ROTX90:
mat_xrot90= Mathutils.RotationMatrix(-90, 4, 'x') mat_xrot90= Mathutils.RotationMatrix(-math.pi/2, 4, 'x')
# Initialize totals, these are updated each object # Initialize totals, these are updated each object
totverts = totuvco = totno = 1 totverts = totuvco = totno = 1
@ -416,8 +422,10 @@ def write(filename, objects, scene,
me = ob.data.create_copy() me = ob.data.create_copy()
if EXPORT_ROTX90: if EXPORT_ROTX90:
print(ob_mat * mat_xrot90)
me.transform(ob_mat * mat_xrot90) me.transform(ob_mat * mat_xrot90)
else: else:
print(ob_mat)
me.transform(ob_mat) me.transform(ob_mat)
# # Will work for non meshes now! :) # # Will work for non meshes now! :)

@ -9,12 +9,9 @@ class DataButtonsPanel(bpy.types.Panel):
def poll(self, context): def poll(self, context):
return (context.armature != None) return (context.armature != None)
class DATA_PT_skeleton(DataButtonsPanel): class DATA_PT_context_arm(DataButtonsPanel):
__idname__ = "DATA_PT_skeleton" __idname__ = "DATA_PT_context_arm"
__label__ = "Skeleton" __no_header__ = True
def poll(self, context):
return (context.object.type == 'ARMATURE' or context.armature)
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout
@ -32,8 +29,19 @@ class DATA_PT_skeleton(DataButtonsPanel):
split.template_ID(space, "pin_id") split.template_ID(space, "pin_id")
split.itemS() split.itemS()
class DATA_PT_skeleton(DataButtonsPanel):
__idname__ = "DATA_PT_skeleton"
__label__ = "Skeleton"
def draw(self, context):
layout = self.layout
ob = context.object
arm = context.armature
space = context.space_data
if arm: if arm:
layout.itemS()
layout.itemR(arm, "rest_position") layout.itemR(arm, "rest_position")
split = layout.split() split = layout.split()
@ -124,6 +132,7 @@ class DATA_PT_ghost(DataButtonsPanel):
sub = split.column() sub = split.column()
sub.itemR(arm, "ghost_only_selected", text="Selected Only") sub.itemR(arm, "ghost_only_selected", text="Selected Only")
bpy.types.register(DATA_PT_context_arm)
bpy.types.register(DATA_PT_skeleton) bpy.types.register(DATA_PT_skeleton)
bpy.types.register(DATA_PT_display) bpy.types.register(DATA_PT_display)
bpy.types.register(DATA_PT_paths) bpy.types.register(DATA_PT_paths)

@ -9,10 +9,25 @@ class BoneButtonsPanel(bpy.types.Panel):
def poll(self, context): def poll(self, context):
return (context.bone or context.edit_bone) return (context.bone or context.edit_bone)
class BONE_PT_context_bone(BoneButtonsPanel):
__idname__ = "BONE_PT_context_bone"
__no_header__ = True
def draw(self, context):
layout = self.layout
bone = context.bone
if not bone:
bone = context.edit_bone
split = layout.split(percentage=0.06)
split.itemL(text="", icon="ICON_BONE_DATA")
split.itemR(bone, "name", text="")
class BONE_PT_bone(BoneButtonsPanel): class BONE_PT_bone(BoneButtonsPanel):
__idname__ = "BONE_PT_bone" __idname__ = "BONE_PT_bone"
__label__ = "Bone" __label__ = "Bone"
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout
bone = context.bone bone = context.bone
@ -22,28 +37,53 @@ class BONE_PT_bone(BoneButtonsPanel):
split = layout.split() split = layout.split()
sub = split.column() sub = split.column()
sub.itemR(bone, "name")
sub.itemR(bone, "parent") sub.itemR(bone, "parent")
sub.itemR(bone, "connected") sub.itemR(bone, "connected")
sub.itemR(bone, "deform")
sub.itemL(text="Inherit:")
sub.itemR(bone, "hinge")
sub.itemR(bone, "inherit_scale")
sub.itemL(text="Envelope:")
sub.itemR(bone, "envelope_distance", text="Distance")
sub.itemR(bone, "envelope_weight", text="Weight")
sub.itemR(bone, "multiply_vertexgroup_with_envelope", text="Multiply")
sub = split.column()
sub.itemL(text="Layers:") sub.itemL(text="Layers:")
sub.template_layers(bone, "layer") sub.template_layers(bone, "layer")
sub = split.column()
sub.itemL(text="Inherit:")
sub.itemR(bone, "hinge", text="Rotation")
sub.itemR(bone, "inherit_scale", text="Scale")
sub.itemL(text="Display:") sub.itemL(text="Display:")
sub.itemR(bone, "draw_wire", text="Wireframe") sub.itemR(bone, "draw_wire", text="Wireframe")
sub.itemR(bone, "hidden", text="Hide") sub.itemR(bone, "hidden", text="Hide")
class BONE_PT_deform(BoneButtonsPanel):
__idname__ = "BONE_PT_deform"
__label__ = "Deform"
def draw_header(self, context):
layout = self.layout
bone = context.bone
if not bone:
bone = context.edit_bone
layout.itemR(bone, "deform", text="")
def draw(self, context):
layout = self.layout
bone = context.bone
if not bone:
bone = context.edit_bone
layout.active = bone.deform
split = layout.split()
sub = split.column()
sub.itemL(text="Envelope:")
sub.itemR(bone, "envelope_distance", text="Distance")
sub.itemR(bone, "envelope_weight", text="Weight")
sub.itemR(bone, "multiply_vertexgroup_with_envelope", text="Multiply")
sub = split.column()
sub.itemL(text="Curved Bones:") sub.itemL(text="Curved Bones:")
sub.itemR(bone, "bbone_segments", text="Segments") sub.itemR(bone, "bbone_segments", text="Segments")
sub.itemR(bone, "bbone_in", text="Ease In") sub.itemR(bone, "bbone_in", text="Ease In")
@ -51,4 +91,7 @@ class BONE_PT_bone(BoneButtonsPanel):
sub.itemR(bone, "cyclic_offset") sub.itemR(bone, "cyclic_offset")
bpy.types.register(BONE_PT_context_bone)
bpy.types.register(BONE_PT_bone) bpy.types.register(BONE_PT_bone)
bpy.types.register(BONE_PT_deform)

@ -9,12 +9,9 @@ class DataButtonsPanel(bpy.types.Panel):
def poll(self, context): def poll(self, context):
return (context.camera != None) return (context.camera != None)
class DATA_PT_camera(DataButtonsPanel): class DATA_PT_context_camera(DataButtonsPanel):
__idname__ = "DATA_PT_camera" __idname__ = "DATA_PT_context_camera"
__label__ = "Lens" __no_header__ = True
def poll(self, context):
return (context.object.type == 'CAMERA')
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout
@ -28,40 +25,48 @@ class DATA_PT_camera(DataButtonsPanel):
if ob: if ob:
split.template_ID(ob, "data") split.template_ID(ob, "data")
split.itemS() split.itemS()
elif arm: elif cam:
split.template_ID(space, "pin_id") split.template_ID(space, "pin_id")
split.itemS() split.itemS()
if cam: class DATA_PT_camera(DataButtonsPanel):
layout.itemS() __idname__ = "DATA_PT_camera"
layout.itemR(cam, "type", expand=True) __label__ = "Lens"
row = layout.row(align=True) def draw(self, context):
if cam.type == 'PERSP': layout = self.layout
row.itemR(cam, "lens_unit", text="")
if cam.lens_unit == 'MILLIMETERS':
row.itemR(cam, "lens", text="Angle")
elif cam.lens_unit == 'DEGREES':
row.itemR(cam, "angle")
elif cam.type == 'ORTHO': cam = context.camera
row.itemR(cam, "ortho_scale")
split = layout.split() layout.itemS()
layout.itemR(cam, "type", expand=True)
sub = split.column(align=True) row = layout.row(align=True)
sub.itemL(text="Shift:") if cam.type == 'PERSP':
sub.itemR(cam, "shift_x", text="X") row.itemR(cam, "lens_unit", text="")
sub.itemR(cam, "shift_y", text="Y") if cam.lens_unit == 'MILLIMETERS':
row.itemR(cam, "lens", text="Angle")
elif cam.lens_unit == 'DEGREES':
row.itemR(cam, "angle")
sub = split.column(align=True) elif cam.type == 'ORTHO':
sub.itemL(text="Clipping:") row.itemR(cam, "ortho_scale")
sub.itemR(cam, "clip_start", text="Start")
sub.itemR(cam, "clip_end", text="End")
row = layout.row() split = layout.split()
row.itemR(cam, "dof_object")
row.itemR(cam, "dof_distance") sub = split.column(align=True)
sub.itemL(text="Shift:")
sub.itemR(cam, "shift_x", text="X")
sub.itemR(cam, "shift_y", text="Y")
sub = split.column(align=True)
sub.itemL(text="Clipping:")
sub.itemR(cam, "clip_start", text="Start")
sub.itemR(cam, "clip_end", text="End")
row = layout.row()
row.itemR(cam, "dof_object")
row.itemR(cam, "dof_distance")
class DATA_PT_camera_display(DataButtonsPanel): class DATA_PT_camera_display(DataButtonsPanel):
__idname__ = "DATA_PT_camera_display" __idname__ = "DATA_PT_camera_display"
@ -86,5 +91,7 @@ class DATA_PT_camera_display(DataButtonsPanel):
colsub.itemR(cam, "passepartout_alpha", text="Alpha", slider=True) colsub.itemR(cam, "passepartout_alpha", text="Alpha", slider=True)
col.itemR(cam, "draw_size", text="Size") col.itemR(cam, "draw_size", text="Size")
bpy.types.register(DATA_PT_context_camera)
bpy.types.register(DATA_PT_camera) bpy.types.register(DATA_PT_camera)
bpy.types.register(DATA_PT_camera_display) bpy.types.register(DATA_PT_camera_display)

@ -7,14 +7,11 @@ class DataButtonsPanel(bpy.types.Panel):
__context__ = "data" __context__ = "data"
def poll(self, context): def poll(self, context):
return (context.object.type == 'CURVE' and context.curve) return (context.object and context.object.type == 'CURVE' and context.curve)
class DATA_PT_shape_curve(DataButtonsPanel): class DATA_PT_context_curve(DataButtonsPanel):
__idname__ = "DATA_PT_shape_curve" __idname__ = "DATA_PT_context_curve"
__label__ = "Shape" __no_header__ = True
def poll(self, context):
return (context.object.type == 'CURVE')
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout
@ -32,8 +29,19 @@ class DATA_PT_shape_curve(DataButtonsPanel):
split.template_ID(space, "pin_id") split.template_ID(space, "pin_id")
split.itemS() split.itemS()
class DATA_PT_shape_curve(DataButtonsPanel):
__idname__ = "DATA_PT_shape_curve"
__label__ = "Shape"
def draw(self, context):
layout = self.layout
ob = context.object
curve = context.curve
space = context.space_data
if curve: if curve:
layout.itemS()
layout.itemR(curve, "curve_2d") layout.itemR(curve, "curve_2d")
split = layout.split() split = layout.split()
@ -46,7 +54,7 @@ class DATA_PT_shape_curve(DataButtonsPanel):
colsub.itemR(curve, "back") colsub.itemR(curve, "back")
col.itemL(text="Textures:") col.itemL(text="Textures:")
col.itemR(curve, "uv_orco") # col.itemR(curve, "uv_orco")
col.itemR(curve, "auto_texspace") col.itemR(curve, "auto_texspace")
sub = split.column() sub = split.column()
@ -56,14 +64,14 @@ class DATA_PT_shape_curve(DataButtonsPanel):
sub.itemR(curve, "render_resolution_u", text="Render U") sub.itemR(curve, "render_resolution_u", text="Render U")
sub.itemR(curve, "render_resolution_v", text="Render V") sub.itemR(curve, "render_resolution_v", text="Render V")
sub.itemL(text="Display:") # sub.itemL(text="Display:")
sub.itemL(text="HANDLES") # sub.itemL(text="HANDLES")
sub.itemL(text="NORMALS") # sub.itemL(text="NORMALS")
sub.itemR(curve, "vertex_normal_flip") # sub.itemR(curve, "vertex_normal_flip")
class DATA_PT_geometry(DataButtonsPanel): class DATA_PT_geometry_curve(DataButtonsPanel):
__idname__ = "DATA_PT_geometry" __idname__ = "DATA_PT_geometry_curve"
__label__ = "Geometry" __label__ = "Geometry "
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout
@ -75,13 +83,13 @@ class DATA_PT_geometry(DataButtonsPanel):
sub.itemL(text="Modification:") sub.itemL(text="Modification:")
sub.itemR(curve, "width") sub.itemR(curve, "width")
sub.itemR(curve, "extrude") sub.itemR(curve, "extrude")
sub.itemR(curve, "taper_object") sub.itemR(curve, "taper_object", icon="ICON_OUTLINER_OB_CURVE")
sub = split.column() sub = split.column()
sub.itemL(text="Bevel:") sub.itemL(text="Bevel:")
sub.itemR(curve, "bevel_depth", text="Depth") sub.itemR(curve, "bevel_depth", text="Depth")
sub.itemR(curve, "bevel_resolution", text="Resolution") sub.itemR(curve, "bevel_resolution", text="Resolution")
sub.itemR(curve, "bevel_object") sub.itemR(curve, "bevel_object", icon="ICON_OUTLINER_OB_CURVE")
class DATA_PT_pathanim(DataButtonsPanel): class DATA_PT_pathanim(DataButtonsPanel):
__idname__ = "DATA_PT_pathanim" __idname__ = "DATA_PT_pathanim"
@ -141,7 +149,9 @@ class DATA_PT_current_curve(DataButtonsPanel):
sub.itemR(currentcurve, "radius_interpolation", text="Tilt") sub.itemR(currentcurve, "radius_interpolation", text="Tilt")
sub.itemR(currentcurve, "smooth") sub.itemR(currentcurve, "smooth")
bpy.types.register(DATA_PT_context_curve)
bpy.types.register(DATA_PT_shape_curve) bpy.types.register(DATA_PT_shape_curve)
bpy.types.register(DATA_PT_geometry) bpy.types.register(DATA_PT_geometry_curve)
bpy.types.register(DATA_PT_pathanim) bpy.types.register(DATA_PT_pathanim)
bpy.types.register(DATA_PT_current_curve) bpy.types.register(DATA_PT_current_curve)

@ -19,12 +19,9 @@ class DATA_PT_preview(DataButtonsPanel):
lamp = context.lamp lamp = context.lamp
layout.template_preview(lamp) layout.template_preview(lamp)
class DATA_PT_lamp(DataButtonsPanel): class DATA_PT_context_lamp(DataButtonsPanel):
__idname__ = "DATA_PT_lamp" __idname__ = "DATA_PT_context_lamp"
__label__ = "Lamp" __no_header__ = True
def poll(self, context):
return (context.object.type == 'LAMP')
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout
@ -42,9 +39,16 @@ class DATA_PT_lamp(DataButtonsPanel):
split.template_ID(space, "pin_id") split.template_ID(space, "pin_id")
split.itemS() split.itemS()
layout.itemS() class DATA_PT_lamp(DataButtonsPanel):
__idname__ = "DATA_PT_lamp"
__label__ = "Lamp"
layout.itemR(lamp, "type", expand=True) def draw(self, context):
layout = self.layout
lamp = context.lamp
layout.itemR(lamp, "type")
split = layout.split() split = layout.split()
@ -244,9 +248,11 @@ class DATA_PT_falloff_curve(DataButtonsPanel):
layout.template_curve_mapping(lamp.falloff_curve) layout.template_curve_mapping(lamp.falloff_curve)
bpy.types.register(DATA_PT_context_lamp)
bpy.types.register(DATA_PT_preview) bpy.types.register(DATA_PT_preview)
bpy.types.register(DATA_PT_lamp) bpy.types.register(DATA_PT_lamp)
bpy.types.register(DATA_PT_shadow) bpy.types.register(DATA_PT_shadow)
bpy.types.register(DATA_PT_sunsky) bpy.types.register(DATA_PT_sunsky)
bpy.types.register(DATA_PT_spot) bpy.types.register(DATA_PT_spot)
bpy.types.register(DATA_PT_falloff_curve) bpy.types.register(DATA_PT_falloff_curve)

@ -9,12 +9,9 @@ class DataButtonsPanel(bpy.types.Panel):
def poll(self, context): def poll(self, context):
return (context.lattice != None) return (context.lattice != None)
class DATA_PT_lattice(DataButtonsPanel): class DATA_PT_context_lattice(DataButtonsPanel):
__idname__ = "DATA_PT_lattice" __idname__ = "DATA_PT_context_lattice"
__label__ = "Lattice" __no_header__ = True
def poll(self, context):
return (context.object.type == 'LATTICE')
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout
@ -32,23 +29,32 @@ class DATA_PT_lattice(DataButtonsPanel):
split.template_ID(space, "pin_id") split.template_ID(space, "pin_id")
split.itemS() split.itemS()
if lat:
layout.itemS()
row = layout.row() class DATA_PT_lattice(DataButtonsPanel):
row.itemR(lat, "points_u") __idname__ = "DATA_PT_lattice"
row.itemR(lat, "interpolation_type_u", expand=True) __label__ = "Lattice"
row = layout.row() def draw(self, context):
row.itemR(lat, "points_v") layout = self.layout
row.itemR(lat, "interpolation_type_v", expand=True)
row = layout.row() lat = context.lattice
row.itemR(lat, "points_w")
row.itemR(lat, "interpolation_type_w", expand=True)
row = layout.row() row = layout.row()
row.itemR(lat, "outside") row.itemR(lat, "points_u")
row.itemR(lat, "shape_keys") row.itemR(lat, "interpolation_type_u", expand=True)
row = layout.row()
row.itemR(lat, "points_v")
row.itemR(lat, "interpolation_type_v", expand=True)
row = layout.row()
row.itemR(lat, "points_w")
row.itemR(lat, "interpolation_type_w", expand=True)
row = layout.row()
row.itemO("LATTICE_OT_make_regular")
row.itemR(lat, "outside")
bpy.types.register(DATA_PT_context_lattice)
bpy.types.register(DATA_PT_lattice) bpy.types.register(DATA_PT_lattice)

@ -9,12 +9,9 @@ class DataButtonsPanel(bpy.types.Panel):
def poll(self, context): def poll(self, context):
return (context.mesh != None) return (context.mesh != None)
class DATA_PT_mesh(DataButtonsPanel): class DATA_PT_context_mesh(DataButtonsPanel):
__idname__ = "DATA_PT_mesh" __idname__ = "DATA_PT_context_mesh"
__label__ = "Mesh" __no_header__ = True
def poll(self, context):
return (context.object and context.object.type == 'MESH')
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout
@ -32,22 +29,28 @@ class DATA_PT_mesh(DataButtonsPanel):
split.template_ID(space, "pin_id") split.template_ID(space, "pin_id")
split.itemS() split.itemS()
if mesh: class DATA_PT_mesh(DataButtonsPanel):
layout.itemS() __idname__ = "DATA_PT_mesh"
__label__ = "Mesh"
split = layout.split() def draw(self, context):
layout = self.layout
col = split.column() mesh = context.mesh
col.itemR(mesh, "autosmooth")
colsub = col.column()
colsub.active = mesh.autosmooth
colsub.itemR(mesh, "autosmooth_angle", text="Angle")
sub = split.column()
sub.itemR(mesh, "vertex_normal_flip")
sub.itemR(mesh, "double_sided")
layout.itemR(mesh, "texco_mesh") split = layout.split()
col = split.column()
col.itemR(mesh, "autosmooth")
colsub = col.column()
colsub.active = mesh.autosmooth
colsub.itemR(mesh, "autosmooth_angle", text="Angle")
sub = split.column()
sub.itemR(mesh, "vertex_normal_flip")
sub.itemR(mesh, "double_sided")
layout.itemS()
layout.itemR(mesh, "texco_mesh")
class DATA_PT_materials(DataButtonsPanel): class DATA_PT_materials(DataButtonsPanel):
__idname__ = "DATA_PT_materials" __idname__ = "DATA_PT_materials"
@ -62,30 +65,154 @@ class DATA_PT_materials(DataButtonsPanel):
row = layout.row() row = layout.row()
row.template_list(ob, "materials", "active_material_index") row.template_list(ob, "materials", ob, "active_material_index")
col = row.column(align=True) col = row.column(align=True)
col.itemO("OBJECT_OT_material_slot_add", icon="ICON_ZOOMIN", text="") col.itemO("OBJECT_OT_material_slot_add", icon="ICON_ZOOMIN", text="")
col.itemO("OBJECT_OT_material_slot_remove", icon="ICON_ZOOMOUT", text="") col.itemO("OBJECT_OT_material_slot_remove", icon="ICON_ZOOMOUT", text="")
row = layout.row(align=True) if context.edit_object:
row = layout.row(align=True)
row.itemO("OBJECT_OT_material_slot_assign", text="Assign"); row.itemO("OBJECT_OT_material_slot_assign", text="Assign")
row.itemO("OBJECT_OT_material_slot_select", text="Select"); row.itemO("OBJECT_OT_material_slot_select", text="Select")
row.itemO("OBJECT_OT_material_slot_deselect", text="Deselect"); row.itemO("OBJECT_OT_material_slot_deselect", text="Deselect")
"""
layout.itemS() layout.itemS()
box= layout.box() box= layout.box()
row = box.row() row = box.row()
row.template_list(ob, "materials", "active_material_index", compact=True) row.template_list(ob, "materials", ob, "active_material_index", compact=True)
subrow = row.row(align=True) subrow = row.row(align=True)
subrow.itemO("OBJECT_OT_material_slot_add", icon="ICON_ZOOMIN", text="") subrow.itemO("OBJECT_OT_material_slot_add", icon="ICON_ZOOMIN", text="")
subrow.itemO("OBJECT_OT_material_slot_remove", icon="ICON_ZOOMOUT", text="") subrow.itemO("OBJECT_OT_material_slot_remove", icon="ICON_ZOOMOUT", text="")
"""
class DATA_PT_vertex_groups(DataButtonsPanel):
__idname__ = "DATA_PT_vertex_groups"
__label__ = "Vertex Groups"
def poll(self, context):
return (context.object and context.object.type in ('MESH', 'LATTICE'))
def draw(self, context):
layout = self.layout
ob = context.object
row = layout.row()
row.template_list(ob, "vertex_groups", ob, "active_vertex_group_index")
col = row.column(align=True)
col.itemO("OBJECT_OT_vertex_group_add", icon="ICON_ZOOMIN", text="")
col.itemO("OBJECT_OT_vertex_group_remove", icon="ICON_ZOOMOUT", text="")
col.itemO("OBJECT_OT_vertex_group_copy", icon="ICON_BLANK1", text="")
if ob.data.users > 1:
col.itemO("OBJECT_OT_vertex_group_copy_to_linked", icon="ICON_BLANK1", text="")
if context.edit_object:
row = layout.row(align=True)
row.itemO("OBJECT_OT_vertex_group_assign", text="Assign")
row.itemO("OBJECT_OT_vertex_group_remove_from", text="Remove")
row.itemO("OBJECT_OT_vertex_group_select", text="Select")
row.itemO("OBJECT_OT_vertex_group_deselect", text="Deselect")
layout.itemR(context.tool_settings, "vertex_group_weight", text="Weight")
class DATA_PT_shape_keys(DataButtonsPanel):
__idname__ = "DATA_PT_shape_keys"
__label__ = "Shape Keys"
def poll(self, context):
return (context.object and context.object.type in ('MESH', 'LATTICE'))
def draw(self, context):
layout = self.layout
ob = context.object
key = ob.data.shape_keys
kb = ob.active_shape_key
row = layout.row()
row.template_list(key, "keys", ob, "active_shape_key_index")
col = row.column()
subcol = col.column(align=True)
subcol.itemO("OBJECT_OT_shape_key_add", icon="ICON_ZOOMIN", text="")
subcol.itemO("OBJECT_OT_shape_key_remove", icon="ICON_ZOOMOUT", text="")
if kb:
col.itemS()
subcol = col.column(align=True)
subcol.itemR(ob, "shape_key_lock", icon="ICON_PINNED", text="")
subcol.itemR(kb, "mute", icon="ICON_MUTE_IPO_ON", text="")
if key.relative:
row = layout.row()
row.itemR(key, "relative")
row.itemL()
if ob.active_shape_key_index != 0:
if not ob.shape_key_lock:
row = layout.row(align=True)
row.itemR(kb, "value", text="")
row.itemR(kb, "slider_min", text="Min")
row.itemR(kb, "slider_max", text="Max")
row = layout.row()
row.item_pointerR(kb, "vertex_group", ob, "vertex_groups", text="")
row.item_pointerR(kb, "relative_key", key, "keys", text="")
else:
row = layout.row()
row.itemR(key, "relative")
row.itemR(key, "slurph")
if context.edit_object:
layout.enabled = False
class DATA_PT_uv_texture(DataButtonsPanel):
__idname__ = "DATA_PT_uv_texture"
__label__ = "UV Texture"
def draw(self, context):
layout = self.layout
me = context.mesh
row = layout.row()
row.template_list(me, "uv_textures", me, "active_uv_texture_index")
col = row.column(align=True)
col.itemO("MESH_OT_uv_texture_add", icon="ICON_ZOOMIN", text="")
col.itemO("MESH_OT_uv_texture_remove", icon="ICON_ZOOMOUT", text="")
class DATA_PT_vertex_colors(DataButtonsPanel):
__idname__ = "DATA_PT_vertex_colors"
__label__ = "Vertex Colors"
def draw(self, context):
layout = self.layout
me = context.mesh
row = layout.row()
row.template_list(me, "vertex_colors", me, "active_vertex_color_index")
col = row.column(align=True)
col.itemO("MESH_OT_vertex_color_add", icon="ICON_ZOOMIN", text="")
col.itemO("MESH_OT_vertex_color_remove", icon="ICON_ZOOMOUT", text="")
bpy.types.register(DATA_PT_context_mesh)
bpy.types.register(DATA_PT_mesh) bpy.types.register(DATA_PT_mesh)
bpy.types.register(DATA_PT_materials) bpy.types.register(DATA_PT_materials)
bpy.types.register(DATA_PT_vertex_groups)
bpy.types.register(DATA_PT_shape_keys)
bpy.types.register(DATA_PT_uv_texture)
bpy.types.register(DATA_PT_vertex_colors)

@ -24,61 +24,63 @@ class DATA_PT_modifiers(DataButtonsPanel):
if box: if box:
if md.type == 'ARMATURE': if md.type == 'ARMATURE':
self.armature(box, ob, md) self.armature(box, ob, md)
if md.type == 'ARRAY': elif md.type == 'ARRAY':
self.array(box, ob, md) self.array(box, ob, md)
if md.type == 'BEVEL': elif md.type == 'BEVEL':
self.bevel(box, ob, md) self.bevel(box, ob, md)
if md.type == 'BOOLEAN': elif md.type == 'BOOLEAN':
self.boolean(box, ob, md) self.boolean(box, ob, md)
if md.type == 'BUILD': elif md.type == 'BUILD':
self.build(box, ob, md) self.build(box, ob, md)
if md.type == 'CAST': elif md.type == 'CAST':
self.cast(box, ob, md) self.cast(box, ob, md)
if md.type == 'CLOTH': elif md.type == 'CLOTH':
self.cloth(box, ob, md) self.cloth(box, ob, md)
if md.type == 'COLLISION': elif md.type == 'COLLISION':
self.collision(box, ob, md) self.collision(box, ob, md)
if md.type == 'CURVE': elif md.type == 'CURVE':
self.curve(box, ob, md) self.curve(box, ob, md)
if md.type == 'DECIMATE': elif md.type == 'DECIMATE':
self.decimate(box, ob, md) self.decimate(box, ob, md)
if md.type == 'DISPLACE': elif md.type == 'DISPLACE':
self.displace(box, ob, md) self.displace(box, ob, md)
if md.type == 'EDGE_SPLIT': elif md.type == 'EDGE_SPLIT':
self.edgesplit(box, ob, md) self.edgesplit(box, ob, md)
if md.type == 'EXPLODE': elif md.type == 'EXPLODE':
self.explode(box, ob, md) self.explode(box, ob, md)
if md.type == 'FLUID_SIMULATION': elif md.type == 'FLUID_SIMULATION':
self.fluid(box, ob, md) self.fluid(box, ob, md)
if md.type == 'HOOK': elif md.type == 'HOOK':
self.hook(box, ob, md) self.hook(box, ob, md)
if md.type == 'LATTICE': elif md.type == 'LATTICE':
self.lattice(box, ob, md) self.lattice(box, ob, md)
if md.type == 'MASK': elif md.type == 'MASK':
self.mask(box, ob, md) self.mask(box, ob, md)
if md.type == 'MESH_DEFORM': elif md.type == 'MESH_DEFORM':
self.mesh_deform(box, ob, md) self.mesh_deform(box, ob, md)
if md.type == 'MIRROR': elif md.type == 'MIRROR':
self.mirror(box, ob, md) self.mirror(box, ob, md)
if md.type == 'MULTIRES': elif md.type == 'MULTIRES':
self.multires(box, ob, md) self.multires(box, ob, md)
if md.type == 'PARTICLE_INSTANCE': elif md.type == 'PARTICLE_INSTANCE':
self.particleinstance(box, ob, md) self.particleinstance(box, ob, md)
if md.type == 'PARTICLE_SYSTEM': elif md.type == 'PARTICLE_SYSTEM':
self.particlesystem(box, ob, md) self.particlesystem(box, ob, md)
if md.type == 'SHRINKWRAP': elif md.type == 'SHRINKWRAP':
self.shrinkwrap(box, ob, md) self.shrinkwrap(box, ob, md)
if md.type == 'SIMPLE_DEFORM': elif md.type == 'SIMPLE_DEFORM':
self.simpledeform(box, ob, md) self.simpledeform(box, ob, md)
if md.type == 'SMOOTH': elif md.type == 'SMOOTH':
self.smooth(box, ob, md) self.smooth(box, ob, md)
if md.type == 'SOFTBODY': elif md.type == 'SOFTBODY':
self.softbody(box, ob, md) self.softbody(box, ob, md)
if md.type == 'SUBSURF': elif md.type == 'SUBSURF':
self.subsurf(box, ob, md) self.subsurf(box, ob, md)
if md.type == 'UV_PROJECT': elif md.type == 'SURFACE':
self.surface(box, ob, md)
elif md.type == 'UV_PROJECT':
self.uvproject(box, ob, md) self.uvproject(box, ob, md)
if md.type == 'WAVE': elif md.type == 'WAVE':
self.wave(box, ob, md) self.wave(box, ob, md)
def armature(self, layout, ob, md): def armature(self, layout, ob, md):
@ -96,9 +98,9 @@ class DATA_PT_modifiers(DataButtonsPanel):
layout.itemR(md, "fit_type") layout.itemR(md, "fit_type")
if md.fit_type == 'FIXED_COUNT': if md.fit_type == 'FIXED_COUNT':
layout.itemR(md, "count") layout.itemR(md, "count")
if md.fit_type == 'FIT_LENGTH': elif md.fit_type == 'FIT_LENGTH':
layout.itemR(md, "length") layout.itemR(md, "length")
if md.fit_type == 'FIT_CURVE': elif md.fit_type == 'FIT_CURVE':
layout.itemR(md, "curve") layout.itemR(md, "curve")
layout.itemS() layout.itemS()
@ -152,7 +154,7 @@ class DATA_PT_modifiers(DataButtonsPanel):
if md.limit_method == 'ANGLE': if md.limit_method == 'ANGLE':
row = layout.row() row = layout.row()
row.itemR(md, "angle") row.itemR(md, "angle")
if md.limit_method == 'WEIGHT': elif md.limit_method == 'WEIGHT':
row = layout.row() row = layout.row()
row.itemR(md, "edge_weight_method", expand=True) row.itemR(md, "edge_weight_method", expand=True)
@ -211,7 +213,7 @@ class DATA_PT_modifiers(DataButtonsPanel):
layout.itemR(md, "texture_coordinates") layout.itemR(md, "texture_coordinates")
if md.texture_coordinates == 'OBJECT': if md.texture_coordinates == 'OBJECT':
layout.itemR(md, "texture_coordinate_object", text="Object") layout.itemR(md, "texture_coordinate_object", text="Object")
if md.texture_coordinates == 'UV' and ob.type == 'MESH': elif md.texture_coordinates == 'UV' and ob.type == 'MESH':
layout.item_pointerR(md, "uv_layer", ob.data, "uv_layers") layout.item_pointerR(md, "uv_layer", ob.data, "uv_layers")
def edgesplit(self, layout, ob, md): def edgesplit(self, layout, ob, md):
@ -235,7 +237,7 @@ class DATA_PT_modifiers(DataButtonsPanel):
# Missing: "Refresh" and "Clear Vertex Group" ? # Missing: "Refresh" and "Clear Vertex Group" ?
def fluid(self, layout, ob, md): def fluid(self, layout, ob, md):
layout.itemL(text="See Fluidsim panel.") layout.itemL(text="See Fluid panel.")
def hook(self, layout, ob, md): def hook(self, layout, ob, md):
layout.itemR(md, "falloff") layout.itemR(md, "falloff")
@ -252,7 +254,7 @@ class DATA_PT_modifiers(DataButtonsPanel):
layout.itemR(md, "mode") layout.itemR(md, "mode")
if md.mode == 'ARMATURE': if md.mode == 'ARMATURE':
layout.itemR(md, "armature") layout.itemR(md, "armature")
if md.mode == 'VERTEX_GROUP': elif md.mode == 'VERTEX_GROUP':
layout.item_pointerR(md, "vertex_group", ob, "vertex_groups") layout.item_pointerR(md, "vertex_group", ob, "vertex_groups")
layout.itemR(md, "inverse") layout.itemR(md, "inverse")
@ -297,10 +299,21 @@ class DATA_PT_modifiers(DataButtonsPanel):
col = layout.column_flow() col = layout.column_flow()
col.itemR(md, "normal") col.itemR(md, "normal")
col.itemR(md, "children") col.itemR(md, "children")
col.itemR(md, "size")
col.itemR(md, "path") col.itemR(md, "path")
if md.path:
col.itemR(md, "keep_shape")
col.itemR(md, "unborn") col.itemR(md, "unborn")
col.itemR(md, "alive") col.itemR(md, "alive")
col.itemR(md, "dead") col.itemR(md, "dead")
col.itemL(md, "")
if md.path:
col.itemR(md, "axis", text="")
if md.path:
row = layout.row()
row.itemR(md, "position", slider=True)
row.itemR(md, "random_position", text = "Random", slider=True)
def particlesystem(self, layout, ob, md): def particlesystem(self, layout, ob, md):
layout.itemL(text="See Particle panel.") layout.itemL(text="See Particle panel.")
@ -325,7 +338,7 @@ class DATA_PT_modifiers(DataButtonsPanel):
col.itemR(md, "positive") col.itemR(md, "positive")
col.itemR(md, "cull_front_faces") col.itemR(md, "cull_front_faces")
col.itemR(md, "cull_back_faces") col.itemR(md, "cull_back_faces")
if md.mode == 'NEAREST_SURFACEPOINT': elif md.mode == 'NEAREST_SURFACEPOINT':
layout.itemR(md, "keep_above_surface") layout.itemR(md, "keep_above_surface")
# To-Do: Validate if structs # To-Do: Validate if structs
@ -350,10 +363,10 @@ class DATA_PT_modifiers(DataButtonsPanel):
sub.itemR(md, "factor") sub.itemR(md, "factor")
sub.itemR(md, "repeat") sub.itemR(md, "repeat")
layout.template_pointer(md, "vertex_group", ob, "vertex_groups") layout.item_pointerR(md, "vertex_group", ob, "vertex_groups")
def softbody(self, layout, ob, md): def softbody(self, layout, ob, md):
layout.itemL(text="See Softbody panel.") layout.itemL(text="See Soft Body panel.")
def subsurf(self, layout, ob, md): def subsurf(self, layout, ob, md):
layout.itemR(md, "subdivision_type") layout.itemR(md, "subdivision_type")
@ -363,6 +376,9 @@ class DATA_PT_modifiers(DataButtonsPanel):
col.itemR(md, "optimal_draw", text="Optimal Display") col.itemR(md, "optimal_draw", text="Optimal Display")
col.itemR(md, "subsurf_uv") col.itemR(md, "subsurf_uv")
def surface(self, layout, ob, md):
layout.itemL(text="See Fields panel.")
def uvproject(self, layout, ob, md): def uvproject(self, layout, ob, md):
if ob.type == 'MESH': if ob.type == 'MESH':
layout.item_pointerR(md, "uv_layer", ob.data, "uv_layers") layout.item_pointerR(md, "uv_layer", ob.data, "uv_layers")
@ -404,7 +420,7 @@ class DATA_PT_modifiers(DataButtonsPanel):
layout.itemR(md, "texture_coordinates") layout.itemR(md, "texture_coordinates")
if md.texture_coordinates == 'MAP_UV' and ob.type == 'MESH': if md.texture_coordinates == 'MAP_UV' and ob.type == 'MESH':
layout.item_pointerR(md, "uv_layer", ob.data, "uv_layers") layout.item_pointerR(md, "uv_layer", ob.data, "uv_layers")
if md.texture_coordinates == 'OBJECT': elif md.texture_coordinates == 'OBJECT':
layout.itemR(md, "texture_coordinates_object") layout.itemR(md, "texture_coordinates_object")
col = layout.column_flow() col = layout.column_flow()

@ -7,15 +7,11 @@ class DataButtonsPanel(bpy.types.Panel):
__context__ = "data" __context__ = "data"
def poll(self, context): def poll(self, context):
return (context.object.type == 'TEXT' and context.curve) return (context.object and context.object.type == 'TEXT' and context.curve)
class DATA_PT_shape_text(DataButtonsPanel): class DATA_PT_context_text(DataButtonsPanel):
__idname__ = "DATA_PT_shape_text" __idname__ = "DATA_PT_context_text"
__label__ = "Shape Text" __no_header__ = True
def poll(self, context):
ob = context.object
return (context.object.type == 'TEXT')
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout
@ -33,8 +29,18 @@ class DATA_PT_shape_text(DataButtonsPanel):
split.template_ID(space, "pin_id") split.template_ID(space, "pin_id")
split.itemS() split.itemS()
class DATA_PT_shape_text(DataButtonsPanel):
__idname__ = "DATA_PT_shape_text"
__label__ = "Shape Text"
def draw(self, context):
layout = self.layout
ob = context.object
curve = context.curve
space = context.space_data
if curve: if curve:
layout.itemS()
layout.itemR(curve, "curve_2d") layout.itemR(curve, "curve_2d")
split = layout.split() split = layout.split()
@ -58,6 +64,28 @@ class DATA_PT_shape_text(DataButtonsPanel):
sub.itemL(text="Display:") sub.itemL(text="Display:")
sub.itemR(curve, "fast") sub.itemR(curve, "fast")
class DATA_PT_geometry_text(DataButtonsPanel):
__idname__ = "DATA_PT_geometry_text"
__label__ = "Geometry"
def draw(self, context):
layout = self.layout
curve = context.curve
split = layout.split()
sub = split.column()
sub.itemL(text="Modification:")
sub.itemR(curve, "width")
sub.itemR(curve, "extrude")
sub.itemR(curve, "taper_object")
sub = split.column()
sub.itemL(text="Bevel:")
sub.itemR(curve, "bevel_depth", text="Depth")
sub.itemR(curve, "bevel_resolution", text="Resolution")
sub.itemR(curve, "bevel_object")
class DATA_PT_font(DataButtonsPanel): class DATA_PT_font(DataButtonsPanel):
__idname__ = "DATA_PT_font" __idname__ = "DATA_PT_font"
__label__ = "Font" __label__ = "Font"
@ -112,7 +140,7 @@ class DATA_PT_paragraph(DataButtonsPanel):
sub.itemL(text="Offset:") sub.itemL(text="Offset:")
sub.itemR(text, "x_offset", text="X") sub.itemR(text, "x_offset", text="X")
sub.itemR(text, "y_offset", text="Y") sub.itemR(text, "y_offset", text="Y")
sub.itemR(text, "wrap") #sub.itemR(text, "wrap")
""" """
class DATA_PT_textboxes(DataButtonsPanel): class DATA_PT_textboxes(DataButtonsPanel):
@ -124,7 +152,10 @@ class DATA_PT_textboxes(DataButtonsPanel):
text = context.curve text = context.curve
""" """
bpy.types.register(DATA_PT_context_text)
bpy.types.register(DATA_PT_shape_text) bpy.types.register(DATA_PT_shape_text)
bpy.types.register(DATA_PT_geometry_text)
bpy.types.register(DATA_PT_font) bpy.types.register(DATA_PT_font)
bpy.types.register(DATA_PT_paragraph) bpy.types.register(DATA_PT_paragraph)
#bpy.types.register(DATA_PT_textboxes) #bpy.types.register(DATA_PT_textboxes)

@ -19,12 +19,12 @@ class MATERIAL_PT_preview(MaterialButtonsPanel):
layout.template_preview(mat) layout.template_preview(mat)
class MATERIAL_PT_material(MaterialButtonsPanel): class MATERIAL_PT_context_material(MaterialButtonsPanel):
__idname__= "MATERIAL_PT_material" __idname__= "MATERIAL_PT_context_material"
__label__ = "Material" __no_header__ = True
def poll(self, context): def poll(self, context):
return (context.object != None) return (context.object)
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout
@ -34,18 +34,38 @@ class MATERIAL_PT_material(MaterialButtonsPanel):
slot = context.material_slot slot = context.material_slot
space = context.space_data space = context.space_data
if ob:
row = layout.row()
row.template_list(ob, "materials", ob, "active_material_index")
col = row.column(align=True)
col.itemO("OBJECT_OT_material_slot_add", icon="ICON_ZOOMIN", text="")
col.itemO("OBJECT_OT_material_slot_remove", icon="ICON_ZOOMOUT", text="")
split = layout.split(percentage=0.65) split = layout.split(percentage=0.65)
if ob and slot: if ob and slot:
split.template_ID(slot, "material", new="MATERIAL_OT_new") split.template_ID(slot, "material", new="MATERIAL_OT_new")
split.itemR(ob, "active_material_index", text="Active") #split.itemR(ob, "active_material_index", text="Active")
elif mat: elif mat:
split.template_ID(space, "pin_id") split.template_ID(space, "pin_id")
split.itemS() split.itemS()
if mat:
layout.itemS()
class MATERIAL_PT_material(MaterialButtonsPanel):
__idname__= "MATERIAL_PT_material"
__label__ = "Material"
def draw(self, context):
layout = self.layout
mat = context.material
ob = context.object
slot = context.material_slot
space = context.space_data
if mat:
layout.itemR(mat, "type", expand=True) layout.itemR(mat, "type", expand=True)
layout.itemR(mat, "alpha", slider=True) layout.itemR(mat, "alpha", slider=True)
@ -169,11 +189,9 @@ class MATERIAL_PT_diffuse(MaterialButtonsPanel):
split.active = mat.shadeless== False split.active = mat.shadeless== False
sub = split.column() sub = split.column()
if mat.diffuse_shader == 'OREN_NAYAR': if mat.diffuse_shader == 'OREN_NAYAR':
sub.itemR(mat, "roughness") sub.itemR(mat, "roughness")
sub = split.column()
if mat.diffuse_shader == 'MINNAERT': if mat.diffuse_shader == 'MINNAERT':
sub.itemR(mat, "darkness") sub.itemR(mat, "darkness")
sub = split.column()
if mat.diffuse_shader == 'TOON': if mat.diffuse_shader == 'TOON':
sub.itemR(mat, "diffuse_toon_size", text="Size") sub.itemR(mat, "diffuse_toon_size", text="Size")
sub = split.column() sub = split.column()
@ -213,13 +231,13 @@ class MATERIAL_PT_specular(MaterialButtonsPanel):
sub = split.column() sub = split.column()
if mat.spec_shader in ('COOKTORR', 'PHONG'): if mat.spec_shader in ('COOKTORR', 'PHONG'):
sub.itemR(mat, "specular_hardness", text="Hardness") sub.itemR(mat, "specular_hardness", text="Hardness")
sub = split.column()
if mat.spec_shader == 'BLINN': if mat.spec_shader == 'BLINN':
sub.itemR(mat, "specular_hardness", text="Hardness") sub.itemR(mat, "specular_hardness", text="Hardness")
sub = split.column() sub = split.column()
sub.itemR(mat, "specular_ior", text="IOR") sub.itemR(mat, "specular_ior", text="IOR")
if mat.spec_shader == 'WARDISO': if mat.spec_shader == 'WARDISO':
sub.itemR(mat, "specular_slope", text="Slope") sub.itemR(mat, "specular_slope", text="Slope")
sub = split.column()
sub.itemR(mat, "specular_hardness", text="Hardness") sub.itemR(mat, "specular_hardness", text="Hardness")
if mat.spec_shader == 'TOON': if mat.spec_shader == 'TOON':
sub.itemR(mat, "specular_toon_size", text="Size") sub.itemR(mat, "specular_toon_size", text="Size")
@ -410,6 +428,8 @@ class MATERIAL_PT_halo(MaterialButtonsPanel):
colsub.itemR(halo, "flare_seed", text="Seed") colsub.itemR(halo, "flare_seed", text="Seed")
colsub.itemR(halo, "flares_sub", text="Sub") colsub.itemR(halo, "flares_sub", text="Sub")
bpy.types.register(MATERIAL_PT_context_material)
bpy.types.register(MATERIAL_PT_preview) bpy.types.register(MATERIAL_PT_preview)
bpy.types.register(MATERIAL_PT_material) bpy.types.register(MATERIAL_PT_material)
bpy.types.register(MATERIAL_PT_diffuse) bpy.types.register(MATERIAL_PT_diffuse)

@ -6,6 +6,18 @@ class ObjectButtonsPanel(bpy.types.Panel):
__region_type__ = "WINDOW" __region_type__ = "WINDOW"
__context__ = "object" __context__ = "object"
class OBJECT_PT_context_object(ObjectButtonsPanel):
__idname__ = "OBJECT_PT_context_object"
__no_header__ = True
def draw(self, context):
layout = self.layout
ob = context.object
split = layout.split(percentage=0.06)
split.itemL(text="", icon="ICON_OBJECT_DATA")
split.itemR(ob, "name", text="")
class OBJECT_PT_transform(ObjectButtonsPanel): class OBJECT_PT_transform(ObjectButtonsPanel):
__idname__ = "OBJECT_PT_transform" __idname__ = "OBJECT_PT_transform"
__label__ = "Transform" __label__ = "Transform"
@ -124,6 +136,7 @@ class OBJECT_PT_animation(ObjectButtonsPanel):
sub.itemR(ob, "up_axis", text="Up Axis") sub.itemR(ob, "up_axis", text="Up Axis")
sub.itemR(ob, "track_rotation", text="Rotation") sub.itemR(ob, "track_rotation", text="Rotation")
bpy.types.register(OBJECT_PT_context_object)
bpy.types.register(OBJECT_PT_transform) bpy.types.register(OBJECT_PT_transform)
bpy.types.register(OBJECT_PT_groups) bpy.types.register(OBJECT_PT_groups)
bpy.types.register(OBJECT_PT_display) bpy.types.register(OBJECT_PT_display)

@ -7,48 +7,74 @@ class PhysicButtonsPanel(bpy.types.Panel):
__context__ = "physics" __context__ = "physics"
def poll(self, context): def poll(self, context):
return (context.cloth != None) ob = context.object
return (ob and ob.type == 'MESH')
class Physic_PT_cloth(PhysicButtonsPanel): class PHYSICS_PT_cloth(PhysicButtonsPanel):
__idname__ = "Physic_PT_cloth" __idname__ = "PHYSICS_PT_cloth"
__label__ = "Cloth" __label__ = "Cloth"
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout
cloth = context.cloth.settings md = context.cloth
ob = context.object
split = layout.split() split = layout.split()
split.operator_context = "EXEC_DEFAULT"
col = split.column() if md:
col.itemR(cloth, "quality", slider=True) # remove modifier + settings
col.itemR(cloth, "gravity") split.set_context_pointer("modifier", md)
col.itemR(cloth, "mass") split.itemO("OBJECT_OT_modifier_remove", text="Remove")
col.itemR(cloth, "mass_vertex_group", text="Vertex Group")
col = split.column() row = split.row(align=True)
col.itemL(text="Stiffness:") row.itemR(md, "render", text="")
col.itemR(cloth, "structural_stiffness", text="Structural") row.itemR(md, "realtime", text="")
col.itemR(cloth, "bending_stiffness", text="Bending") else:
col.itemL(text="Damping:") # add modifier
col.itemR(cloth, "spring_damping", text="Spring") split.item_enumO("OBJECT_OT_modifier_add", "type", "CLOTH", text="Add")
col.itemR(cloth, "air_damping", text="Air") split.itemL()
# Disabled for now if md:
""" cloth = md.settings
if cloth.mass_vertex_group:
layout.itemL(text="Goal:")
col = layout.column_flow() split = layout.split()
col.itemR(cloth, "goal_default", text="Default")
col.itemR(cloth, "goal_spring", text="Stiffness") col = split.column()
col.itemR(cloth, "goal_friction", text="Friction") col.itemR(cloth, "quality", slider=True)
""" col.itemR(cloth, "gravity")
subcol = col.column(align=True)
subcol.itemR(cloth, "mass")
subcol.item_pointerR(cloth, "mass_vertex_group", ob, "vertex_groups", text="")
col = split.column()
col.itemL(text="Stiffness:")
col.itemR(cloth, "structural_stiffness", text="Structural")
col.itemR(cloth, "bending_stiffness", text="Bending")
col.itemL(text="Damping:")
col.itemR(cloth, "spring_damping", text="Spring")
col.itemR(cloth, "air_damping", text="Air")
# Disabled for now
"""
if cloth.mass_vertex_group:
layout.itemL(text="Goal:")
col = layout.column_flow()
col.itemR(cloth, "goal_default", text="Default")
col.itemR(cloth, "goal_spring", text="Stiffness")
col.itemR(cloth, "goal_friction", text="Friction")
"""
class PHYSICS_PT_cloth_cache(PhysicButtonsPanel): class PHYSICS_PT_cloth_cache(PhysicButtonsPanel):
__idname__= "PHYSICS_PT_cloth_cache" __idname__= "PHYSICS_PT_cloth_cache"
__label__ = "Cache" __label__ = "Cloth Cache"
__default_closed__ = True __default_closed__ = True
def poll(self, context):
return (context.cloth != None)
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout
@ -91,19 +117,22 @@ class PHYSICS_PT_cloth_cache(PhysicButtonsPanel):
row.itemO("PTCACHE_OT_free_bake_all", text="Free All Bakes") row.itemO("PTCACHE_OT_free_bake_all", text="Free All Bakes")
layout.itemO("PTCACHE_OT_bake_all", text="Update All Dynamics to current frame") layout.itemO("PTCACHE_OT_bake_all", text="Update All Dynamics to current frame")
class Physic_PT_cloth_collision(PhysicButtonsPanel): class PHYSICS_PT_cloth_collision(PhysicButtonsPanel):
__idname__ = "Physic_PT_clothcollision" __idname__ = "PHYSICS_PT_clothcollision"
__label__ = "Cloth Collision" __label__ = "Cloth Collision"
def poll(self, context):
return (context.cloth != None)
def draw_header(self, context): def draw_header(self, context):
layout = self.layout layout = self.layout
cloth = context.cloth.settings cloth = context.cloth.collision_settings
layout.itemR(cloth, "enable_collision", text="") layout.itemR(cloth, "enable_collision", text="")
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout
cloth = context.cloth.settings cloth = context.cloth.collision_settings
layout.active = cloth.enable_collision layout.active = cloth.enable_collision
@ -120,10 +149,13 @@ class Physic_PT_cloth_collision(PhysicButtonsPanel):
col.itemR(cloth, "self_collision_quality", slider=True) col.itemR(cloth, "self_collision_quality", slider=True)
col.itemR(cloth, "self_min_distance", text="MinDistance") col.itemR(cloth, "self_min_distance", text="MinDistance")
class Physic_PT_cloth_stiffness(PhysicButtonsPanel): class PHYSICS_PT_cloth_stiffness(PhysicButtonsPanel):
__idname__ = "Physic_PT_stiffness" __idname__ = "PHYSICS_PT_stiffness"
__label__ = "Cloth Stiffness Scaling" __label__ = "Cloth Stiffness Scaling"
def poll(self, context):
return (context.cloth != None)
def draw_header(self, context): def draw_header(self, context):
layout = self.layout layout = self.layout
cloth = context.cloth.settings cloth = context.cloth.settings
@ -132,23 +164,25 @@ class Physic_PT_cloth_stiffness(PhysicButtonsPanel):
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout
ob = context.object
cloth = context.cloth.settings cloth = context.cloth.settings
layout.active = cloth.stiffness_scaling layout.active = cloth.stiffness_scaling
split = layout.split() split = layout.split()
sub = split.column() sub = split.column(align=True)
sub.itemL(text="Structural Stiffness:") sub.itemL(text="Structural Stiffness:")
sub.column().itemR(cloth, "structural_stiffness_vertex_group", text="VGroup") sub.item_pointerR(cloth, "structural_stiffness_vertex_group", ob, "vertex_groups", text="")
sub.itemR(cloth, "structural_stiffness_max", text="Max") sub.itemR(cloth, "structural_stiffness_max", text="Max")
sub = split.column() sub = split.column(align=True)
sub.itemL(text="Bending Stiffness:") sub.itemL(text="Bending Stiffness:")
sub.column().itemR(cloth, "bending_vertex_group", text="VGroup") sub.item_pointerR(cloth, "bending_vertex_group", ob, "vertex_groups", text="")
sub.itemR(cloth, "bending_stiffness_max", text="Max") sub.itemR(cloth, "bending_stiffness_max", text="Max")
bpy.types.register(Physic_PT_cloth) bpy.types.register(PHYSICS_PT_cloth)
bpy.types.register(PHYSICS_PT_cloth_cache) bpy.types.register(PHYSICS_PT_cloth_cache)
bpy.types.register(Physic_PT_cloth_collision) bpy.types.register(PHYSICS_PT_cloth_collision)
bpy.types.register(Physic_PT_cloth_stiffness) bpy.types.register(PHYSICS_PT_cloth_stiffness)

@ -0,0 +1,66 @@
import bpy
class PhysicButtonsPanel(bpy.types.Panel):
__space_type__ = "BUTTONS_WINDOW"
__region_type__ = "WINDOW"
__context__ = "physics"
def poll(self, context):
return (context.object != None)
class PHYSICS_PT_field(PhysicButtonsPanel):
__idname__ = "PHYSICS_PT_field"
__label__ = "Field"
def draw(self, context):
layout = self.layout
ob = context.object
field = ob.field
layout.itemR(field, "type")
if field.type != "NONE":
layout.itemR(field, "strength")
if field.type in ("HARMONIC", "SPHERICAL", "CHARGE", "LENNARDj"):
if ob.type in ("MESH", "SURFACE", "FONT", "CURVE"):
layout.itemR(field, "surface")
class PHYSICS_PT_collision(PhysicButtonsPanel):
__idname__ = "PHYSICS_PT_collision"
__label__ = "Collision"
__default_closed__ = True
def poll(self, context):
ob = context.object
return (ob and ob.type == 'MESH')
def draw_header(self, context):
settings = context.object.collision
self.layout.itemR(settings, "enabled", text="")
def draw(self, context):
layout = self.layout
md = context.collision
settings = context.object.collision
layout.active = settings.enabled
split = layout.split()
col = split.column()
col.itemL(text="Damping:")
col.itemR(settings, "damping_factor", text="Factor");
col.itemR(settings, "random_damping", text="Random");
col = split.column()
col.itemL(text="Friction:")
col.itemR(settings, "friction_factor", text="Factor");
col.itemR(settings, "random_friction", text="Random");
layout.itemR(settings, "permeability");
layout.itemR(settings, "kill_particles");
bpy.types.register(PHYSICS_PT_field)
bpy.types.register(PHYSICS_PT_collision)

@ -0,0 +1,223 @@
import bpy
class PhysicButtonsPanel(bpy.types.Panel):
__space_type__ = "BUTTONS_WINDOW"
__region_type__ = "WINDOW"
__context__ = "physics"
def poll(self, context):
ob = context.object
return (ob and ob.type == 'MESH')
class PHYSICS_PT_fluid(PhysicButtonsPanel):
__idname__ = "PHYSICS_PT_fluid"
__label__ = "Fluid"
def draw(self, context):
layout = self.layout
md = context.fluid
ob = context.object
split = layout.split()
split.operator_context = "EXEC_DEFAULT"
if md:
# remove modifier + settings
split.set_context_pointer("modifier", md)
split.itemO("OBJECT_OT_modifier_remove", text="Remove")
row = split.row(align=True)
row.itemR(md, "render", text="")
row.itemR(md, "realtime", text="")
else:
# add modifier
split.item_enumO("OBJECT_OT_modifier_add", "type", "FLUID_SIMULATION", text="Add")
split.itemL()
if md:
fluid = md.settings
col = layout.column(align=True)
row = col.row()
row.item_enumR(fluid, "type", "DOMAIN")
row.item_enumR(fluid, "type", "FLUID")
row.item_enumR(fluid, "type", "OBSTACLE")
row = col.row()
row.item_enumR(fluid, "type", "INFLOW")
row.item_enumR(fluid, "type", "OUTFLOW")
row.item_enumR(fluid, "type", "PARTICLE")
row.item_enumR(fluid, "type", "CONTROL")
if fluid.type == 'DOMAIN':
layout.itemO("FLUID_OT_bake", text="BAKE")
layout.itemL(text="Required Memory: " + fluid.memory_estimate)
layout.itemL(text="Resolution:")
split = layout.split()
col = split.column()
colsub = col.column(align=True)
colsub.itemR(fluid, "resolution", text="Final")
colsub.itemR(fluid, "render_display_mode", text="")
colsub = col.column(align=True)
colsub.itemL(text="Time:")
colsub.itemR(fluid, "start_time", text="Start")
colsub.itemR(fluid, "end_time", text="End")
col = split.column()
colsub = col.column(align=True)
colsub.itemR(fluid, "preview_resolution", text="Preview", slider=True)
colsub.itemR(fluid, "viewport_display_mode", text="")
colsub = col.column()
colsub.itemR(fluid, "reverse_frames")
colsub.itemR(fluid, "generate_speed_vectors")
colsub.itemR(fluid, "path", text="")
if fluid.type in ('FLUID', 'OBSTACLE', 'INFLOW', 'OUTFLOW'):
layout.itemR(fluid, "volume_initialization")
if fluid.type == 'FLUID':
row = layout.row()
row.column().itemR(fluid, "initial_velocity")
row.itemR(fluid, "export_animated_mesh")
if fluid.type == 'OBSTACLE':
row = layout.row()
row.itemL()
row.itemR(fluid, "export_animated_mesh")
layout.itemR(fluid, "slip_type", expand=True)
if fluid.slip_type == 'PARTIALSLIP':
layout.itemR(fluid, "partial_slip_amount", text="Amount")
layout.itemR(fluid, "impact_factor")
if fluid.type == 'INFLOW':
row = layout.row()
row.column().itemR(fluid, "inflow_velocity")
row.itemR(fluid, "export_animated_mesh")
layout.itemR(fluid, "local_coordinates")
if fluid.type == 'OUTFLOW':
row = layout.row()
row.itemL()
row.itemR(fluid, "export_animated_mesh")
if fluid.type == 'PARTICLE':
split = layout.split()
col = split.column()
col.itemL(text="Type:")
col.itemR(fluid, "drops")
col.itemR(fluid, "floats")
col.itemR(fluid, "tracer")
col = split.column()
col.itemL(text="Influence:")
col.itemR(fluid, "particle_influence", text="Particle")
col.itemR(fluid, "alpha_influence", text="Alpha")
layout.itemR(fluid, "path")
if fluid.type == 'CONTROL':
split = layout.split()
col = split.column()
col.itemL(text="Time:")
col.itemR(fluid, "start_time", text="Start")
col.itemR(fluid, "end_time", text="End")
col = split.column()
col.itemR(fluid, "quality", slider=True)
col.itemR(fluid, "reverse_frames")
split = layout.split()
col = split.column()
col.itemL(text="Attraction:")
col.itemR(fluid, "attraction_strength", text="Strength")
col.itemR(fluid, "attraction_radius", text="Radius")
col = split.column()
col.itemL(text="Velocity:")
col.itemR(fluid, "velocity_strength", text="Strength")
col.itemR(fluid, "velocity_radius", text="Radius")
class PHYSICS_PT_domain_gravity(PhysicButtonsPanel):
__idname__ = "PHYSICS_PT_domain_gravity"
__label__ = "Domain World/Gravity"
__default_closed__ = True
def poll(self, context):
md = context.fluid
if md:
return (md.settings.type == 'DOMAIN')
def draw(self, context):
layout = self.layout
fluid = context.fluid.settings
split = layout.split()
col = split.column()
col.itemR(fluid, "gravity")
col = split.column(align=True)
col.itemL(text="Viscosity:")
col.itemR(fluid, "viscosity_preset", text="")
if fluid.viscosity_preset == 'MANUAL':
col.itemR(fluid, "viscosity_base", text="Base")
col.itemR(fluid, "viscosity_exponent", text="Exponent")
col = layout.column_flow()
col.itemR(fluid, "real_world_size")
col.itemR(fluid, "grid_levels")
col.itemR(fluid, "compressibility")
class PHYSICS_PT_domain_boundary(PhysicButtonsPanel):
__idname__ = "PHYSICS_PT_domain_boundary"
__label__ = "Domain Boundary"
__default_closed__ = True
def poll(self, context):
md = context.fluid
if md:
return (md.settings.type == 'DOMAIN')
def draw(self, context):
layout = self.layout
fluid = context.fluid.settings
layout.itemL(text="Slip:")
layout.itemR(fluid, "slip_type", expand=True)
if fluid.slip_type == 'PARTIALSLIP':
layout.itemR(fluid, "partial_slip_amount", text="Amount")
layout.itemL(text="Surface:")
row = layout.row()
row.itemR(fluid, "surface_smoothing", text="Smoothing")
row.itemR(fluid, "surface_subdivisions", text="Subdivisions")
class PHYSICS_PT_domain_particles(PhysicButtonsPanel):
__idname__ = "PHYSICS_PT_domain_particles"
__label__ = "Domain Particles"
__default_closed__ = True
def poll(self, context):
md = context.fluid
if md:
return (md.settings.type == 'DOMAIN')
def draw(self, context):
layout = self.layout
fluid = context.fluid.settings
layout.itemR(fluid, "tracer_particles")
layout.itemR(fluid, "generate_particles")
bpy.types.register(PHYSICS_PT_fluid)
bpy.types.register(PHYSICS_PT_domain_gravity)
bpy.types.register(PHYSICS_PT_domain_boundary)
bpy.types.register(PHYSICS_PT_domain_particles)

@ -0,0 +1,219 @@
import bpy
class PhysicButtonsPanel(bpy.types.Panel):
__space_type__ = "BUTTONS_WINDOW"
__region_type__ = "WINDOW"
__context__ = "physics"
def poll(self, context):
ob = context.object
return (ob and ob.type == 'MESH')
class PHYSICS_PT_softbody(PhysicButtonsPanel):
__idname__ = "PHYSICS_PT_softbody"
__label__ = "Soft Body"
def draw(self, context):
layout = self.layout
md = context.soft_body
ob = context.object
split = layout.split()
split.operator_context = "EXEC_DEFAULT"
if md:
# remove modifier + settings
split.set_context_pointer("modifier", md)
split.itemO("OBJECT_OT_modifier_remove", text="Remove")
row = split.row(align=True)
row.itemR(md, "render", text="")
row.itemR(md, "realtime", text="")
else:
# add modifier
split.item_enumO("OBJECT_OT_modifier_add", "type", "SOFTBODY", text="Add")
split.itemL("")
if md:
softbody = md.settings
# General
split = layout.split()
col = split.column()
col.itemL(text="Object:")
col.itemR(softbody, "mass")
col.itemR(softbody, "friction")
col = split.column()
col.itemL(text="Simulation:")
col.itemR(softbody, "gravity")
col.itemR(softbody, "speed")
class PHYSICS_PT_softbody_goal(PhysicButtonsPanel):
__idname__ = "PHYSICS_PT_softbody_goal"
__label__ = "Soft Body Goal"
def poll(self, context):
return (context.soft_body != None)
def draw_header(self, context):
layout = self.layout
softbody = context.soft_body.settings
layout.itemR(softbody, "use_goal", text="")
def draw(self, context):
layout = self.layout
md = context.soft_body
ob = context.object
split = layout.split()
if md:
softbody = md.settings
layout.active = softbody.use_goal
# Goal
split = layout.split()
col = split.column()
col.itemL(text="Goal Strengths:")
col.itemR(softbody, "goal_default", text="Default")
subcol = col.column(align=True)
subcol.itemR(softbody, "goal_min", text="Minimum")
subcol.itemR(softbody, "goal_max", text="Maximum")
col = split.column()
col.itemL(text="Goal Settings:")
col.itemR(softbody, "goal_spring", text="Stiffness")
col.itemR(softbody, "goal_friction", text="Damping")
layout.item_pointerR(softbody, "goal_vertex_group", ob, "vertex_groups", text="Vertex Group")
class PHYSICS_PT_softbody_edge(PhysicButtonsPanel):
__idname__ = "PHYSICS_PT_softbody_edge"
__label__ = "Soft Body Edges"
def poll(self, context):
return (context.soft_body != None)
def draw_header(self, context):
layout = self.layout
softbody = context.soft_body.settings
layout.itemR(softbody, "use_edges", text="")
def draw(self, context):
layout = self.layout
md = context.soft_body
ob = context.object
split = layout.split()
if md:
softbody = md.settings
layout.active = softbody.use_edges
split = layout.split()
col = split.column()
col.itemL(text="Springs:")
col.itemR(softbody, "pull")
col.itemR(softbody, "push")
col.itemR(softbody, "damp")
col.itemR(softbody, "plastic")
col.itemR(softbody, "bending")
col.itemR(softbody, "spring_length", text="Length")
col = split.column()
col.itemR(softbody, "stiff_quads")
subcol = col.column()
subcol.active = softbody.stiff_quads
subcol.itemR(softbody, "shear")
col.itemR(softbody, "new_aero", text="Aero")
subcol = col.column()
subcol.active = softbody.new_aero
subcol.itemR(softbody, "aero", text="Factor", enabled=softbody.new_aero)
col.itemL(text="Collision:")
col.itemR(softbody, "edge_collision", text="Edge")
col.itemR(softbody, "face_collision", text="Face")
class PHYSICS_PT_softbody_collision(PhysicButtonsPanel):
__idname__ = "PHYSICS_PT_softbody_collision"
__label__ = "Soft Body Collision"
def poll(self, context):
return (context.soft_body != None)
def draw_header(self, context):
layout = self.layout
softbody = context.soft_body.settings
layout.itemR(softbody, "self_collision", text="")
def draw(self, context):
layout = self.layout
md = context.soft_body
ob = context.object
split = layout.split()
if md:
softbody = md.settings
layout.active = softbody.self_collision
layout.itemL(text="Collision Type:")
layout.itemR(softbody, "collision_type", expand=True)
col = layout.column(align=True)
col.itemL(text="Ball:")
col.itemR(softbody, "ball_size", text="Size")
col.itemR(softbody, "ball_stiff", text="Stiffness")
col.itemR(softbody, "ball_damp", text="Dampening")
class PHYSICS_PT_softbody_solver(PhysicButtonsPanel):
__idname__ = "PHYSICS_PT_softbody_solver"
__label__ = "Soft Body Solver"
def poll(self, context):
return (context.soft_body != None)
def draw(self, context):
layout = self.layout
md = context.soft_body
ob = context.object
split = layout.split()
if md:
softbody = md.settings
# Solver
split = layout.split()
col = split.column(align=True)
col.itemL(text="Step Size:")
col.itemR(softbody, "minstep")
col.itemR(softbody, "maxstep")
col.itemR(softbody, "auto_step", text="Auto-Step")
col = split.column()
col.itemR(softbody, "error_limit")
col.itemL(text="Helpers:")
col.itemR(softbody, "choke")
col.itemR(softbody, "fuzzy")
layout.itemL(text="Diagnostics:")
layout.itemR(softbody, "diagnose")
bpy.types.register(PHYSICS_PT_softbody)
bpy.types.register(PHYSICS_PT_softbody_goal)
bpy.types.register(PHYSICS_PT_softbody_edge)
bpy.types.register(PHYSICS_PT_softbody_collision)
bpy.types.register(PHYSICS_PT_softbody_solver)

@ -35,6 +35,8 @@ class RENDER_PT_output(RenderButtonsPanel):
layout = self.layout layout = self.layout
rd = context.scene.render_data rd = context.scene.render_data
layout.itemR(rd, "display_mode", text="Display")
layout.itemR(rd, "output_path") layout.itemR(rd, "output_path")
split = layout.split() split = layout.split()
@ -54,7 +56,6 @@ class RENDER_PT_output(RenderButtonsPanel):
col.itemR(rd, "placeholders") col.itemR(rd, "placeholders")
col.itemR(rd, "no_overwrite") col.itemR(rd, "no_overwrite")
layout.itemR(rd, "file_format", text="Format") layout.itemR(rd, "file_format", text="Format")
split = layout.split() split = layout.split()

@ -19,9 +19,9 @@ class TEXTURE_PT_preview(TextureButtonsPanel):
layout.template_preview(tex) layout.template_preview(tex)
class TEXTURE_PT_texture(TextureButtonsPanel): class TEXTURE_PT_context_texture(TextureButtonsPanel):
__idname__= "TEXTURE_PT_texture" __idname__= "TEXTURE_PT_context_texture"
__label__ = "Texture" __no_header__ = True
def poll(self, context): def poll(self, context):
return (context.material or context.world or context.lamp) return (context.material or context.world or context.lamp)
@ -36,6 +36,20 @@ class TEXTURE_PT_texture(TextureButtonsPanel):
space = context.space_data space = context.space_data
slot = context.texture_slot slot = context.texture_slot
if ma or la or wo:
row = layout.row()
if ma:
row.template_list(ma, "textures", ma, "active_texture_index")
elif la:
row.template_list(la, "textures", la, "active_texture_index")
elif wo:
row.template_list(wo, "textures", wo, "active_texture_index")
"""if ma or la or wo:
col = row.column(align=True)
col.itemO("TEXTURE_OT_new", icon="ICON_ZOOMIN", text="")
#col.itemO("OBJECT_OT_material_slot_remove", icon="ICON_ZOOMOUT", text="")
"""
split = layout.split(percentage=0.65) split = layout.split(percentage=0.65)
if ma or la or wo: if ma or la or wo:
@ -44,17 +58,11 @@ class TEXTURE_PT_texture(TextureButtonsPanel):
else: else:
split.itemS() split.itemS()
if ma:
split.itemR(ma, "active_texture_index", text="Active")
elif la:
split.itemR(la, "active_texture_index", text="Active")
elif wo:
split.itemR(wo, "active_texture_index", text="Active")
elif tex: elif tex:
split.template_ID(space, "pin_id") split.template_ID(space, "pin_id")
split.itemS() split.itemS()
layout.itemS() layout.itemS()
if tex: if tex:
split = layout.split(percentage=0.2) split = layout.split(percentage=0.2)
@ -508,8 +516,8 @@ class TEXTURE_PT_distortednoise(TextureButtonsPanel):
sub = split.column() sub = split.column()
sub.itemR(tex, "nabla") sub.itemR(tex, "nabla")
bpy.types.register(TEXTURE_PT_context_texture)
bpy.types.register(TEXTURE_PT_preview) bpy.types.register(TEXTURE_PT_preview)
bpy.types.register(TEXTURE_PT_texture)
bpy.types.register(TEXTURE_PT_clouds) bpy.types.register(TEXTURE_PT_clouds)
bpy.types.register(TEXTURE_PT_wood) bpy.types.register(TEXTURE_PT_wood)
bpy.types.register(TEXTURE_PT_marble) bpy.types.register(TEXTURE_PT_marble)

@ -18,8 +18,8 @@ class WORLD_PT_preview(WorldButtonsPanel):
layout.template_preview(world) layout.template_preview(world)
class WORLD_PT_world(WorldButtonsPanel): class WORLD_PT_context_world(WorldButtonsPanel):
__label__ = "World" __no_header__ = True
def poll(self, context): def poll(self, context):
return (context.scene != None) return (context.scene != None)
@ -38,10 +38,15 @@ class WORLD_PT_world(WorldButtonsPanel):
elif world: elif world:
split.template_ID(space, "pin_id") split.template_ID(space, "pin_id")
split.itemS() class WORLD_PT_world(WorldButtonsPanel):
__label__ = "World"
def draw(self, context):
layout = self.layout
world = context.world
if world: if world:
layout.itemS()
row = layout.row() row = layout.row()
row.itemR(world, "blend_sky") row.itemR(world, "blend_sky")
@ -171,6 +176,7 @@ class WORLD_PT_ambient_occlusion(WorldButtonsPanel):
col.row().itemR(ao, "color", expand=True) col.row().itemR(ao, "color", expand=True)
col.itemR(ao, "energy") col.itemR(ao, "energy")
bpy.types.register(WORLD_PT_context_world)
bpy.types.register(WORLD_PT_preview) bpy.types.register(WORLD_PT_preview)
bpy.types.register(WORLD_PT_world) bpy.types.register(WORLD_PT_world)
bpy.types.register(WORLD_PT_ambient_occlusion) bpy.types.register(WORLD_PT_ambient_occlusion)

@ -21,6 +21,8 @@ class FILEBROWSER_HT_header(bpy.types.Header):
row = layout.row(align=True) row = layout.row(align=True)
row.itemO("FILE_OT_parent", text="", icon='ICON_FILE_PARENT') row.itemO("FILE_OT_parent", text="", icon='ICON_FILE_PARENT')
row.itemO("FILE_OT_refresh", text="", icon='ICON_FILE_REFRESH') row.itemO("FILE_OT_refresh", text="", icon='ICON_FILE_REFRESH')
row.itemO("FILE_OT_previous", text="", icon='ICON_PREV_KEYFRAME')
row.itemO("FILE_OT_next", text="", icon='ICON_NEXT_KEYFRAME')
layout.itemR(params, "display", expand=True, text="") layout.itemR(params, "display", expand=True, text="")
layout.itemR(params, "sort", expand=True, text="") layout.itemR(params, "sort", expand=True, text="")

@ -13,7 +13,7 @@ class IMAGE_MT_view(bpy.types.Menu):
show_uvedit = sima.show_uvedit show_uvedit = sima.show_uvedit
layout.itemO("IMAGE_OT_properties") # icon layout.itemO("IMAGE_OT_properties", icon="ICON_MENU_PANEL")
layout.itemS() layout.itemS()
@ -55,7 +55,7 @@ class IMAGE_MT_select(bpy.types.Menu):
layout.itemS() layout.itemS()
layout.itemO("UV_OT_select_all_toggle") layout.itemO("UV_OT_select_all_toggle")
layout.itemO("UV_OT_select_invert") layout.itemO("UV_OT_select_inverse")
layout.itemO("UV_OT_unlink_selection") layout.itemO("UV_OT_unlink_selection")
layout.itemS() layout.itemS()
@ -257,8 +257,6 @@ class IMAGE_HT_header(bpy.types.Header):
if show_uvedit: if show_uvedit:
uvedit = sima.uv_editor uvedit = sima.uv_editor
layout.itemS()
layout.itemR(uvedit, "pivot", text="") layout.itemR(uvedit, "pivot", text="")
layout.itemR(settings, "uv_sync_selection", text="") layout.itemR(settings, "uv_sync_selection", text="")

@ -90,6 +90,10 @@ class SEQUENCER_MT_view(bpy.types.Menu):
""" """
layout.itemR(st, "draw_frames") layout.itemR(st, "draw_frames")
if st.display_mode == 'IMAGE':
layout.itemR(st, "draw_safe_margin")
if st.display_mode == 'WAVEFORM':
layout.itemR(st, "seperate_color_preview")
""" """
if(!sa->full) uiDefIconTextBut(block, BUTM, B_FULL, ICON_BLANK1, "Maximize Window|Ctrl UpArrow", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0,0, ""); if(!sa->full) uiDefIconTextBut(block, BUTM, B_FULL, ICON_BLANK1, "Maximize Window|Ctrl UpArrow", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0,0, "");
@ -115,7 +119,7 @@ class SEQUENCER_MT_select(bpy.types.Menu):
layout.itemS() layout.itemS()
layout.itemO("SEQUENCER_OT_select_linked") layout.itemO("SEQUENCER_OT_select_linked")
layout.itemO("SEQUENCER_OT_select_all_toggle") layout.itemO("SEQUENCER_OT_select_all_toggle")
layout.itemO("SEQUENCER_OT_select_invert") layout.itemO("SEQUENCER_OT_select_inverse")
class SEQUENCER_MT_marker(bpy.types.Menu): class SEQUENCER_MT_marker(bpy.types.Menu):
__space_type__ = "SEQUENCE_EDITOR" __space_type__ = "SEQUENCE_EDITOR"
@ -198,7 +202,7 @@ class SEQUENCER_MT_strip(bpy.types.Menu):
layout.itemO("SEQUENCER_OT_images_separate") layout.itemO("SEQUENCER_OT_images_separate")
layout.itemS() layout.itemS()
layout.itemO("SEQUENCER_OT_duplicate_add") layout.itemO("SEQUENCER_OT_duplicate")
layout.itemO("SEQUENCER_OT_delete") layout.itemO("SEQUENCER_OT_delete")
strip = act_strip(context) strip = act_strip(context)
@ -238,7 +242,7 @@ class SEQUENCER_MT_strip(bpy.types.Menu):
layout.itemO("SEQUENCER_OT_mute") layout.itemO("SEQUENCER_OT_mute")
layout.itemO("SEQUENCER_OT_unmute") layout.itemO("SEQUENCER_OT_unmute")
layout.item_enumO("SEQUENCER_OT_mute", property="type", value='UNSELECTED', text="Mute Deselected Strips") layout.item_booleanO("SEQUENCER_OT_mute", "unselected", 1, text="Mute Deselected Strips")
layout.itemO("SEQUENCER_OT_snap") layout.itemO("SEQUENCER_OT_snap")

@ -0,0 +1,254 @@
import bpy
# ********** default tools for objectmode ****************
class View3DPanel(bpy.types.Panel):
__space_type__ = "VIEW_3D"
__region_type__ = "TOOLS"
__context__ = "objectmode"
class VIEW3D_PT_tools_objectmode(View3DPanel):
__idname__ = "VIEW3D_PT_tools_objectmode"
__label__ = "Object Tools"
def draw(self, context):
layout = self.layout
layout.row().itemO("OBJECT_OT_duplicate")
layout.row().itemO("OBJECT_OT_delete")
layout.row().itemO("OBJECT_OT_mesh_add")
layout.row().itemO("OBJECT_OT_curve_add")
layout.row().itemO("OBJECT_OT_text_add")
layout.row().itemO("OBJECT_OT_surface_add")
# ********** default tools for editmode_mesh ****************
class View3DPanel(bpy.types.Panel):
__space_type__ = "VIEW_3D"
__region_type__ = "TOOLS"
__context__ = "editmode_mesh"
class VIEW3D_PT_tools_editmode_mesh(View3DPanel):
__idname__ = "VIEW3D_PT_tools_editmode_mesh"
__label__ = "Mesh Tools"
def draw(self, context):
layout = self.layout
layout.row().itemO("MESH_OT_duplicate")
layout.row().itemO("MESH_OT_delete")
layout.row().itemO("MESH_OT_spin")
layout.row().itemO("MESH_OT_screw")
layout.row().itemO("MESH_OT_primitive_plane_add")
layout.row().itemO("MESH_OT_primitive_cube_add")
layout.row().itemO("MESH_OT_primitive_circle_add")
layout.row().itemO("MESH_OT_primitive_cylinder_add")
# ********** default tools for editmode_curve ****************
class View3DPanel(bpy.types.Panel):
__space_type__ = "VIEW_3D"
__region_type__ = "TOOLS"
__context__ = "editmode_curve"
class VIEW3D_PT_tools_editmode_curve(View3DPanel):
__idname__ = "VIEW3D_PT_tools_editmode_curve"
__label__ = "Curve Tools"
def draw(self, context):
layout = self.layout
layout.row().itemO("CURVE_OT_duplicate")
layout.row().itemO("CURVE_OT_delete")
layout.row().itemO("OBJECT_OT_curve_add")
layout.row().itemO("CURVE_OT_subdivide")
# ********** default tools for editmode_surface ****************
class View3DPanel(bpy.types.Panel):
__space_type__ = "VIEW_3D"
__region_type__ = "TOOLS"
__context__ = "editmode_surface"
class VIEW3D_PT_tools_editmode_surface(View3DPanel):
__idname__ = "VIEW3D_PT_tools_editmode_surface"
__label__ = "Surface Tools"
def draw(self, context):
layout = self.layout
layout.row().itemO("CURVE_OT_duplicate")
layout.row().itemO("CURVE_OT_delete")
layout.row().itemO("OBJECT_OT_surface_add")
layout.row().itemO("CURVE_OT_subdivide")
# ********** default tools for editmode_text ****************
class View3DPanel(bpy.types.Panel):
__space_type__ = "VIEW_3D"
__region_type__ = "TOOLS"
__context__ = "editmode_text"
class VIEW3D_PT_tools_editmode_text(View3DPanel):
__idname__ = "VIEW3D_PT_tools_editmode_text"
__label__ = "Text Tools"
def draw(self, context):
layout = self.layout
layout.row().itemO("FONT_OT_text_copy")
layout.row().itemO("FONT_OT_text_paste")
layout.row().itemO("FONT_OT_case_set")
layout.row().itemO("FONT_OT_style_toggle")
# ********** default tools for editmode_armature ****************
class View3DPanel(bpy.types.Panel):
__space_type__ = "VIEW_3D"
__region_type__ = "TOOLS"
__context__ = "editmode_armature"
class VIEW3D_PT_tools_editmode_armature(View3DPanel):
__idname__ = "VIEW3D_PT_tools_editmode_armature"
__label__ = "Armature Tools"
def draw(self, context):
layout = self.layout
layout.row().itemO("ARMATURE_OT_duplicate_selected")
layout.row().itemO("ARMATURE_OT_bone_primitive_add")
layout.row().itemO("ARMATURE_OT_delete")
layout.row().itemO("ARMATURE_OT_parent_clear")
# ********** default tools for editmode_mball ****************
class View3DPanel(bpy.types.Panel):
__space_type__ = "VIEW_3D"
__region_type__ = "TOOLS"
__context__ = "editmode_mball"
class VIEW3D_PT_tools_editmode_mball(View3DPanel):
__idname__ = "VIEW3D_PT_tools_editmode_mball"
__label__ = "Meta Tools"
def draw(self, context):
layout = self.layout
row = layout.row()
# ********** default tools for editmode_lattice ****************
class View3DPanel(bpy.types.Panel):
__space_type__ = "VIEW_3D"
__region_type__ = "TOOLS"
__context__ = "editmode_lattice"
class VIEW3D_PT_tools_editmode_lattice(View3DPanel):
__idname__ = "VIEW3D_PT_tools_editmode_lattice"
__label__ = "Lattice Tools"
def draw(self, context):
layout = self.layout
row = layout.row()
# ********** default tools for posemode ****************
class View3DPanel(bpy.types.Panel):
__space_type__ = "VIEW_3D"
__region_type__ = "TOOLS"
__context__ = "posemode"
class VIEW3D_PT_tools_posemode(View3DPanel):
__idname__ = "VIEW3D_PT_tools_posemode"
__label__ = "Pose Tools"
def draw(self, context):
layout = self.layout
layout.row().itemO("POSE_OT_hide")
layout.row().itemO("POSE_OT_reveal")
layout.row().itemO("POSE_OT_rot_clear")
layout.row().itemO("POSE_OT_loc_clear")
# ********** default tools for sculptmode ****************
class View3DPanel(bpy.types.Panel):
__space_type__ = "VIEW_3D"
__region_type__ = "TOOLS"
__context__ = "sculptmode"
class VIEW3D_PT_tools_sculptmode(View3DPanel):
__idname__ = "VIEW3D_PT_tools_sculptmode"
__label__ = "Sculpt Tools"
def draw(self, context):
layout = self.layout
layout.row().itemO("SCULPT_OT_radial_control")
# ********** default tools for weightpaint ****************
class View3DPanel(bpy.types.Panel):
__space_type__ = "VIEW_3D"
__region_type__ = "TOOLS"
__context__ = "weightpaint"
class VIEW3D_PT_tools_weightpaint(View3DPanel):
__idname__ = "VIEW3D_PT_tools_weightpaint"
__label__ = "Weight Paint Tools"
def draw(self, context):
layout = self.layout
layout.row().itemO("PAINT_OT_weight_paint_radial_control")
# ********** default tools for vertexpaint ****************
class View3DPanel(bpy.types.Panel):
__space_type__ = "VIEW_3D"
__region_type__ = "TOOLS"
__context__ = "vertexpaint"
class VIEW3D_PT_tools_vertexpaint(View3DPanel):
__idname__ = "VIEW3D_PT_tools_vertexpaint"
__label__ = "Vertex Paint Tools"
def draw(self, context):
layout = self.layout
layout.row().itemO("PAINT_OT_vertex_paint_radial_control")
# ********** default tools for texturepaint ****************
class View3DPanel(bpy.types.Panel):
__space_type__ = "VIEW_3D"
__region_type__ = "TOOLS"
__context__ = "texturepaint"
class VIEW3D_PT_tools_texturepaint(View3DPanel):
__idname__ = "VIEW3D_PT_tools_texturepaint"
__label__ = "Texture Paint Tools"
def draw(self, context):
layout = self.layout
layout.row().itemO("PAINT_OT_texture_paint_radial_control")
bpy.types.register(VIEW3D_PT_tools_objectmode)
bpy.types.register(VIEW3D_PT_tools_editmode_mesh)
bpy.types.register(VIEW3D_PT_tools_editmode_curve)
bpy.types.register(VIEW3D_PT_tools_editmode_surface)
bpy.types.register(VIEW3D_PT_tools_editmode_text)
bpy.types.register(VIEW3D_PT_tools_editmode_armature)
bpy.types.register(VIEW3D_PT_tools_editmode_mball)
bpy.types.register(VIEW3D_PT_tools_editmode_lattice)
bpy.types.register(VIEW3D_PT_tools_posemode)
bpy.types.register(VIEW3D_PT_tools_sculptmode)
bpy.types.register(VIEW3D_PT_tools_weightpaint)
bpy.types.register(VIEW3D_PT_tools_vertexpaint)
bpy.types.register(VIEW3D_PT_tools_texturepaint)

@ -83,7 +83,6 @@ GRPLIB += $(NAN_SOUNDSYSTEM)/lib/$(DEBUG_DIR)libSoundSystem.a
GRPLIB += $(NAN_GHOST)/lib/$(DEBUG_DIR)libghost.a GRPLIB += $(NAN_GHOST)/lib/$(DEBUG_DIR)libghost.a
GRPLIB += $(NAN_STRING)/lib/$(DEBUG_DIR)libstring.a GRPLIB += $(NAN_STRING)/lib/$(DEBUG_DIR)libstring.a
GRPLIB += $(OCGDIR)/blender/render/$(DEBUG_DIR)librender.a GRPLIB += $(OCGDIR)/blender/render/$(DEBUG_DIR)librender.a
GRPLIB += $(OCGDIR)/blender/radiosity/$(DEBUG_DIR)libradiosity.a
# nlin: the reason that some libraries appear more than once below is # nlin: the reason that some libraries appear more than once below is
# to handle circular dependencies in linking among libraries... some # to handle circular dependencies in linking among libraries... some
@ -221,8 +220,8 @@ PULIB += $(OCGDIR)/blender/ed_sequencer/$(DEBUG_DIR)libed_sequencer.a
PULIB += $(OCGDIR)/blender/ed_file/$(DEBUG_DIR)libed_file.a PULIB += $(OCGDIR)/blender/ed_file/$(DEBUG_DIR)libed_file.a
PULIB += $(OCGDIR)/blender/ed_info/$(DEBUG_DIR)libed_info.a PULIB += $(OCGDIR)/blender/ed_info/$(DEBUG_DIR)libed_info.a
PULIB += $(OCGDIR)/blender/ed_buttons/$(DEBUG_DIR)libed_buttons.a PULIB += $(OCGDIR)/blender/ed_buttons/$(DEBUG_DIR)libed_buttons.a
PULIB += $(OCGDIR)/blender/ed_node/$(DEBUG_DIR)libed_node.a
PULIB += $(OCGDIR)/blender/ed_graph/$(DEBUG_DIR)libed_graph.a PULIB += $(OCGDIR)/blender/ed_graph/$(DEBUG_DIR)libed_graph.a
PULIB += $(OCGDIR)/blender/ed_node/$(DEBUG_DIR)libed_node.a
PULIB += $(OCGDIR)/blender/ed_outliner/$(DEBUG_DIR)libed_outliner.a PULIB += $(OCGDIR)/blender/ed_outliner/$(DEBUG_DIR)libed_outliner.a
PULIB += $(OCGDIR)/blender/ed_time/$(DEBUG_DIR)libed_time.a PULIB += $(OCGDIR)/blender/ed_time/$(DEBUG_DIR)libed_time.a
PULIB += $(OCGDIR)/blender/ed_preview/$(DEBUG_DIR)libed_preview.a PULIB += $(OCGDIR)/blender/ed_preview/$(DEBUG_DIR)libed_preview.a

@ -78,6 +78,11 @@ float BLF_height(char *str);
float BLF_width_default(char *str); float BLF_width_default(char *str);
float BLF_height_default(char *str); float BLF_height_default(char *str);
/*
* set rotation for default font
*/
void BLF_default_rotation(float angle);
/* /*
* By default, rotation and clipping are disable and * By default, rotation and clipping are disable and
* have to be enable/disable using BLF_enable/disable. * have to be enable/disable using BLF_enable/disable.
@ -85,7 +90,6 @@ float BLF_height_default(char *str);
void BLF_rotation(float angle); void BLF_rotation(float angle);
void BLF_clipping(float xmin, float ymin, float xmax, float ymax); void BLF_clipping(float xmin, float ymin, float xmax, float ymax);
void BLF_blur(int size); void BLF_blur(int size);
void BLF_kerning(float space);
void BLF_enable(int option); void BLF_enable(int option);
void BLF_disable(int option); void BLF_disable(int option);
@ -132,10 +136,8 @@ void BLF_dir_free(char **dirs, int count);
/* font->flags. */ /* font->flags. */
#define BLF_ROTATION (1<<0) #define BLF_ROTATION (1<<0)
#define BLF_CLIPPING (1<<1) #define BLF_CLIPPING (1<<1)
#define BLF_FONT_KERNING (1<<2) #define BLF_SHADOW (1<<2)
#define BLF_USER_KERNING (1<<3) #define BLF_KERNING_DEFAULT (1<<3)
#define BLF_SHADOW (1<<4)
#define BLF_OVERLAP_CHAR (1<<5)
/* font->mode. */ /* font->mode. */
#define BLF_MODE_TEXTURE 0 #define BLF_MODE_TEXTURE 0

@ -321,6 +321,19 @@ void BLF_draw_default(float x, float y, float z, char *str)
} }
} }
void BLF_default_rotation(float angle)
{
if (global_font_default>=0) {
global_font[global_font_default]->angle= angle;
if(angle)
global_font[global_font_default]->flags |= BLF_ROTATION;
else
global_font[global_font_default]->flags &= ~BLF_ROTATION;
}
}
void BLF_draw(char *str) void BLF_draw(char *str)
{ {
FontBLF *font; FontBLF *font;
@ -492,15 +505,6 @@ void BLF_mode(int mode)
font->mode= mode; font->mode= mode;
} }
void BLF_kerning(float space)
{
FontBLF *font;
font= global_font[global_font_cur];
if (font)
font->kerning= space;
}
void BLF_shadow(int level, float r, float g, float b, float a) void BLF_shadow(int level, float r, float g, float b, float a)
{ {
FontBLF *font; FontBLF *font;

@ -101,8 +101,8 @@ void blf_font_draw(FontBLF *font, char *str)
GlyphBLF *g, *g_prev; GlyphBLF *g, *g_prev;
FT_Vector delta; FT_Vector delta;
FT_UInt glyph_index, g_prev_index; FT_UInt glyph_index, g_prev_index;
float pen_x, pen_y, old_pen_x; int pen_x, pen_y;
int i, has_kerning; int i, has_kerning, st;
if (!font->glyph_cache) if (!font->glyph_cache)
return; return;
@ -139,33 +139,21 @@ void blf_font_draw(FontBLF *font, char *str)
else if (font->mode == BLF_MODE_TEXTURE && (!g->tex_data)) else if (font->mode == BLF_MODE_TEXTURE && (!g->tex_data))
g= blf_glyph_add(font, glyph_index, c); g= blf_glyph_add(font, glyph_index, c);
if ((font->flags & BLF_FONT_KERNING) && has_kerning && g_prev) { if (has_kerning && g_prev) {
old_pen_x= pen_x;
delta.x= 0; delta.x= 0;
delta.y= 0; delta.y= 0;
if (FT_Get_Kerning(font->face, g_prev_index, glyph_index, FT_KERNING_UNFITTED, &delta) == 0) { if (font->flags & BLF_KERNING_DEFAULT)
st= FT_Get_Kerning(font->face, g_prev_index, glyph_index, ft_kerning_default, &delta);
else
st= FT_Get_Kerning(font->face, g_prev_index, glyph_index, FT_KERNING_UNFITTED, &delta);
if (st == 0)
pen_x += delta.x >> 6; pen_x += delta.x >> 6;
if (font->flags & BLF_OVERLAP_CHAR) {
if (pen_x < old_pen_x)
pen_x= old_pen_x;
}
}
}
if (font->flags & BLF_USER_KERNING) {
old_pen_x= pen_x;
pen_x += font->kerning;
if (font->flags & BLF_OVERLAP_CHAR) {
if (pen_x < old_pen_x)
pen_x= old_pen_x;
}
} }
/* do not return this loop if clipped, we want every character tested */ /* do not return this loop if clipped, we want every character tested */
blf_glyph_render(font, g, pen_x, pen_y); blf_glyph_render(font, g, (float)pen_x, (float)pen_y);
pen_x += g->advance; pen_x += g->advance;
g_prev= g; g_prev= g;
@ -180,8 +168,8 @@ void blf_font_boundbox(FontBLF *font, char *str, rctf *box)
FT_Vector delta; FT_Vector delta;
FT_UInt glyph_index, g_prev_index; FT_UInt glyph_index, g_prev_index;
rctf gbox; rctf gbox;
float pen_x, pen_y, old_pen_x; int pen_x, pen_y;
int i, has_kerning; int i, has_kerning, st;
if (!font->glyph_cache) if (!font->glyph_cache)
return; return;
@ -223,29 +211,17 @@ void blf_font_boundbox(FontBLF *font, char *str, rctf *box)
else if (font->mode == BLF_MODE_TEXTURE && (!g->tex_data)) else if (font->mode == BLF_MODE_TEXTURE && (!g->tex_data))
g= blf_glyph_add(font, glyph_index, c); g= blf_glyph_add(font, glyph_index, c);
if ((font->flags & BLF_FONT_KERNING) && has_kerning && g_prev) { if (has_kerning && g_prev) {
old_pen_x= pen_x;
delta.x= 0; delta.x= 0;
delta.y= 0; delta.y= 0;
if (FT_Get_Kerning(font->face, g_prev_index, glyph_index, FT_KERNING_UNFITTED, &delta) == 0) { if (font->flags & BLF_KERNING_DEFAULT)
st= FT_Get_Kerning(font->face, g_prev_index, glyph_index, ft_kerning_default, &delta);
else
st= FT_Get_Kerning(font->face, g_prev_index, glyph_index, FT_KERNING_UNFITTED, &delta);
if (st == 0)
pen_x += delta.x >> 6; pen_x += delta.x >> 6;
if (font->flags & BLF_OVERLAP_CHAR) {
if (pen_x < old_pen_x)
pen_x= old_pen_x;
}
}
}
if (font->flags & BLF_USER_KERNING) {
old_pen_x= pen_x;
pen_x += font->kerning;
if (font->flags & BLF_OVERLAP_CHAR) {
if (pen_x < old_pen_x)
pen_x= old_pen_x;
}
} }
gbox.xmin= g->box.xmin + pen_x; gbox.xmin= g->box.xmin + pen_x;
@ -329,10 +305,9 @@ void blf_font_fill(FontBLF *font)
font->clip_rec.xmax= 0.0f; font->clip_rec.xmax= 0.0f;
font->clip_rec.ymin= 0.0f; font->clip_rec.ymin= 0.0f;
font->clip_rec.ymax= 0.0f; font->clip_rec.ymax= 0.0f;
font->flags= BLF_USER_KERNING | BLF_FONT_KERNING; font->flags= 0;
font->dpi= 0; font->dpi= 0;
font->size= 0; font->size= 0;
font->kerning= 0.0f;
font->cache.first= NULL; font->cache.first= NULL;
font->cache.last= NULL; font->cache.last= NULL;
font->glyph_cache= NULL; font->glyph_cache= NULL;

@ -213,11 +213,7 @@ GlyphBLF *blf_glyph_texture_add(FontBLF *font, FT_UInt index, unsigned int c)
else else
do_new= 1; do_new= 1;
if (font->flags & BLF_FONT_KERNING) err= FT_Load_Glyph(font->face, index, FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP);
err= FT_Load_Glyph(font->face, index, FT_LOAD_NO_BITMAP);
else
err= FT_Load_Glyph(font->face, index, FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP);
if (err) if (err)
return(NULL); return(NULL);
@ -332,11 +328,7 @@ GlyphBLF *blf_glyph_bitmap_add(FontBLF *font, FT_UInt index, unsigned int c)
else else
do_new= 1; do_new= 1;
if (font->flags & BLF_FONT_KERNING) err= FT_Load_Glyph(font->face, index, FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP);
err= FT_Load_Glyph(font->face, index, FT_LOAD_NO_BITMAP);
else
err= FT_Load_Glyph(font->face, index, FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP);
if (err) if (err)
return(NULL); return(NULL);

@ -177,9 +177,6 @@ typedef struct FontBLF {
/* font size. */ /* font size. */
int size; int size;
/* kerning space, user setting. */
float kerning;
/* max texture size. */ /* max texture size. */
int max_tex_size; int max_tex_size;

@ -68,6 +68,9 @@ void make_local_action(struct bAction *act);
/* Some kind of bounding box operation on the action */ /* Some kind of bounding box operation on the action */
void calc_action_range(const struct bAction *act, float *start, float *end, int incl_hidden); void calc_action_range(const struct bAction *act, float *start, float *end, int incl_hidden);
/* Does action have any motion data at all? */
short action_has_motion(const struct bAction *act);
/* Action Groups API ----------------- */ /* Action Groups API ----------------- */
/* Make the given Action Group the active one */ /* Make the given Action Group the active one */
@ -145,12 +148,6 @@ void copy_pose_result(struct bPose *to, struct bPose *from);
/* clear all transforms */ /* clear all transforms */
void rest_pose(struct bPose *pose); void rest_pose(struct bPose *pose);
/* map global time (frame nr) to strip converted time, doesn't clip */
float get_action_frame(struct Object *ob, float cframe);
/* map strip time to global time (frame nr) */
float get_action_frame_inv(struct Object *ob, float cframe);
/* functions used by the game engine */ /* functions used by the game engine */
void game_copy_pose(struct bPose **dst, struct bPose *src); void game_copy_pose(struct bPose **dst, struct bPose *src);
void game_free_pose(struct bPose *pose); void game_free_pose(struct bPose *pose);

@ -41,6 +41,8 @@ struct Particle;
struct Group; struct Group;
struct RNG; struct RNG;
struct PartDeflect *object_add_collision_fields(void);
typedef struct pEffectorCache { typedef struct pEffectorCache {
struct pEffectorCache *next, *prev; struct pEffectorCache *next, *prev;
Object *ob; Object *ob;

@ -1,12 +1,33 @@
/* Testing code for new animation system in 2.5 /**
* Copyright 2009, Joshua Leung * $Id$
*
* ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
* All rights reserved.
*
* Contributor(s): Joshua Leung (full recode)
*
* ***** END GPL LICENSE BLOCK *****
*/ */
#ifndef BKE_FCURVE_H #ifndef BKE_FCURVE_H
#define BKE_FCURVE_H #define BKE_FCURVE_H
//struct ListBase;
struct FCurve; struct FCurve;
struct FModifier; struct FModifier;
struct ChannelDriver; struct ChannelDriver;
@ -54,8 +75,8 @@ typedef struct FModifierTypeInfo {
short size; /* size in bytes of the struct */ short size; /* size in bytes of the struct */
short acttype; /* eFMI_Action_Types */ short acttype; /* eFMI_Action_Types */
short requires; /* eFMI_Requirement_Flags */ short requires; /* eFMI_Requirement_Flags */
char name[32]; /* name of modifier in interface */ char name[64]; /* name of modifier in interface */
char structName[32]; /* name of struct for SDNA */ char structName[64]; /* name of struct for SDNA */
/* data management function pointers - special handling */ /* data management function pointers - special handling */
/* free any data that is allocated separately (optional) */ /* free any data that is allocated separately (optional) */
@ -104,14 +125,20 @@ FModifierTypeInfo *get_fmodifier_typeinfo(int type);
/* ---------------------- */ /* ---------------------- */
struct FModifier *fcurve_add_modifier(struct FCurve *fcu, int type); struct FModifier *add_fmodifier(ListBase *modifiers, int type);
void fcurve_copy_modifiers(ListBase *dst, ListBase *src); void copy_fmodifiers(ListBase *dst, ListBase *src);
void fcurve_remove_modifier(struct FCurve *fcu, struct FModifier *fcm); void remove_fmodifier(ListBase *modifiers, struct FModifier *fcm);
void fcurve_free_modifiers(struct FCurve *fcu); void free_fmodifiers(ListBase *modifiers);
void fcurve_bake_modifiers(struct FCurve *fcu, int start, int end);
struct FModifier *fcurve_find_active_modifier(struct FCurve *fcu); struct FModifier *find_active_fmodifier(ListBase *modifiers);
void fcurve_set_active_modifier(struct FCurve *fcu, struct FModifier *fcm); void set_active_fmodifier(ListBase *modifiers, struct FModifier *fcm);
short list_has_suitable_fmodifier(ListBase *modifiers, int mtype, short acttype);
float evaluate_time_fmodifiers(ListBase *modifiers, struct FCurve *fcu, float cvalue, float evaltime);
void evaluate_value_fmodifiers(ListBase *modifiers, struct FCurve *fcu, float *cvalue, float evaltime);
void fcurve_bake_modifiers(struct FCurve *fcu, int start, int end);
/* ************** F-Curves API ******************** */ /* ************** F-Curves API ******************** */
@ -126,9 +153,6 @@ void copy_fcurves(ListBase *dst, ListBase *src);
/* find matching F-Curve in the given list of F-Curves */ /* find matching F-Curve in the given list of F-Curves */
struct FCurve *list_find_fcurve(ListBase *list, const char rna_path[], const int array_index); struct FCurve *list_find_fcurve(ListBase *list, const char rna_path[], const int array_index);
/* test if there is a keyframe at cfra */
short on_keyframe_fcurve(struct FCurve *fcu, float cfra);
/* get the time extents for F-Curve */ /* get the time extents for F-Curve */
void calc_fcurve_range(struct FCurve *fcu, float *min, float *max); void calc_fcurve_range(struct FCurve *fcu, float *min, float *max);

@ -1,6 +1,5 @@
/** /**
* BKE_fluidsim.h * $Id$
*
* *
* ***** BEGIN GPL LICENSE BLOCK ***** * ***** BEGIN GPL LICENSE BLOCK *****
* *
@ -28,29 +27,40 @@
* ***** END GPL LICENSE BLOCK ***** * ***** END GPL LICENSE BLOCK *****
*/ */
#include "DNA_modifier_types.h" #ifndef BKE_FLUIDSIM_H
#include "DNA_object_fluidsim.h" // N_T #define BKE_FLUIDSIM_H
#include "DNA_object_types.h"
#include "BKE_DerivedMesh.h" struct Object;
struct Scene;
struct FluidsimModifierData;
struct DerivedMesh;
struct MVert;
/* old interface */ /* old interface */
FluidsimSettings *fluidsimSettingsNew(Object *srcob); struct FluidsimSettings *fluidsimSettingsNew(struct Object *srcob);
void initElbeemMesh(Scene *scene, Object *ob, int *numVertices, float **vertices, int *numTriangles, int **triangles, int useGlobalCoords, int modifierIndex);
void initElbeemMesh(struct Scene *scene, struct Object *ob,
int *numVertices, float **vertices,
int *numTriangles, int **triangles,
int useGlobalCoords, int modifierIndex);
/* new fluid-modifier interface */ /* new fluid-modifier interface */
void fluidsim_init(FluidsimModifierData *fluidmd); void fluidsim_init(struct FluidsimModifierData *fluidmd);
void fluidsim_free(FluidsimModifierData *fluidmd); void fluidsim_free(struct FluidsimModifierData *fluidmd);
DerivedMesh *fluidsim_read_cache(Object *ob, DerivedMesh *orgdm, FluidsimModifierData *fluidmd, int framenr, int useRenderParams); struct DerivedMesh *fluidsim_read_cache(struct Object *ob, struct DerivedMesh *orgdm,
void fluidsim_read_vel_cache(FluidsimModifierData *fluidmd, DerivedMesh *dm, char *filename); struct FluidsimModifierData *fluidmd, int framenr, int useRenderParams);
DerivedMesh *fluidsimModifier_do(FluidsimModifierData *fluidmd, Scene *scene, Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc); void fluidsim_read_vel_cache(struct FluidsimModifierData *fluidmd, struct DerivedMesh *dm,
char *filename);
struct DerivedMesh *fluidsimModifier_do(struct FluidsimModifierData *fluidmd,
struct Scene *scene, struct Object *ob, struct DerivedMesh *dm,
int useRenderParams, int isFinalCalc);
// get bounding box of mesh /* bounding box & memory estimate */
void fluid_get_bb(MVert *mvert, int totvert, float obmat[][4], void fluid_get_bb(struct MVert *mvert, int totvert, float obmat[][4],
/*RET*/ float start[3], /*RET*/ float size[3] ); float start[3], float size[3]);
void fluid_estimate_memory(struct Object *ob, struct FluidsimSettings *fss, char *value);
#endif

@ -62,7 +62,7 @@ typedef enum {
* used for particles modifier that doesn't actually modify the object * used for particles modifier that doesn't actually modify the object
* unless it's a mesh and can be exploded -> curve can also emit particles * unless it's a mesh and can be exploded -> curve can also emit particles
*/ */
eModifierTypeType_DeformOrConstruct eModifierTypeType_DeformOrConstruct,
} ModifierTypeType; } ModifierTypeType;
typedef enum { typedef enum {
@ -87,6 +87,9 @@ typedef enum {
/* For modifiers that support pointcache, so we can check to see if it has files we need to deal with /* For modifiers that support pointcache, so we can check to see if it has files we need to deal with
*/ */
eModifierTypeFlag_UsesPointCache = (1<<6), eModifierTypeFlag_UsesPointCache = (1<<6),
/* For physics modifiers, max one per type */
eModifierTypeFlag_Single = (1<<7)
} ModifierTypeFlag; } ModifierTypeFlag;
typedef void (*ObjectWalkFunc)(void *userData, struct Object *ob, struct Object **obpoin); typedef void (*ObjectWalkFunc)(void *userData, struct Object *ob, struct Object **obpoin);

@ -17,12 +17,12 @@
* along with this program; if not, write to the Free Software Foundation, * along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* *
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
* All rights reserved. * All rights reserved.
* *
* The Original Code is: all of this file. * The Original Code is: all of this file.
* *
* Contributor(s): none yet. * Contributor(s): Joshua Leung (full recode)
* *
* ***** END GPL LICENSE BLOCK ***** * ***** END GPL LICENSE BLOCK *****
*/ */
@ -30,15 +30,90 @@
#ifndef BKE_NLA_H #ifndef BKE_NLA_H
#define BKE_NLA_H #define BKE_NLA_H
struct bActionStrip; struct AnimData;
struct ListBase; struct NlaStrip;
struct Object; struct NlaTrack;
struct bAction;
/* ----------------------------- */
/* Data Management */
void free_nlastrip(ListBase *strips, struct NlaStrip *strip);
void free_nlatrack(ListBase *tracks, struct NlaTrack *nlt);
void free_nladata(ListBase *tracks);
struct NlaStrip *copy_nlastrip(struct NlaStrip *strip);
struct NlaTrack *copy_nlatrack(struct NlaTrack *nlt);
void copy_nladata(ListBase *dst, ListBase *src);
struct NlaTrack *add_nlatrack(struct AnimData *adt, struct NlaTrack *prev);
struct NlaStrip *add_nlastrip(struct bAction *act);
struct NlaStrip *add_nlastrip_to_stack(struct AnimData *adt, struct bAction *act);
/* ----------------------------- */
/* API */
short BKE_nlastrips_has_space(ListBase *strips, float start, float end);
void BKE_nlastrips_sort_strips(ListBase *strips);
short BKE_nlastrips_add_strip(ListBase *strips, struct NlaStrip *strip);
void BKE_nlastrips_make_metas(ListBase *strips, short temp);
void BKE_nlastrips_clear_metas(ListBase *strips, short onlySel, short onlyTemp);
void BKE_nlastrips_clear_metastrip(ListBase *strips, struct NlaStrip *strip);
short BKE_nlameta_add_strip(struct NlaStrip *mstrip, struct NlaStrip *strip);
void BKE_nlameta_flush_transforms(struct NlaStrip *mstrip);
/* ............ */
struct NlaTrack *BKE_nlatrack_find_active(ListBase *tracks);
void BKE_nlatrack_set_active(ListBase *tracks, struct NlaTrack *nlt);
void BKE_nlatrack_solo_toggle(struct AnimData *adt, struct NlaTrack *nlt);
short BKE_nlatrack_has_space(struct NlaTrack *nlt, float start, float end);
void BKE_nlatrack_sort_strips(struct NlaTrack *nlt);
short BKE_nlatrack_add_strip(struct NlaTrack *nlt, struct NlaStrip *strip);
/* ............ */
struct NlaStrip *BKE_nlastrip_find_active(struct NlaTrack *nlt);
short BKE_nlastrip_within_bounds(struct NlaStrip *strip, float min, float max);
void BKE_nlastrip_validate_name(struct AnimData *adt, struct NlaStrip *strip);
/* ............ */
short BKE_nlatrack_has_animated_strips(struct NlaTrack *nlt);
short BKE_nlatracks_have_animated_strips(ListBase *tracks);
void BKE_nlastrip_validate_fcurves(struct NlaStrip *strip);
/* ............ */
void BKE_nla_action_pushdown(struct AnimData *adt);
short BKE_nla_tweakmode_enter(struct AnimData *adt);
void BKE_nla_tweakmode_exit(struct AnimData *adt);
/* ----------------------------- */
/* Time Mapping */
/* time mapping conversion modes */
enum {
/* convert from global time to strip time - for evaluation */
NLATIME_CONVERT_EVAL = 0,
/* convert from global time to strip time - for editing corrections */
// XXX old 0 invert
NLATIME_CONVERT_UNMAP,
/* convert from strip time to global time */
// xxx old 1 invert
NLATIME_CONVERT_MAP,
} eNlaTime_ConvertModes;
float BKE_nla_tweakedit_remap(struct AnimData *adt, float cframe, short mode);
void free_actionstrip (struct bActionStrip* strip);
void free_nlastrips (struct ListBase *nlalist);
void copy_nlastrips (struct ListBase *dst, struct ListBase *src);
void copy_actionstrip (struct bActionStrip **dst, struct bActionStrip **src);
void find_stridechannel(struct Object *ob, struct bActionStrip *strip);
struct bActionStrip *convert_action_to_strip (struct Object *ob);
#endif #endif

@ -91,7 +91,8 @@ typedef struct ParticleTexture{
float ivel; /* used in reset */ float ivel; /* used in reset */
float time, life, exist, size; /* used in init */ float time, life, exist, size; /* used in init */
float pvel[3]; /* used in physics */ float pvel[3]; /* used in physics */
float length, clump, kink, rough; /* used in path caching */ float length, clump, kink, effector;/* used in path caching */
float rough1, rough2, roughe; /* used in path caching */
} ParticleTexture; } ParticleTexture;
typedef struct BoidVecFunc{ typedef struct BoidVecFunc{
@ -270,7 +271,7 @@ void psys_update_world_cos(struct Object *ob, struct ParticleSystem *psys);
int do_guide(struct Scene *scene, struct ParticleKey *state, int pa_num, float time, struct ListBase *lb); int do_guide(struct Scene *scene, struct ParticleKey *state, int pa_num, float time, struct ListBase *lb);
float psys_get_size(struct Object *ob, struct Material *ma, struct ParticleSystemModifierData *psmd, struct IpoCurve *icu_size, struct ParticleSystem *psys, struct ParticleSettings *part, struct ParticleData *pa, float *vg_size); float psys_get_size(struct Object *ob, struct Material *ma, struct ParticleSystemModifierData *psmd, struct IpoCurve *icu_size, struct ParticleSystem *psys, struct ParticleSettings *part, struct ParticleData *pa, float *vg_size);
float psys_get_timestep(struct ParticleSettings *part); float psys_get_timestep(struct ParticleSettings *part);
float psys_get_child_time(struct ParticleSystem *psys, struct ChildParticle *cpa, float cfra); float psys_get_child_time(struct ParticleSystem *psys, struct ChildParticle *cpa, float cfra, float *birthtime, float *dietime);
float psys_get_child_size(struct ParticleSystem *psys, struct ChildParticle *cpa, float cfra, float *pa_time); float psys_get_child_size(struct ParticleSystem *psys, struct ChildParticle *cpa, float cfra, float *pa_time);
void psys_get_particle_on_path(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys, int pa_num, struct ParticleKey *state, int vel); void psys_get_particle_on_path(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys, int pa_num, struct ParticleKey *state, int vel);
int psys_get_particle_state(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys, int p, struct ParticleKey *state, int always); int psys_get_particle_state(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys, int p, struct ParticleKey *state, int always);

@ -114,6 +114,7 @@ typedef struct PTCacheBaker {
struct Scene *scene; struct Scene *scene;
int bake; int bake;
int render; int render;
int anim_init;
int quick_step; int quick_step;
struct PTCacheID *pid; struct PTCacheID *pid;
int (*break_test)(void *data); int (*break_test)(void *data);

@ -91,6 +91,9 @@ typedef struct SpaceType {
/* region type definitions */ /* region type definitions */
ListBase regiontypes; ListBase regiontypes;
/* tool shelf definitions */
ListBase toolshelf;
/* read and write... */ /* read and write... */
/* default keymaps to add */ /* default keymaps to add */

@ -128,6 +128,7 @@
#define IS_EQT(a, b, c) ((a > b)? (((a-b) <= c)? 1:0) : ((((b-a) <= c)? 1:0))) #define IS_EQT(a, b, c) ((a > b)? (((a-b) <= c)? 1:0) : ((((b-a) <= c)? 1:0)))
#define IN_RANGE(a, b, c) ((b < c)? ((b<a && a<c)? 1:0) : ((c<a && a<b)? 1:0)) #define IN_RANGE(a, b, c) ((b < c)? ((b<a && a<c)? 1:0) : ((c<a && a<b)? 1:0))
#define IN_RANGE_INCL(a, b, c) ((b < c)? ((b<=a && a<=c)? 1:0) : ((c<=a && a<=b)? 1:0))
/* this weirdo pops up in two places ... */ /* this weirdo pops up in two places ... */
#if !defined(WIN32) #if !defined(WIN32)

@ -769,70 +769,23 @@ void framechange_poses_clear_unkeyed(void)
/* ************** time ****************** */ /* ************** time ****************** */
static bActionStrip *get_active_strip(Object *ob) /* Check if the given action has any keyframes */
short action_has_motion(const bAction *act)
{ {
#if 0 // XXX old animation system FCurve *fcu;
bActionStrip *strip;
if(ob->action==NULL) /* return on the first F-Curve that has some keyframes/samples defined */
return NULL; if (act) {
for (fcu= act->curves.first; fcu; fcu= fcu->next) {
if (fcu->totvert)
return 1;
}
}
for (strip=ob->nlastrips.first; strip; strip=strip->next) /* nothing found */
if(strip->flag & ACTSTRIP_ACTIVE) return 0;
break;
if(strip && strip->act==ob->action)
return strip;
#endif // XXX old animation system
return NULL;
} }
/* non clipped mapping of strip */
static float get_actionstrip_frame(bActionStrip *strip, float cframe, int invert)
{
float length, actlength, repeat, scale;
if (strip->repeat == 0.0f) strip->repeat = 1.0f;
repeat = (strip->flag & ACTSTRIP_USESTRIDE) ? (1.0f) : (strip->repeat);
if (strip->scale == 0.0f) strip->scale= 1.0f;
scale = (float)fabs(strip->scale); /* scale must be positive (for now) */
actlength = strip->actend-strip->actstart;
if (actlength == 0.0f) actlength = 1.0f;
length = repeat * scale * actlength;
/* invert = convert action-strip time to global time */
if (invert)
return length*(cframe - strip->actstart)/(repeat*actlength) + strip->start;
else
return repeat*actlength*(cframe - strip->start)/length + strip->actstart;
}
/* if the conditions match, it converts current time to strip time */
float get_action_frame(Object *ob, float cframe)
{
bActionStrip *strip= get_active_strip(ob);
if(strip)
return get_actionstrip_frame(strip, cframe, 0);
return cframe;
}
/* inverted, strip time to current time */
float get_action_frame_inv(Object *ob, float cframe)
{
bActionStrip *strip= get_active_strip(ob);
if(strip)
return get_actionstrip_frame(strip, cframe, 1);
return cframe;
}
/* Calculate the extents of given action */ /* Calculate the extents of given action */
void calc_action_range(const bAction *act, float *start, float *end, int incl_hidden) void calc_action_range(const bAction *act, float *start, float *end, int incl_hidden)
{ {

@ -786,8 +786,9 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
BLI_srandom(31415926 + psys->seed); BLI_srandom(31415926 + psys->seed);
lay= scene->lay; lay= scene->lay;
if((part->draw_as == PART_DRAW_OB && part->dup_ob) || if((psys->renderdata || part->draw_as==PART_DRAW_REND) &&
(part->draw_as == PART_DRAW_GR && part->dup_group && part->dup_group->gobject.first)) { ((part->ren_as == PART_DRAW_OB && part->dup_ob) ||
(part->ren_as == PART_DRAW_GR && part->dup_group && part->dup_group->gobject.first))) {
/* if we have a hair particle system, use the path cache */ /* if we have a hair particle system, use the path cache */
if(part->type == PART_HAIR) { if(part->type == PART_HAIR) {
@ -804,7 +805,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
psys->lattice = psys_get_lattice(scene, par, psys); psys->lattice = psys_get_lattice(scene, par, psys);
/* gather list of objects or single object */ /* gather list of objects or single object */
if(part->draw_as==PART_DRAW_GR) { if(part->ren_as==PART_DRAW_GR) {
group_handle_recalc_and_update(scene, par, part->dup_group); group_handle_recalc_and_update(scene, par, part->dup_group);
for(go=part->dup_group->gobject.first; go; go=go->next) for(go=part->dup_group->gobject.first; go; go=go->next)
@ -850,7 +851,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
size = psys_get_child_size(psys, cpa, ctime, 0); size = psys_get_child_size(psys, cpa, ctime, 0);
} }
if(part->draw_as==PART_DRAW_GR) { if(part->ren_as==PART_DRAW_GR) {
/* for groups, pick the object based on settings */ /* for groups, pick the object based on settings */
if(part->draw&PART_DRAW_RAND_GR) if(part->draw&PART_DRAW_RAND_GR)
b= BLI_rand() % totgroup; b= BLI_rand() % totgroup;
@ -894,7 +895,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
pamat[3][3]= 1.0f; pamat[3][3]= 1.0f;
} }
if(part->draw_as==PART_DRAW_GR && psys->part->draw & PART_DRAW_WHOLE_GR) { if(part->ren_as==PART_DRAW_GR && psys->part->draw & PART_DRAW_WHOLE_GR) {
for(go= part->dup_group->gobject.first, b=0; go; go= go->next, b++) { for(go= part->dup_group->gobject.first, b=0; go; go= go->next, b++) {
Mat4MulMat4(tmat, oblist[b]->obmat, pamat); Mat4MulMat4(tmat, oblist[b]->obmat, pamat);
Mat4MulFloat3((float *)tmat, size*scale); Mat4MulFloat3((float *)tmat, size*scale);
@ -930,7 +931,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
} }
/* restore objects since they were changed in where_is_object_time */ /* restore objects since they were changed in where_is_object_time */
if(part->draw_as==PART_DRAW_GR) { if(part->ren_as==PART_DRAW_GR) {
for(a=0; a<totgroup; a++) for(a=0; a<totgroup; a++)
*(oblist[a])= obcopylist[a]; *(oblist[a])= obcopylist[a];
} }

@ -1,10 +1,37 @@
/* Testing code for new animation system in 2.5 /**
* Copyright 2009, Joshua Leung * $Id$
*
* ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): Joshua Leung (full recode)
*
* ***** END GPL LICENSE BLOCK *****
*/ */
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stddef.h> #include <stddef.h>
#include <float.h>
#include <math.h>
#include "MEM_guardedalloc.h" #include "MEM_guardedalloc.h"
@ -12,9 +39,12 @@
#include "BLI_arithb.h" #include "BLI_arithb.h"
#include "BLI_dynstr.h" #include "BLI_dynstr.h"
#include "DNA_anim_types.h"
#include "BKE_animsys.h" #include "BKE_animsys.h"
#include "BKE_action.h" #include "BKE_action.h"
#include "BKE_fcurve.h" #include "BKE_fcurve.h"
#include "BKE_nla.h"
#include "BKE_global.h" #include "BKE_global.h"
#include "BKE_main.h" #include "BKE_main.h"
#include "BKE_utildefines.h" #include "BKE_utildefines.h"
@ -22,7 +52,7 @@
#include "RNA_access.h" #include "RNA_access.h"
#include "RNA_types.h" #include "RNA_types.h"
#include "DNA_anim_types.h" #include "nla_private.h"
/* ***************************************** */ /* ***************************************** */
/* AnimData API */ /* AnimData API */
@ -116,6 +146,12 @@ void BKE_free_animdata (ID *id)
/* unlink action (don't free, as it's in its own list) */ /* unlink action (don't free, as it's in its own list) */
if (adt->action) if (adt->action)
adt->action->id.us--; adt->action->id.us--;
/* same goes for the temporarily displaced action */
if (adt->tmpact)
adt->tmpact->id.us--;
/* free nla data */
free_nladata(&adt->nla_tracks);
/* free drivers - stored as a list of F-Curves */ /* free drivers - stored as a list of F-Curves */
free_fcurves(&adt->drivers); free_fcurves(&adt->drivers);
@ -146,9 +182,10 @@ AnimData *BKE_copy_animdata (AnimData *adt)
// XXX review this... it might not be optimal behaviour yet... // XXX review this... it might not be optimal behaviour yet...
//id_us_plus((ID *)dadt->action); //id_us_plus((ID *)dadt->action);
dadt->action= copy_action(adt->action); dadt->action= copy_action(adt->action);
dadt->tmpact= copy_action(adt->tmpact);
/* duplicate NLA data */ /* duplicate NLA data */
// XXX todo... copy_nladata(&dadt->nla_tracks, &adt->nla_tracks);
/* duplicate drivers (F-Curves) */ /* duplicate drivers (F-Curves) */
copy_fcurves(&dadt->drivers, &adt->drivers); copy_fcurves(&dadt->drivers, &adt->drivers);
@ -355,10 +392,10 @@ void BKE_keyingsets_free (ListBase *list)
short animsys_remap_path (AnimMapper *remap, char *path, char **dst) short animsys_remap_path (AnimMapper *remap, char *path, char **dst)
{ {
/* is there a valid remapping table to use? */ /* is there a valid remapping table to use? */
if (remap) { //if (remap) {
/* find a matching entry... to use to remap */ /* find a matching entry... to use to remap */
// ...TODO... // ...TODO...
} //}
/* nothing suitable found, so just set dst to look at path (i.e. no alloc/free needed) */ /* nothing suitable found, so just set dst to look at path (i.e. no alloc/free needed) */
*dst= path; *dst= path;
@ -455,11 +492,14 @@ static void animsys_evaluate_fcurves (PointerRNA *ptr, ListBase *list, AnimMappe
/* calculate then execute each curve */ /* calculate then execute each curve */
for (fcu= list->first; fcu; fcu= fcu->next) for (fcu= list->first; fcu; fcu= fcu->next)
{ {
/* check if this curve should be skipped */ /* check if this F-Curve doesn't belong to a muted group */
if ((fcu->flag & (FCURVE_MUTED|FCURVE_DISABLED)) == 0) if ((fcu->grp == NULL) || (fcu->grp->flag & AGRP_MUTED)==0) {
{ /* check if this curve should be skipped */
calculate_fcurve(fcu, ctime); if ((fcu->flag & (FCURVE_MUTED|FCURVE_DISABLED)) == 0)
animsys_execute_fcurve(ptr, remap, fcu); {
calculate_fcurve(fcu, ctime);
animsys_execute_fcurve(ptr, remap, fcu);
}
} }
} }
} }
@ -481,7 +521,6 @@ static void animsys_evaluate_drivers (PointerRNA *ptr, AnimData *adt, float ctim
short ok= 0; short ok= 0;
/* check if this driver's curve should be skipped */ /* check if this driver's curve should be skipped */
// FIXME: maybe we shouldn't check for muted, though that would make things more confusing, as there's already too many ways to disable?
if ((fcu->flag & (FCURVE_MUTED|FCURVE_DISABLED)) == 0) if ((fcu->flag & (FCURVE_MUTED|FCURVE_DISABLED)) == 0)
{ {
/* check if driver itself is tagged for recalculation */ /* check if driver itself is tagged for recalculation */
@ -514,6 +553,10 @@ void animsys_evaluate_action_group (PointerRNA *ptr, bAction *act, bActionGroup
if ELEM(NULL, act, agrp) return; if ELEM(NULL, act, agrp) return;
if ((remap) && (remap->target != act)) remap= NULL; if ((remap) && (remap->target != act)) remap= NULL;
/* if group is muted, don't evaluated any of the F-Curve */
if (agrp->flag & AGRP_MUTED)
return;
/* calculate then execute each curve */ /* calculate then execute each curve */
for (fcu= agrp->channels.first; (fcu) && (fcu->grp == agrp); fcu= fcu->next) for (fcu= agrp->channels.first; (fcu) && (fcu->grp == agrp); fcu= fcu->next)
{ {
@ -540,152 +583,590 @@ void animsys_evaluate_action (PointerRNA *ptr, bAction *act, AnimMapper *remap,
/* ***************************************** */ /* ***************************************** */
/* NLA System - Evaluation */ /* NLA System - Evaluation */
/* used for list of strips to accumulate at current time */ /* calculate influence of strip based for given frame based on blendin/out values */
typedef struct NlaEvalStrip { static float nlastrip_get_influence (NlaStrip *strip, float cframe)
struct NlaEvalStrip *next, *prev;
NlaTrack *track; /* track that this strip belongs to */
NlaStrip *strip; /* strip that's being used */
NlaStrip *sblend; /* strip that's being blended towards (if applicable) */
short track_index; /* the index of the track within the list */
short strip_mode; /* which end of the strip are we looking at */
} NlaEvalStrip;
/* bNlaEvalStrip->strip_mode */
enum {
NES_TIME_BEFORE = -1,
NES_TIME_WITHIN,
NES_TIME_AFTER,
NES_TIME_AFTER_BLEND
} eNlaEvalStrip_StripMode;
/* temp channel for accumulating data from NLA (avoids needing to clear all values first) */
// TODO: maybe this will be used as the 'cache' stuff needed for editable values too?
typedef struct NlaEvalChannel {
struct NlaEvalChannel *next, *prev;
char *path; /* ready-to-use path (i.e. remapped already) */
int array_index; /* if applicable... */
float value; /* value of this channel */
} NlaEvalChannel;
/* ---------------------- */
/* evaluate the F-Curves controlling settings for the NLA-strips (currently, not relinkable) */
static void nlastrip_evaluate_fcurves (NlaStrip *strip, float ctime)
{ {
//PointerRNA actstrip_ptr; /* sanity checks - normalise the blendin/out values? */
//FCurve *fcu; strip->blendin= (float)fabs(strip->blendin);
strip->blendout= (float)fabs(strip->blendout);
/* create RNA-pointer needed to set values */ /* result depends on where frame is in respect to blendin/out values */
//RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &actstrip_ptr); if (IS_EQ(strip->blendin, 0)==0 && (cframe <= (strip->start + strip->blendin))) {
/* there is some blend-in */
/* execute these settings as per normal */ return (float)fabs(cframe - strip->start) / (strip->blendin);
//animsys_evaluate_fcurves(&actstrip_ptr, &strip->fcurves, NULL, ctime); }
else if (IS_EQ(strip->blendout, 0)==0 && (cframe >= (strip->end - strip->blendout))) {
/* there is some blend-out */
return (float)fabs(strip->end - cframe) / (strip->blendout);
}
else {
/* in the middle of the strip, we should be full strength */
return 1.0f;
}
} }
/* evaluate the evaluation time and influence for the strip, storing the results in the strip */
/* gets the strip active at the current time for a track */ static void nlastrip_evaluate_controls (NlaStrip *strip, float ctime)
static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index, float ctime)
{ {
NlaStrip *strip, *astrip=NULL, *bstrip=NULL; /* firstly, analytically generate values for influence and time (if applicable) */
if ((strip->flag & NLASTRIP_FLAG_USR_TIME) == 0)
strip->strip_time= nlastrip_get_frame(strip, ctime, NLATIME_CONVERT_EVAL);
if ((strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) == 0)
strip->influence= nlastrip_get_influence(strip, ctime);
/* now strip's evaluate F-Curves for these settings (if applicable) */
if (strip->fcurves.first) {
PointerRNA strip_ptr;
/* create RNA-pointer needed to set values */
RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr);
/* execute these settings as per normal */
animsys_evaluate_fcurves(&strip_ptr, &strip->fcurves, NULL, ctime);
}
}
/* gets the strip active at the current time for a list of strips for evaluation purposes */
NlaEvalStrip *nlastrips_ctime_get_strip (ListBase *list, ListBase *strips, short index, float ctime)
{
NlaStrip *strip, *estrip=NULL;
NlaEvalStrip *nes; NlaEvalStrip *nes;
short side= 0; short side= 0;
/* skip if track is muted */
if (nlt->flag & NLATRACK_MUTED)
return;
/* loop over strips, checking if they fall within the range */ /* loop over strips, checking if they fall within the range */
for (strip= nlt->strips.first; strip; strip= strip->next) { for (strip= strips->first; strip; strip= strip->next) {
/* only consider if: /* check if current time occurs within this strip */
* - current time occurs within strip's extents if (IN_RANGE_INCL(ctime, strip->start, strip->end)) {
* - current time occurs before strip (if it is the first) /* this strip is active, so try to use it */
* - current time occurs after strip (if hold is on) estrip= strip;
* - current time occurs between strips (1st of those isn't holding) - blend!
*/
if (IN_RANGE(ctime, strip->start, strip->end)) {
astrip= strip;
side= NES_TIME_WITHIN; side= NES_TIME_WITHIN;
break; break;
} }
else if (ctime < strip->start) {
if (strip == nlt->strips.first) { /* if time occurred before current strip... */
astrip= strip; if (ctime < strip->start) {
if (strip == strips->first) {
/* before first strip - only try to use it if it extends backwards in time too */
if (strip->extendmode == NLASTRIP_EXTEND_HOLD)
estrip= strip;
/* side is 'before' regardless of whether there's a useful strip */
side= NES_TIME_BEFORE; side= NES_TIME_BEFORE;
break;
} }
else { else {
astrip= strip->prev; /* before next strip - previous strip has ended, but next hasn't begun,
* so blending mode depends on whether strip is being held or not...
* - only occurs when no transition strip added, otherwise the transition would have
* been picked up above...
*/
strip= strip->prev;
if (astrip->flag & NLASTRIP_HOLDLASTFRAME) { if (strip->extendmode != NLASTRIP_EXTEND_NOTHING)
side= NES_TIME_AFTER; estrip= strip;
break; side= NES_TIME_AFTER;
}
else {
bstrip= strip;
side= NES_TIME_AFTER_BLEND;
break;
}
} }
break;
}
/* if time occurred after current strip... */
if (ctime > strip->end) {
/* only if this is the last strip should we do anything, and only if that is being held */
if (strip == strips->last) {
if (strip->extendmode != NLASTRIP_EXTEND_NOTHING)
estrip= strip;
side= NES_TIME_AFTER;
break;
}
/* otherwise, skip... as the 'before' case will catch it more elegantly! */
} }
} }
/* check if strip has been found (and whether it has data worth considering) */ /* check if a valid strip was found
if (ELEM(NULL, astrip, astrip->act)) * - must not be muted (i.e. will have contribution
return; */
if (astrip->flag & NLASTRIP_MUTE) if ((estrip == NULL) || (estrip->flag & NLASTRIP_FLAG_MUTED))
return; return NULL;
/* check if blending between strips */ /* if ctime was not within the boundaries of the strip, clamp! */
if (side == NES_TIME_AFTER_BLEND) { switch (side) {
/* blending between strips... so calculate influence+act_time of both */ case NES_TIME_BEFORE: /* extend first frame only */
nlastrip_evaluate_fcurves(astrip, ctime); ctime= estrip->start;
nlastrip_evaluate_fcurves(bstrip, ctime); break;
case NES_TIME_AFTER: /* extend last frame only */
if ((astrip->influence <= 0.0f) && (bstrip->influence <= 0.0f)) ctime= estrip->end;
return; break;
}
else {
/* calculate/set the influence+act_time of this strip - don't consider if 0 influence */
nlastrip_evaluate_fcurves(astrip, ctime);
if (astrip->influence <= 0.0f)
return;
} }
/* evaluate strip's evaluation controls
* - skip if no influence (i.e. same effect as muting the strip)
* - negative influence is not supported yet... how would that be defined?
*/
// TODO: this sounds a bit hacky having a few isolated F-Curves stuck on some data it operates on...
nlastrip_evaluate_controls(estrip, ctime);
if (estrip->influence <= 0.0f)
return NULL;
/* allocate new eval-strip for this strip + add to stack */ /* check if strip has valid data to evaluate,
* and/or perform any additional type-specific actions
*/
switch (estrip->type) {
case NLASTRIP_TYPE_CLIP:
/* clip must have some action to evaluate */
if (estrip->act == NULL)
return NULL;
break;
case NLASTRIP_TYPE_TRANSITION:
/* there must be strips to transition from and to (i.e. prev and next required) */
if (ELEM(NULL, estrip->prev, estrip->next))
return NULL;
/* evaluate controls for the relevant extents of the bordering strips... */
nlastrip_evaluate_controls(estrip->prev, estrip->start);
nlastrip_evaluate_controls(estrip->next, estrip->end);
break;
}
/* add to list of strips we need to evaluate */
nes= MEM_callocN(sizeof(NlaEvalStrip), "NlaEvalStrip"); nes= MEM_callocN(sizeof(NlaEvalStrip), "NlaEvalStrip");
nes->track= nlt; nes->strip= estrip;
nes->strip= astrip;
nes->sblend= bstrip;
nes->track_index= index;
nes->strip_mode= side; nes->strip_mode= side;
nes->track_index= index;
nes->strip_time= estrip->strip_time;
BLI_addtail(list, nes); if (list)
BLI_addtail(list, nes);
return nes;
} }
/* ---------------------- */ /* ---------------------- */
/* evaluates the given evaluation strip */ /* find an NlaEvalChannel that matches the given criteria
// FIXME: will we need the evaluation cache table set up to blend stuff in? * - ptr and prop are the RNA data to find a match for
// TODO: only evaluate here, but flush in one go using the accumulated channels at end... */
static void nlastrip_ctime_evaluate (ListBase *channels, NlaEvalStrip *nes, float ctime) static NlaEvalChannel *nlaevalchan_find_match (ListBase *channels, PointerRNA *ptr, PropertyRNA *prop, int array_index)
{ {
// 1. (in old code) was to extract 'IPO-channels' from actions NlaEvalChannel *nec;
// 2. blend between the 'accumulated' data, and the new data
/* sanity check */
if (channels == NULL)
return NULL;
/* loop through existing channels, checking for a channel which affects the same property */
for (nec= channels->first; nec; nec= nec->next) {
/* - comparing the PointerRNA's is done by comparing the pointers
* to the actual struct the property resides in, since that all the
* other data stored in PointerRNA cannot allow us to definitively
* identify the data
*/
if ((nec->ptr.data == ptr->data) && (nec->prop == prop) && (nec->index == array_index))
return nec;
}
/* not found */
return NULL;
}
/* verify that an appropriate NlaEvalChannel for this F-Curve exists */
static NlaEvalChannel *nlaevalchan_verify (PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes, FCurve *fcu, short *newChan)
{
NlaEvalChannel *nec;
NlaStrip *strip= nes->strip;
PropertyRNA *prop;
PointerRNA new_ptr;
char *path = NULL;
short free_path=0;
/* sanity checks */
if (channels == NULL)
return NULL;
/* get RNA pointer+property info from F-Curve for more convenient handling */
/* get path, remapped as appropriate to work in its new environment */
free_path= animsys_remap_path(strip->remap, fcu->rna_path, &path);
/* a valid property must be available, and it must be animateable */
if (RNA_path_resolve(ptr, path, &new_ptr, &prop) == 0) {
if (G.f & G_DEBUG) printf("NLA Strip Eval: Cannot resolve path \n");
return NULL;
}
/* only ok if animateable */
else if (RNA_property_animateable(&new_ptr, prop) == 0) {
if (G.f & G_DEBUG) printf("NLA Strip Eval: Property not animateable \n");
return NULL;
}
/* try to find a match */
nec= nlaevalchan_find_match(channels, &new_ptr, prop, fcu->array_index);
/* allocate a new struct for this if none found */
if (nec == NULL) {
nec= MEM_callocN(sizeof(NlaEvalChannel), "NlaEvalChannel");
*newChan= 1;
BLI_addtail(channels, nec);
nec->ptr= new_ptr;
nec->prop= prop;
nec->index= fcu->array_index;
}
else
*newChan= 0;
/* we can now return */
return nec;
}
/* accumulate (i.e. blend) the given value on to the channel it affects */
static void nlaevalchan_accumulate (NlaEvalChannel *nec, NlaEvalStrip *nes, short newChan, float value)
{
NlaStrip *strip= nes->strip;
short blendmode= strip->blendmode;
float inf= strip->influence;
/* if channel is new, just store value regardless of blending factors, etc. */
if (newChan) {
nec->value= value;
return;
}
/* if this is being performed as part of transition evaluation, incorporate
* an additional weighting factor for the influence
*/
if (nes->strip_mode == NES_TIME_TRANSITION_END)
inf *= nes->strip_time;
/* premultiply the value by the weighting factor */
if (IS_EQ(inf, 0)) return;
value *= inf;
/* perform blending */
switch (blendmode) {
case NLASTRIP_MODE_ADD:
/* simply add the scaled value on to the stack */
nec->value += value;
break;
case NLASTRIP_MODE_SUBTRACT:
/* simply subtract the scaled value from the stack */
nec->value -= value;
break;
case NLASTRIP_MODE_MULTIPLY:
/* multiply the scaled value with the stack */
nec->value *= value;
break;
case NLASTRIP_MODE_REPLACE:
default: // TODO: do we really want to blend by default? it seems more uses might prefer add...
/* do linear interpolation
* - the influence of the accumulated data (elsewhere, that is called dstweight)
* is 1 - influence, since the strip's influence is srcweight
*/
nec->value= nec->value * (1.0f - inf) + value;
break;
}
}
/* accumulate the results of a temporary buffer with the results of the full-buffer */
static void nlaevalchan_buffers_accumulate (ListBase *channels, ListBase *tmp_buffer, NlaEvalStrip *nes)
{
NlaEvalChannel *nec, *necn, *necd;
/* optimise - abort if no channels */
if (tmp_buffer->first == NULL)
return;
/* accumulate results in tmp_channels buffer to the accumulation buffer */
for (nec= tmp_buffer->first; nec; nec= necn) {
/* get pointer to next channel in case we remove the current channel from the temp-buffer */
necn= nec->next;
/* try to find an existing matching channel for this setting in the accumulation buffer */
necd= nlaevalchan_find_match(channels, &nec->ptr, nec->prop, nec->index);
/* if there was a matching channel already in the buffer, accumulate to it,
* otherwise, add the current channel to the buffer for efficiency
*/
if (necd)
nlaevalchan_accumulate(necd, nes, 0, nec->value);
else {
BLI_remlink(tmp_buffer, nec);
BLI_addtail(channels, nec);
}
}
/* free temp-channels that haven't been assimilated into the buffer */
BLI_freelistN(tmp_buffer);
}
/* ---------------------- */
/* F-Modifier stack joining/separation utilities - should we generalise these for BLI_listbase.h interface? */
/* Temporarily join two lists of modifiers together, storing the result in a third list */
static void nlaeval_fmodifiers_join_stacks (ListBase *result, ListBase *list1, ListBase *list2)
{
FModifier *fcm1, *fcm2;
/* if list1 is invalid... */
if ELEM(NULL, list1, list1->first) {
if (list2 && list2->first) {
result->first= list2->first;
result->last= list2->last;
}
}
/* if list 2 is invalid... */
else if ELEM(NULL, list2, list2->first) {
result->first= list1->first;
result->last= list1->last;
}
else {
/* list1 should be added first, and list2 second, with the endpoints of these being the endpoints for result
* - the original lists must be left unchanged though, as we need that fact for restoring
*/
result->first= list1->first;
result->last= list2->last;
fcm1= list1->last;
fcm2= list2->first;
fcm1->next= fcm2;
fcm2->prev= fcm1;
}
}
/* Split two temporary lists of modifiers */
static void nlaeval_fmodifiers_split_stacks (ListBase *list1, ListBase *list2)
{
FModifier *fcm1, *fcm2;
/* if list1/2 is invalid... just skip */
if ELEM(NULL, list1, list2)
return;
if ELEM(NULL, list1->first, list2->first)
return;
/* get endpoints */
fcm1= list1->last;
fcm2= list2->first;
/* clear their links */
fcm1->next= NULL;
fcm2->prev= NULL;
}
/* ---------------------- */
/* evaluate action-clip strip */
static void nlastrip_evaluate_actionclip (PointerRNA *ptr, ListBase *channels, ListBase *modifiers, NlaEvalStrip *nes)
{
ListBase tmp_modifiers = {NULL, NULL};
NlaStrip *strip= nes->strip;
FCurve *fcu;
float evaltime;
/* join this strip's modifiers to the parent's modifiers (own modifiers first) */
nlaeval_fmodifiers_join_stacks(&tmp_modifiers, &strip->modifiers, modifiers);
/* evaluate strip's modifiers which modify time to evaluate the base curves at */
evaltime= evaluate_time_fmodifiers(&tmp_modifiers, NULL, 0.0f, strip->strip_time);
/* evaluate all the F-Curves in the action, saving the relevant pointers to data that will need to be used */
for (fcu= strip->act->curves.first; fcu; fcu= fcu->next) {
NlaEvalChannel *nec;
float value = 0.0f;
short newChan = -1;
/* check if this curve should be skipped */
if (fcu->flag & (FCURVE_MUTED|FCURVE_DISABLED))
continue;
if ((fcu->grp) && (fcu->grp->flag & AGRP_MUTED))
continue;
/* evaluate the F-Curve's value for the time given in the strip
* NOTE: we use the modified time here, since strip's F-Curve Modifiers are applied on top of this
*/
value= evaluate_fcurve(fcu, evaltime);
/* apply strip's F-Curve Modifiers on this value
* NOTE: we apply the strip's original evaluation time not the modified one (as per standard F-Curve eval)
*/
evaluate_value_fmodifiers(&tmp_modifiers, fcu, &value, strip->strip_time);
/* get an NLA evaluation channel to work with, and accumulate the evaluated value with the value(s)
* stored in this channel if it has been used already
*/
nec= nlaevalchan_verify(ptr, channels, nes, fcu, &newChan);
if (nec)
nlaevalchan_accumulate(nec, nes, newChan, value);
}
/* unlink this strip's modifiers from the parent's modifiers again */
nlaeval_fmodifiers_split_stacks(&strip->modifiers, modifiers);
}
/* evaluate transition strip */
static void nlastrip_evaluate_transition (PointerRNA *ptr, ListBase *channels, ListBase *modifiers, NlaEvalStrip *nes)
{
ListBase tmp_channels = {NULL, NULL};
ListBase tmp_modifiers = {NULL, NULL};
NlaEvalStrip tmp_nes;
NlaStrip *s1, *s2;
/* join this strip's modifiers to the parent's modifiers (own modifiers first) */
nlaeval_fmodifiers_join_stacks(&tmp_modifiers, &nes->strip->modifiers, modifiers);
/* get the two strips to operate on
* - we use the endpoints of the strips directly flanking our strip
* using these as the endpoints of the transition (destination and source)
* - these should have already been determined to be valid...
* - if this strip is being played in reverse, we need to swap these endpoints
* otherwise they will be interpolated wrong
*/
if (nes->strip->flag & NLASTRIP_FLAG_REVERSE) {
s1= nes->strip->next;
s2= nes->strip->prev;
}
else {
s1= nes->strip->prev;
s2= nes->strip->next;
}
/* prepare template for 'evaluation strip'
* - based on the transition strip's evaluation strip data
* - strip_mode is NES_TIME_TRANSITION_* based on which endpoint
* - strip_time is the 'normalised' (i.e. in-strip) time for evaluation,
* which doubles up as an additional weighting factor for the strip influences
* which allows us to appear to be 'interpolating' between the two extremes
*/
tmp_nes= *nes;
/* evaluate these strips into a temp-buffer (tmp_channels) */
// FIXME: modifier evalation here needs some work...
/* first strip */
tmp_nes.strip_mode= NES_TIME_TRANSITION_START;
tmp_nes.strip= s1;
nlastrip_evaluate_actionclip(ptr, &tmp_channels, &tmp_modifiers, &tmp_nes);
/* second strip */
tmp_nes.strip_mode= NES_TIME_TRANSITION_END;
tmp_nes.strip= s2;
nlastrip_evaluate_actionclip(ptr, &tmp_channels, &tmp_modifiers, &tmp_nes);
/* assumulate temp-buffer and full-buffer, using the 'real' strip */
nlaevalchan_buffers_accumulate(channels, &tmp_channels, nes);
/* unlink this strip's modifiers from the parent's modifiers again */
nlaeval_fmodifiers_split_stacks(&nes->strip->modifiers, modifiers);
}
/* evaluate meta-strip */
static void nlastrip_evaluate_meta (PointerRNA *ptr, ListBase *channels, ListBase *modifiers, NlaEvalStrip *nes)
{
ListBase tmp_channels = {NULL, NULL};
ListBase tmp_modifiers = {NULL, NULL};
NlaStrip *strip= nes->strip;
NlaEvalStrip *tmp_nes;
float evaltime;
/* meta-strip was calculated normally to have some time to be evaluated at
* and here we 'look inside' the meta strip, treating it as a decorated window to
* it's child strips, which get evaluated as if they were some tracks on a strip
* (but with some extra modifiers to apply).
*
* NOTE: keep this in sync with animsys_evaluate_nla()
*/
/* join this strip's modifiers to the parent's modifiers (own modifiers first) */
nlaeval_fmodifiers_join_stacks(&tmp_modifiers, &strip->modifiers, modifiers);
/* find the child-strip to evaluate */
evaltime= (nes->strip_time * (strip->end - strip->start)) + strip->start;
tmp_nes= nlastrips_ctime_get_strip(NULL, &strip->strips, -1, evaltime);
if (tmp_nes == NULL)
return;
/* evaluate child-strip into tmp_channels buffer before accumulating
* in the accumulation buffer
*/
nlastrip_evaluate(ptr, &tmp_channels, &tmp_modifiers, tmp_nes);
/* assumulate temp-buffer and full-buffer, using the 'real' strip */
nlaevalchan_buffers_accumulate(channels, &tmp_channels, nes);
/* free temp eval-strip */
MEM_freeN(tmp_nes);
/* unlink this strip's modifiers from the parent's modifiers again */
nlaeval_fmodifiers_split_stacks(&strip->modifiers, modifiers);
}
/* evaluates the given evaluation strip */
void nlastrip_evaluate (PointerRNA *ptr, ListBase *channels, ListBase *modifiers, NlaEvalStrip *nes)
{
/* actions to take depend on the type of strip */
switch (nes->strip->type) {
case NLASTRIP_TYPE_CLIP: /* action-clip */
nlastrip_evaluate_actionclip(ptr, channels, modifiers, nes);
break;
case NLASTRIP_TYPE_TRANSITION: /* transition */
nlastrip_evaluate_transition(ptr, channels, modifiers, nes);
break;
case NLASTRIP_TYPE_META: /* meta */
nlastrip_evaluate_meta(ptr, channels, modifiers, nes);
break;
}
} }
/* write the accumulated settings to */ /* write the accumulated settings to */
static void nladata_flush_channels (PointerRNA *ptr, ListBase *channels) void nladata_flush_channels (ListBase *channels)
{ {
NlaEvalChannel *nec;
/* sanity checks */
if (channels == NULL)
return;
/* for each channel with accumulated values, write its value on the property it affects */
for (nec= channels->first; nec; nec= nec->next) {
PointerRNA *ptr= &nec->ptr;
PropertyRNA *prop= nec->prop;
int array_index= nec->index;
float value= nec->value;
/* write values - see animsys_write_rna_setting() to sync the code */
switch (RNA_property_type(prop))
{
case PROP_BOOLEAN:
if (RNA_property_array_length(prop))
RNA_property_boolean_set_index(ptr, prop, array_index, (int)value);
else
RNA_property_boolean_set(ptr, prop, (int)value);
break;
case PROP_INT:
if (RNA_property_array_length(prop))
RNA_property_int_set_index(ptr, prop, array_index, (int)value);
else
RNA_property_int_set(ptr, prop, (int)value);
break;
case PROP_FLOAT:
if (RNA_property_array_length(prop))
RNA_property_float_set_index(ptr, prop, array_index, value);
else
RNA_property_float_set(ptr, prop, value);
break;
case PROP_ENUM:
RNA_property_enum_set(ptr, prop, (int)value);
break;
default:
// can't do anything with other types of property....
break;
}
}
} }
/* ---------------------- */ /* ---------------------- */
@ -703,9 +1184,26 @@ static void animsys_evaluate_nla (PointerRNA *ptr, AnimData *adt, float ctime)
ListBase echannels= {NULL, NULL}; ListBase echannels= {NULL, NULL};
NlaEvalStrip *nes; NlaEvalStrip *nes;
// TODO: need to zero out all channels used, otherwise we have problems with threadsafety
// and also when the user jumps between different times instead of moving sequentially...
/* 1. get the stack of strips to evaluate at current time (influence calculated here) */ /* 1. get the stack of strips to evaluate at current time (influence calculated here) */
for (nlt=adt->nla_tracks.first; nlt; nlt=nlt->next, track_index++) for (nlt=adt->nla_tracks.first; nlt; nlt=nlt->next, track_index++) {
nlatrack_ctime_get_strip(&estrips, nlt, track_index, ctime); /* if tweaking is on and this strip is the tweaking track, stop on this one */
if ((adt->flag & ADT_NLA_EDIT_ON) && (nlt->flag & NLATRACK_DISABLED))
break;
/* skip if we're only considering a track tagged 'solo' */
if ((adt->flag & ADT_NLA_SOLO_TRACK) && (nlt->flag & NLATRACK_SOLO)==0)
continue;
/* skip if track is muted */
if (nlt->flag & NLATRACK_MUTED)
continue;
/* otherwise, get strip to evaluate for this channel */
nes= nlastrips_ctime_get_strip(&estrips, &nlt->strips, track_index, ctime);
if (nes) nes->track= nlt;
}
/* only continue if there are strips to evaluate */ /* only continue if there are strips to evaluate */
if (estrips.first == NULL) if (estrips.first == NULL)
@ -714,10 +1212,10 @@ static void animsys_evaluate_nla (PointerRNA *ptr, AnimData *adt, float ctime)
/* 2. for each strip, evaluate then accumulate on top of existing channels, but don't set values yet */ /* 2. for each strip, evaluate then accumulate on top of existing channels, but don't set values yet */
for (nes= estrips.first; nes; nes= nes->next) for (nes= estrips.first; nes; nes= nes->next)
nlastrip_ctime_evaluate(&echannels, nes, ctime); nlastrip_evaluate(ptr, &echannels, NULL, nes);
/* 3. flush effects of accumulating channels in NLA to the actual data they affect */ /* 3. flush effects of accumulating channels in NLA to the actual data they affect */
nladata_flush_channels(ptr, &echannels); nladata_flush_channels(&echannels);
/* 4. free temporary evaluation data */ /* 4. free temporary evaluation data */
BLI_freelistN(&estrips); BLI_freelistN(&estrips);
@ -799,17 +1297,23 @@ void BKE_animsys_evaluate_animdata (ID *id, AnimData *adt, float ctime, short re
* - NLA before Active Action, as Active Action behaves as 'tweaking track' * - NLA before Active Action, as Active Action behaves as 'tweaking track'
* that overrides 'rough' work in NLA * that overrides 'rough' work in NLA
*/ */
// TODO: need to double check that this all works correctly
if ((recalc & ADT_RECALC_ANIM) || (adt->recalc & ADT_RECALC_ANIM)) if ((recalc & ADT_RECALC_ANIM) || (adt->recalc & ADT_RECALC_ANIM))
{ {
/* evaluate NLA data */ /* evaluate NLA data */
if ((adt->nla_tracks.first) && !(adt->flag & ADT_NLA_EVAL_OFF)) if ((adt->nla_tracks.first) && !(adt->flag & ADT_NLA_EVAL_OFF))
{ {
/* evaluate NLA-stack */
animsys_evaluate_nla(&id_ptr, adt, ctime); animsys_evaluate_nla(&id_ptr, adt, ctime);
}
/* evaluate Action data */ /* evaluate 'active' Action (may be tweaking track) on top of results of NLA-evaluation
// FIXME: what if the solo track was not tweaking one, then nla-solo should be checked too? * - only do this if we're not exclusively evaluating the 'solo' NLA-track
if (adt->action) */
if ((adt->action) && !(adt->flag & ADT_NLA_SOLO_TRACK))
animsys_evaluate_action(&id_ptr, adt->action, adt->remap, ctime);
}
/* evaluate Active Action only */
else if (adt->action)
animsys_evaluate_action(&id_ptr, adt->action, adt->remap, ctime); animsys_evaluate_action(&id_ptr, adt->action, adt->remap, ctime);
/* reset tag */ /* reset tag */
@ -876,10 +1380,22 @@ void BKE_animsys_evaluate_all_animation (Main *main, float ctime)
EVAL_ANIM_IDS(main->camera.first, ADT_RECALC_ANIM); EVAL_ANIM_IDS(main->camera.first, ADT_RECALC_ANIM);
/* shapekeys */ /* shapekeys */
// TODO: we probably need the same hack as for curves (ctime-hack)
EVAL_ANIM_IDS(main->key.first, ADT_RECALC_ANIM); EVAL_ANIM_IDS(main->key.first, ADT_RECALC_ANIM);
/* curves */ /* curves */
// TODO... /* we need to perform a special hack here to ensure that the ctime
* value of the curve gets set in case there's no animation for that
* - it needs to be set before animation is evaluated just so that
* animation can successfully override...
*/
for (id= main->curve.first; id; id= id->next) {
AnimData *adt= BKE_animdata_from_id(id);
Curve *cu= (Curve *)id;
cu->ctime= ctime;
BKE_animsys_evaluate_animdata(id, adt, ctime, ADT_RECALC_ANIM);
}
/* meshes */ /* meshes */
// TODO... // TODO...

@ -341,24 +341,27 @@ void bvhselftree_update_from_cloth(ClothModifierData *clmd, int moving)
} }
int modifiers_indexInObject(Object *ob, ModifierData *md_seek); int modifiers_indexInObject(Object *ob, ModifierData *md_seek);
static void cloth_write_state(int index, Cloth *cloth, float *data) static void cloth_write_state(int index, void *cloth_v, float *data)
{ {
Cloth *cloth= cloth_v;
ClothVertex *vert = cloth->verts + index; ClothVertex *vert = cloth->verts + index;
memcpy(data, vert->x, 3 * sizeof(float)); memcpy(data, vert->x, 3 * sizeof(float));
memcpy(data + 3, vert->xconst, 3 * sizeof(float)); memcpy(data + 3, vert->xconst, 3 * sizeof(float));
memcpy(data + 6, vert->v, 3 * sizeof(float)); memcpy(data + 6, vert->v, 3 * sizeof(float));
} }
static void cloth_read_state(int index, Cloth *cloth, float *data) static void cloth_read_state(int index, void *cloth_v, float *data)
{ {
Cloth *cloth= cloth_v;
ClothVertex *vert = cloth->verts + index; ClothVertex *vert = cloth->verts + index;
memcpy(vert->x, data, 3 * sizeof(float)); memcpy(vert->x, data, 3 * sizeof(float));
memcpy(vert->xconst, data + 3, 3 * sizeof(float)); memcpy(vert->xconst, data + 3, 3 * sizeof(float));
memcpy(vert->v, data + 6, 3 * sizeof(float)); memcpy(vert->v, data + 6, 3 * sizeof(float));
} }
static void cloth_cache_interpolate(int index, Cloth *cloth, float frs_sec, float cfra, float cfra1, float cfra2, float *data1, float *data2) static void cloth_cache_interpolate(int index, void *cloth_v, float frs_sec, float cfra, float cfra1, float cfra2, float *data1, float *data2)
{ {
Cloth *cloth= cloth_v;
ClothVertex *vert = cloth->verts + index; ClothVertex *vert = cloth->verts + index;
ParticleKey keys[4]; ParticleKey keys[4];
float dfra; float dfra;

@ -378,7 +378,7 @@ PointerRNA CTX_data_pointer_get_type(const bContext *C, const char *member, Stru
{ {
PointerRNA ptr = CTX_data_pointer_get(C, member); PointerRNA ptr = CTX_data_pointer_get(C, member);
if(ptr.data && ptr.type == type) if(ptr.data && RNA_struct_is_a(ptr.type, type))
return ptr; return ptr;
return PointerRNA_NULL; return PointerRNA_NULL;

@ -568,14 +568,14 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA, "Particle Keyed Physics"); dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA, "Particle Keyed Physics");
} }
if(part->draw_as == PART_DRAW_OB && part->dup_ob) { if(part->ren_as == PART_DRAW_OB && part->dup_ob) {
node2 = dag_get_node(dag, part->dup_ob); node2 = dag_get_node(dag, part->dup_ob);
dag_add_relation(dag, node, node2, DAG_RL_OB_OB, "Particle Object Visualisation"); dag_add_relation(dag, node, node2, DAG_RL_OB_OB, "Particle Object Visualisation");
if(part->dup_ob->type == OB_MBALL) if(part->dup_ob->type == OB_MBALL)
dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA, "Particle Object Visualisation"); dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA, "Particle Object Visualisation");
} }
if(part->draw_as == PART_DRAW_GR && part->dup_group) { if(part->ren_as == PART_DRAW_GR && part->dup_group) {
for(go=part->dup_group->gobject.first; go; go=go->next) { for(go=part->dup_group->gobject.first; go; go=go->next) {
node2 = dag_get_node(dag, go->ob); node2 = dag_get_node(dag, go->ob);
dag_add_relation(dag, node, node2, DAG_RL_OB_OB, "Particle Group Visualisation"); dag_add_relation(dag, node, node2, DAG_RL_OB_OB, "Particle Group Visualisation");

@ -56,6 +56,8 @@
#include "BLI_jitter.h" #include "BLI_jitter.h"
#include "BLI_rand.h" #include "BLI_rand.h"
#include "PIL_time.h"
#include "BKE_action.h" #include "BKE_action.h"
#include "BKE_anim.h" /* needed for where_on_path */ #include "BKE_anim.h" /* needed for where_on_path */
#include "BKE_armature.h" #include "BKE_armature.h"
@ -93,6 +95,20 @@
//XXX #include "BIF_screen.h" //XXX #include "BIF_screen.h"
PartDeflect *object_add_collision_fields(void)
{
PartDeflect *pd;
pd= MEM_callocN(sizeof(PartDeflect), "PartDeflect");
pd->pdef_sbdamp = 0.1f;
pd->pdef_sbift = 0.2f;
pd->pdef_sboft = 0.02f;
pd->seed = ((unsigned int)(ceil(PIL_check_seconds_timer()))+1) % 128;
return pd;
}
/* temporal struct, used for reading return of mesh_get_mapped_verts_nors() */ /* temporal struct, used for reading return of mesh_get_mapped_verts_nors() */
typedef struct VeNoCo { typedef struct VeNoCo {

File diff suppressed because it is too large Load Diff

@ -34,7 +34,9 @@
#include "DNA_mesh_types.h" #include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h" #include "DNA_meshdata_types.h"
#include "DNA_object_fluidsim.h"
#include "DNA_object_force.h" // for pointcache #include "DNA_object_force.h" // for pointcache
#include "DNA_object_types.h"
#include "DNA_particle_types.h" #include "DNA_particle_types.h"
#include "DNA_scene_types.h" // N_T #include "DNA_scene_types.h" // N_T
@ -78,7 +80,7 @@ void fluidsim_init(FluidsimModifierData *fluidmd)
if(!fss) if(!fss)
return; return;
fss->type = OB_FSBND_NOSLIP; fss->type = OB_FLUIDSIM_ENABLE;
fss->show_advancedoptions = 0; fss->show_advancedoptions = 0;
fss->resolutionxyz = 50; fss->resolutionxyz = 50;
@ -112,7 +114,7 @@ void fluidsim_init(FluidsimModifierData *fluidmd)
// no bounding box needed // no bounding box needed
// todo - reuse default init from elbeem! // todo - reuse default init from elbeem!
fss->typeFlags = 0; fss->typeFlags = OB_FSBND_NOSLIP;
fss->domainNovecgen = 0; fss->domainNovecgen = 0;
fss->volumeInitType = 1; // volume fss->volumeInitType = 1; // volume
fss->partSlipValue = 0.0; fss->partSlipValue = 0.0;
@ -657,5 +659,20 @@ void initElbeemMesh(struct Scene *scene, struct Object *ob,
dm->release(dm); dm->release(dm);
} }
void fluid_estimate_memory(Object *ob, FluidsimSettings *fss, char *value)
{
Mesh *mesh;
value[0]= '\0';
if(ob->type == OB_MESH) {
/* use mesh bounding box and object scaling */
mesh= ob->data;
fluid_get_bb(mesh->mvert, mesh->totvert, ob->obmat, fss->bbStart, fss->bbSize);
elbeemEstimateMemreq(fss->resolutionxyz, fss->bbSize[0],fss->bbSize[1],fss->bbSize[2], fss->maxRefine, value);
}
}
#endif // DISABLE_ELBEEM #endif // DISABLE_ELBEEM

File diff suppressed because it is too large Load Diff

@ -253,6 +253,10 @@ void free_image(Image *ima)
if (ima->preview) { if (ima->preview) {
BKE_previewimg_free(&ima->preview); BKE_previewimg_free(&ima->preview);
} }
if (ima->render_text) {
MEM_freeN(ima->render_text);
ima->render_text= NULL;
}
} }
/* only image block itself */ /* only image block itself */

@ -58,6 +58,7 @@
#include "DNA_key_types.h" #include "DNA_key_types.h"
#include "DNA_material_types.h" #include "DNA_material_types.h"
#include "DNA_mesh_types.h" #include "DNA_mesh_types.h"
#include "DNA_nla_types.h"
#include "DNA_object_types.h" #include "DNA_object_types.h"
#include "DNA_object_force.h" #include "DNA_object_force.h"
#include "DNA_particle_types.h" #include "DNA_particle_types.h"
@ -85,6 +86,7 @@
#include "BKE_library.h" #include "BKE_library.h"
#include "BKE_main.h" #include "BKE_main.h"
#include "BKE_mesh.h" #include "BKE_mesh.h"
#include "BKE_nla.h"
#include "BKE_object.h" #include "BKE_object.h"
@ -825,6 +827,10 @@ char *get_rna_access (int blocktype, int adrcode, char actname[], char constname
char buf[512]; char buf[512];
int dummy_index= 0; int dummy_index= 0;
/* hack: if constname is set, we can only be dealing with an Constraint curve */
if (constname)
blocktype= ID_CO;
/* get property name based on blocktype */ /* get property name based on blocktype */
switch (blocktype) { switch (blocktype) {
case ID_OB: /* object */ case ID_OB: /* object */
@ -870,7 +876,10 @@ char *get_rna_access (int blocktype, int adrcode, char actname[], char constname
/* XXX problematic blocktypes */ /* XXX problematic blocktypes */
case ID_CU: /* curve */ case ID_CU: /* curve */
propname= "speed"; // XXX this was a 'dummy curve' that didn't really correspond to any real var... /* this used to be a 'dummy' curve which got evaluated on the fly...
* now we've got real var for this!
*/
propname= "eval_time";
break; break;
case ID_SEQ: /* sequencer strip */ case ID_SEQ: /* sequencer strip */
@ -1144,7 +1153,7 @@ static void icu_to_fcurves (ListBase *groups, ListBase *list, IpoCurve *icu, cha
/* Add a new FModifier (Cyclic) instead of setting extend value /* Add a new FModifier (Cyclic) instead of setting extend value
* as that's the new equivilant of that option. * as that's the new equivilant of that option.
*/ */
FModifier *fcm= fcurve_add_modifier(fcu, FMODIFIER_TYPE_CYCLES); FModifier *fcm= add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_CYCLES);
FMod_Cycles *data= (FMod_Cycles *)fcm->data; FMod_Cycles *data= (FMod_Cycles *)fcm->data;
/* if 'offset' one is in use, set appropriate settings */ /* if 'offset' one is in use, set appropriate settings */
@ -1463,6 +1472,87 @@ static void action_to_animdata (ID *id, bAction *act)
action_to_animato(act, &adt->action->groups, &adt->action->curves, &adt->drivers); action_to_animato(act, &adt->action->groups, &adt->action->curves, &adt->drivers);
} }
/* ------------------------- */
// TODO:
// - NLA group duplicators info
// - NLA curve/stride modifiers...
/* Convert NLA-Strip to new system */
static void nlastrips_to_animdata (ID *id, ListBase *strips)
{
AnimData *adt= BKE_animdata_from_id(id);
NlaTrack *nlt = NULL;
NlaStrip *strip;
bActionStrip *as, *asn;
/* for each one of the original strips, convert to a new strip and free the old... */
for (as= strips->first; as; as= asn) {
asn= as->next;
/* this old strip is only worth something if it had an action... */
if (as->act) {
/* convert Action data (if not yet converted), storing the results in the same Action */
action_to_animato(as->act, &as->act->groups, &as->act->curves, &adt->drivers);
/* create a new-style NLA-strip which references this Action, then copy over relevant settings */
{
/* init a new strip, and assign the action to it
* - no need to muck around with the user-counts, since this is just
* passing over the ref to the new owner, not creating an additional ref
*/
strip= MEM_callocN(sizeof(NlaStrip), "NlaStrip");
strip->act= as->act;
/* endpoints */
strip->start= as->start;
strip->end= as->end;
strip->actstart= as->actstart;
strip->actend= as->actend;
/* action reuse */
strip->repeat= as->repeat;
strip->scale= as->scale;
if (as->flag & ACTSTRIP_LOCK_ACTION) strip->flag |= NLASTRIP_FLAG_SYNC_LENGTH;
/* blending */
strip->blendin= as->blendin;
strip->blendout= as->blendout;
strip->blendmode= (as->mode==ACTSTRIPMODE_ADD) ? NLASTRIP_MODE_ADD : NLASTRIP_MODE_REPLACE;
if (as->flag & ACTSTRIP_AUTO_BLENDS) strip->flag |= NLASTRIP_FLAG_AUTO_BLENDS;
/* assorted setting flags */
if (as->flag & ACTSTRIP_SELECT) strip->flag |= NLASTRIP_FLAG_SELECT;
if (as->flag & ACTSTRIP_ACTIVE) strip->flag |= NLASTRIP_FLAG_ACTIVE;
if (as->flag & ACTSTRIP_MUTE) strip->flag |= NLASTRIP_FLAG_MUTED;
if (as->flag & ACTSTRIP_REVERSE) strip->flag |= NLASTRIP_FLAG_REVERSE;
/* by default, we now always extrapolate, while in the past this was optional */
if ((as->flag & ACTSTRIP_HOLDLASTFRAME)==0)
strip->extendmode= NLASTRIP_EXTEND_NOTHING;
}
/* try to add this strip to the current NLA-Track (i.e. the 'last' one on the stack atm) */
if (BKE_nlatrack_add_strip(nlt, strip) == 0) {
/* trying to add to the current failed (no space),
* so add a new track to the stack, and add to that...
*/
nlt= add_nlatrack(adt, NULL);
BKE_nlatrack_add_strip(nlt, strip);
}
}
/* modifiers */
// FIXME: for now, we just free them...
if (as->modifiers.first)
BLI_freelistN(&as->modifiers);
/* free the old strip */
BLI_freelinkN(strips, as);
}
}
/* *************************************************** */ /* *************************************************** */
/* External API - Only Called from do_versions() */ /* External API - Only Called from do_versions() */
@ -1509,7 +1599,30 @@ void do_versions_ipos_to_animato(Main *main)
if (G.f & G_DEBUG) printf("\tconverting ob %s \n", id->name+2); if (G.f & G_DEBUG) printf("\tconverting ob %s \n", id->name+2);
/* check if object has any animation data */ /* check if object has any animation data */
if ((ob->ipo) || (ob->action) || (ob->nlastrips.first)) { if (ob->nlastrips.first) {
/* Add AnimData block */
adt= BKE_id_add_animdata(id);
/* IPO first to take into any non-NLA'd Object Animation */
if (ob->ipo) {
ipo_to_animdata(id, ob->ipo, NULL, NULL);
ob->ipo->id.us--;
ob->ipo= NULL;
}
/* Action is skipped since it'll be used by some strip in the NLA anyway,
* causing errors with evaluation in the new evaluation pipeline
*/
if (ob->action) {
ob->action->id.us--;
ob->action= NULL;
}
/* finally NLA */
nlastrips_to_animdata(id, &ob->nlastrips);
}
else if ((ob->ipo) || (ob->action)) {
/* Add AnimData block */ /* Add AnimData block */
adt= BKE_id_add_animdata(id); adt= BKE_id_add_animdata(id);
@ -1530,9 +1643,6 @@ void do_versions_ipos_to_animato(Main *main)
ob->ipo->id.us--; ob->ipo->id.us--;
ob->ipo= NULL; ob->ipo= NULL;
} }
/* finally NLA */
// XXX todo... for now, new NLA code not hooked up yet, so keep old stuff (but not for too long!)
} }
/* check PoseChannels for constraints with local data */ /* check PoseChannels for constraints with local data */

@ -232,8 +232,8 @@ void free_lattice(Lattice *lt)
if(lt->def) MEM_freeN(lt->def); if(lt->def) MEM_freeN(lt->def);
if(lt->dvert) free_dverts(lt->dvert, lt->pntsu*lt->pntsv*lt->pntsw); if(lt->dvert) free_dverts(lt->dvert, lt->pntsu*lt->pntsv*lt->pntsw);
if(lt->editlatt) { if(lt->editlatt) {
if(lt->def) MEM_freeN(lt->def); if(lt->editlatt->def) MEM_freeN(lt->editlatt->def);
if(lt->dvert) free_dverts(lt->dvert, lt->pntsu*lt->pntsv*lt->pntsw); if(lt->editlatt->dvert) free_dverts(lt->editlatt->dvert, lt->pntsu*lt->pntsv*lt->pntsw);
MEM_freeN(lt->editlatt); MEM_freeN(lt->editlatt);
} }
} }
@ -817,59 +817,68 @@ void outside_lattice(Lattice *lt)
int u, v, w; int u, v, w;
float fac1, du=0.0, dv=0.0, dw=0.0; float fac1, du=0.0, dv=0.0, dw=0.0;
bp= lt->def; if(lt->flag & LT_OUTSIDE) {
bp= lt->def;
if(lt->pntsu>1) du= 1.0f/((float)lt->pntsu-1); if(lt->pntsu>1) du= 1.0f/((float)lt->pntsu-1);
if(lt->pntsv>1) dv= 1.0f/((float)lt->pntsv-1); if(lt->pntsv>1) dv= 1.0f/((float)lt->pntsv-1);
if(lt->pntsw>1) dw= 1.0f/((float)lt->pntsw-1); if(lt->pntsw>1) dw= 1.0f/((float)lt->pntsw-1);
for(w=0; w<lt->pntsw; w++) { for(w=0; w<lt->pntsw; w++) {
for(v=0; v<lt->pntsv; v++) { for(v=0; v<lt->pntsv; v++) {
for(u=0; u<lt->pntsu; u++, bp++) { for(u=0; u<lt->pntsu; u++, bp++) {
if(u==0 || v==0 || w==0 || u==lt->pntsu-1 || v==lt->pntsv-1 || w==lt->pntsw-1); if(u==0 || v==0 || w==0 || u==lt->pntsu-1 || v==lt->pntsv-1 || w==lt->pntsw-1);
else { else {
bp->hide= 1; bp->hide= 1;
bp->f1 &= ~SELECT; bp->f1 &= ~SELECT;
/* u extrema */ /* u extrema */
bp1= latt_bp(lt, 0, v, w); bp1= latt_bp(lt, 0, v, w);
bp2= latt_bp(lt, lt->pntsu-1, v, w); bp2= latt_bp(lt, lt->pntsu-1, v, w);
fac1= du*u; fac1= du*u;
bp->vec[0]= (1.0f-fac1)*bp1->vec[0] + fac1*bp2->vec[0]; bp->vec[0]= (1.0f-fac1)*bp1->vec[0] + fac1*bp2->vec[0];
bp->vec[1]= (1.0f-fac1)*bp1->vec[1] + fac1*bp2->vec[1]; bp->vec[1]= (1.0f-fac1)*bp1->vec[1] + fac1*bp2->vec[1];
bp->vec[2]= (1.0f-fac1)*bp1->vec[2] + fac1*bp2->vec[2]; bp->vec[2]= (1.0f-fac1)*bp1->vec[2] + fac1*bp2->vec[2];
/* v extrema */ /* v extrema */
bp1= latt_bp(lt, u, 0, w); bp1= latt_bp(lt, u, 0, w);
bp2= latt_bp(lt, u, lt->pntsv-1, w); bp2= latt_bp(lt, u, lt->pntsv-1, w);
fac1= dv*v; fac1= dv*v;
bp->vec[0]+= (1.0f-fac1)*bp1->vec[0] + fac1*bp2->vec[0]; bp->vec[0]+= (1.0f-fac1)*bp1->vec[0] + fac1*bp2->vec[0];
bp->vec[1]+= (1.0f-fac1)*bp1->vec[1] + fac1*bp2->vec[1]; bp->vec[1]+= (1.0f-fac1)*bp1->vec[1] + fac1*bp2->vec[1];
bp->vec[2]+= (1.0f-fac1)*bp1->vec[2] + fac1*bp2->vec[2]; bp->vec[2]+= (1.0f-fac1)*bp1->vec[2] + fac1*bp2->vec[2];
/* w extrema */ /* w extrema */
bp1= latt_bp(lt, u, v, 0); bp1= latt_bp(lt, u, v, 0);
bp2= latt_bp(lt, u, v, lt->pntsw-1); bp2= latt_bp(lt, u, v, lt->pntsw-1);
fac1= dw*w; fac1= dw*w;
bp->vec[0]+= (1.0f-fac1)*bp1->vec[0] + fac1*bp2->vec[0]; bp->vec[0]+= (1.0f-fac1)*bp1->vec[0] + fac1*bp2->vec[0];
bp->vec[1]+= (1.0f-fac1)*bp1->vec[1] + fac1*bp2->vec[1]; bp->vec[1]+= (1.0f-fac1)*bp1->vec[1] + fac1*bp2->vec[1];
bp->vec[2]+= (1.0f-fac1)*bp1->vec[2] + fac1*bp2->vec[2]; bp->vec[2]+= (1.0f-fac1)*bp1->vec[2] + fac1*bp2->vec[2];
VecMulf(bp->vec, 0.3333333f); VecMulf(bp->vec, 0.3333333f);
}
} }
} }
} }
} }
else {
bp= lt->def;
for(w=0; w<lt->pntsw; w++)
for(v=0; v<lt->pntsv; v++)
for(u=0; u<lt->pntsu; u++, bp++)
bp->hide= 0;
}
} }
float (*lattice_getVertexCos(struct Object *ob, int *numVerts_r))[3] float (*lattice_getVertexCos(struct Object *ob, int *numVerts_r))[3]

@ -63,6 +63,7 @@
#include "DNA_meshdata_types.h" #include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h" #include "DNA_modifier_types.h"
#include "DNA_object_types.h" #include "DNA_object_types.h"
#include "DNA_object_fluidsim.h"
#include "DNA_object_force.h" #include "DNA_object_force.h"
#include "DNA_particle_types.h" #include "DNA_particle_types.h"
#include "DNA_scene_types.h" #include "DNA_scene_types.h"
@ -6389,6 +6390,7 @@ static void particleSystemModifier_deformVerts(
} }
if(psys){ if(psys){
psmd->flag &= ~eParticleSystemFlag_psys_updated;
particle_system_update(md->scene, ob, psys); particle_system_update(md->scene, ob, psys);
psmd->flag |= eParticleSystemFlag_psys_updated; psmd->flag |= eParticleSystemFlag_psys_updated;
psmd->flag &= ~eParticleSystemFlag_DM_changed; psmd->flag &= ~eParticleSystemFlag_DM_changed;
@ -6420,6 +6422,8 @@ static void particleInstanceModifier_initData(ModifierData *md)
pimd->flag = eParticleInstanceFlag_Parents|eParticleInstanceFlag_Unborn| pimd->flag = eParticleInstanceFlag_Parents|eParticleInstanceFlag_Unborn|
eParticleInstanceFlag_Alive|eParticleInstanceFlag_Dead; eParticleInstanceFlag_Alive|eParticleInstanceFlag_Dead;
pimd->psys = 1; pimd->psys = 1;
pimd->position = 1.0f;
pimd->axis = 2;
} }
static void particleInstanceModifier_copyData(ModifierData *md, ModifierData *target) static void particleInstanceModifier_copyData(ModifierData *md, ModifierData *target)
@ -6430,6 +6434,8 @@ static void particleInstanceModifier_copyData(ModifierData *md, ModifierData *ta
tpimd->ob = pimd->ob; tpimd->ob = pimd->ob;
tpimd->psys = pimd->psys; tpimd->psys = pimd->psys;
tpimd->flag = pimd->flag; tpimd->flag = pimd->flag;
tpimd->position = pimd->position;
tpimd->random_position = pimd->random_position;
} }
static int particleInstanceModifier_dependsOnTime(ModifierData *md) static int particleInstanceModifier_dependsOnTime(ModifierData *md)
@ -6469,8 +6475,9 @@ static DerivedMesh * particleInstanceModifier_applyModifier(
MFace *mface, *orig_mface; MFace *mface, *orig_mface;
MVert *mvert, *orig_mvert; MVert *mvert, *orig_mvert;
int i,totvert, totpart=0, totface, maxvert, maxface, first_particle=0; int i,totvert, totpart=0, totface, maxvert, maxface, first_particle=0;
short track=ob->trackflag%3, trackneg; short track=ob->trackflag%3, trackneg, axis = pimd->axis;
float max_co=0.0, min_co=0.0, temp_co[3], cross[3]; float max_co=0.0, min_co=0.0, temp_co[3], cross[3];
float *size=NULL;
trackneg=((ob->trackflag>2)?1:0); trackneg=((ob->trackflag>2)?1:0);
@ -6497,6 +6504,25 @@ static DerivedMesh * particleInstanceModifier_applyModifier(
if(totpart==0) if(totpart==0)
return derivedData; return derivedData;
if(pimd->flag & eParticleInstanceFlag_UseSize) {
int p;
float *si;
si = size = MEM_callocN(totpart * sizeof(float), "particle size array");
if(pimd->flag & eParticleInstanceFlag_Parents) {
for(p=0, pa= psys->particles; p<psys->totpart; p++, pa++, si++)
*si = pa->size;
}
if(pimd->flag & eParticleInstanceFlag_Children) {
ChildParticle *cpa = psys->child;
for(p=0; p<psys->totchild; p++, cpa++, si++) {
*si = psys_get_child_size(psys, cpa, 0.0f, NULL);
}
}
}
pars=psys->particles; pars=psys->particles;
totvert=dm->getNumVerts(dm); totvert=dm->getNumVerts(dm);
@ -6507,7 +6533,7 @@ static DerivedMesh * particleInstanceModifier_applyModifier(
psys->lattice=psys_get_lattice(md->scene, ob, psys); psys->lattice=psys_get_lattice(md->scene, ob, psys);
if(psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED)){ if(psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED){
float min_r[3], max_r[3]; float min_r[3], max_r[3];
INIT_MINMAX(min_r, max_r); INIT_MINMAX(min_r, max_r);
@ -6532,40 +6558,59 @@ static DerivedMesh * particleInstanceModifier_applyModifier(
/*change orientation based on object trackflag*/ /*change orientation based on object trackflag*/
VECCOPY(temp_co,mv->co); VECCOPY(temp_co,mv->co);
mv->co[0]=temp_co[track]; mv->co[axis]=temp_co[track];
mv->co[1]=temp_co[(track+1)%3]; mv->co[(axis+1)%3]=temp_co[(track+1)%3];
mv->co[2]=temp_co[(track+2)%3]; mv->co[(axis+2)%3]=temp_co[(track+2)%3];
if((psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) && pimd->flag & eParticleInstanceFlag_Path){
float ran = 0.0f;
if(pimd->random_position != 0.0f) {
/* just use some static collection of random numbers */
/* TODO: use something else that's unique to each instanced object */
pa = psys->particles + (i/totvert)%totpart;
ran = pimd->random_position * 0.5 * (1.0f + pa->r_ave[0]);
}
if(pimd->flag & eParticleInstanceFlag_KeepShape) {
state.time = pimd->position * (1.0f - ran);
}
else {
state.time=(mv->co[axis]-min_co)/(max_co-min_co) * pimd->position * (1.0f - ran);
if(trackneg)
state.time=1.0f-state.time;
mv->co[axis] = 0.0;
}
if(psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED) && pimd->flag & eParticleInstanceFlag_Path){
state.time=(mv->co[0]-min_co)/(max_co-min_co);
if(trackneg)
state.time=1.0f-state.time;
psys_get_particle_on_path(md->scene, pimd->ob, psys,first_particle + i/totvert, &state,1); psys_get_particle_on_path(md->scene, pimd->ob, psys,first_particle + i/totvert, &state,1);
mv->co[0] = 0.0;
Normalize(state.vel); Normalize(state.vel);
if(state.vel[0] < -0.9999 || state.vel[0] > 0.9999) { /* TODO: incremental rotations somehow */
state.rot[0] = 1.0; if(state.vel[axis] < -0.9999 || state.vel[axis] > 0.9999) {
state.rot[0] = 1;
state.rot[1] = state.rot[2] = state.rot[3] = 0.0f; state.rot[1] = state.rot[2] = state.rot[3] = 0.0f;
} }
else { else {
/* a cross product of state.vel and a unit vector in x-direction */ float temp[3] = {0.0f,0.0f,0.0f};
cross[0] = 0.0f; temp[axis] = 1.0f;
cross[1] = -state.vel[2];
cross[2] = state.vel[1];
/* state.vel[0] is the only component surviving from a dot product with a vector in x-direction*/ Crossf(cross, temp, state.vel);
VecRotToQuat(cross,saacos(state.vel[0]),state.rot);
/* state.vel[axis] is the only component surviving from a dot product with the axis */
VecRotToQuat(cross,saacos(state.vel[axis]),state.rot);
} }
} }
else{ else{
state.time=-1.0; state.time=-1.0;
psys_get_particle_state(md->scene, pimd->ob, psys, i/totvert, &state,1); psys_get_particle_state(md->scene, pimd->ob, psys, first_particle + i/totvert, &state,1);
} }
QuatMulVecf(state.rot,mv->co); QuatMulVecf(state.rot,mv->co);
if(pimd->flag & eParticleInstanceFlag_UseSize)
VecMulf(mv->co, size[i/totvert]);
VECADD(mv->co,mv->co,state.co); VECADD(mv->co,mv->co,state.co);
} }
@ -6618,6 +6663,9 @@ static DerivedMesh * particleInstanceModifier_applyModifier(
psys->lattice= NULL; psys->lattice= NULL;
} }
if(size)
MEM_freeN(size);
return result; return result;
} }
static DerivedMesh *particleInstanceModifier_applyModifierEM( static DerivedMesh *particleInstanceModifier_applyModifierEM(
@ -7256,10 +7304,10 @@ static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd,
timestep= psys_get_timestep(part); timestep= psys_get_timestep(part);
if(part->flag & PART_GLOB_TIME) //if(part->flag & PART_GLOB_TIME)
cfra=bsystem_time(scene, 0,(float)scene->r.cfra,0.0); cfra=bsystem_time(scene, 0,(float)scene->r.cfra,0.0);
else //else
cfra=bsystem_time(scene, ob,(float)scene->r.cfra,0.0); // cfra=bsystem_time(scene, ob,(float)scene->r.cfra,0.0);
/* hash table for vertice <-> particle relations */ /* hash table for vertice <-> particle relations */
vertpahash= BLI_edgehash_new(); vertpahash= BLI_edgehash_new();
@ -8387,7 +8435,8 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type)
mti = INIT_TYPE(Softbody); mti = INIT_TYPE(Softbody);
mti->type = eModifierTypeType_OnlyDeform; mti->type = eModifierTypeType_OnlyDeform;
mti->flags = eModifierTypeFlag_AcceptsCVs mti->flags = eModifierTypeFlag_AcceptsCVs
| eModifierTypeFlag_RequiresOriginalData; | eModifierTypeFlag_RequiresOriginalData
| eModifierTypeFlag_Single;
mti->deformVerts = softbodyModifier_deformVerts; mti->deformVerts = softbodyModifier_deformVerts;
mti->dependsOnTime = softbodyModifier_dependsOnTime; mti->dependsOnTime = softbodyModifier_dependsOnTime;
@ -8395,7 +8444,8 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type)
mti->type = eModifierTypeType_Nonconstructive; mti->type = eModifierTypeType_Nonconstructive;
mti->initData = clothModifier_initData; mti->initData = clothModifier_initData;
mti->flags = eModifierTypeFlag_AcceptsMesh mti->flags = eModifierTypeFlag_AcceptsMesh
| eModifierTypeFlag_UsesPointCache; | eModifierTypeFlag_UsesPointCache
| eModifierTypeFlag_Single;
mti->dependsOnTime = clothModifier_dependsOnTime; mti->dependsOnTime = clothModifier_dependsOnTime;
mti->freeData = clothModifier_freeData; mti->freeData = clothModifier_freeData;
mti->requiredDataMask = clothModifier_requiredDataMask; mti->requiredDataMask = clothModifier_requiredDataMask;
@ -8406,7 +8456,8 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type)
mti = INIT_TYPE(Collision); mti = INIT_TYPE(Collision);
mti->type = eModifierTypeType_OnlyDeform; mti->type = eModifierTypeType_OnlyDeform;
mti->initData = collisionModifier_initData; mti->initData = collisionModifier_initData;
mti->flags = eModifierTypeFlag_AcceptsMesh; mti->flags = eModifierTypeFlag_AcceptsMesh
| eModifierTypeFlag_Single;
mti->dependsOnTime = collisionModifier_dependsOnTime; mti->dependsOnTime = collisionModifier_dependsOnTime;
mti->freeData = collisionModifier_freeData; mti->freeData = collisionModifier_freeData;
mti->deformVerts = collisionModifier_deformVerts; mti->deformVerts = collisionModifier_deformVerts;
@ -8489,7 +8540,8 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type)
mti = INIT_TYPE(Fluidsim); mti = INIT_TYPE(Fluidsim);
mti->type = eModifierTypeType_Nonconstructive mti->type = eModifierTypeType_Nonconstructive
| eModifierTypeFlag_RequiresOriginalData; | eModifierTypeFlag_RequiresOriginalData
| eModifierTypeFlag_Single;
mti->flags = eModifierTypeFlag_AcceptsMesh; mti->flags = eModifierTypeFlag_AcceptsMesh;
mti->initData = fluidsimModifier_initData; mti->initData = fluidsimModifier_initData;
mti->freeData = fluidsimModifier_freeData; mti->freeData = fluidsimModifier_freeData;

File diff suppressed because it is too large Load Diff

@ -1198,18 +1198,12 @@ Object *copy_object(Object *ob)
armature_rebuild_pose(obn, obn->data); armature_rebuild_pose(obn, obn->data);
} }
copy_defgroups(&obn->defbase, &ob->defbase); copy_defgroups(&obn->defbase, &ob->defbase);
#if 0 // XXX old animation system
copy_nlastrips(&obn->nlastrips, &ob->nlastrips);
#endif // XXX old animation system
copy_constraints(&obn->constraints, &ob->constraints); copy_constraints(&obn->constraints, &ob->constraints);
/* increase user numbers */ /* increase user numbers */
id_us_plus((ID *)obn->data); id_us_plus((ID *)obn->data);
#if 0 // XXX old animation system
id_us_plus((ID *)obn->ipo);
id_us_plus((ID *)obn->action);
#endif // XXX old animation system
id_us_plus((ID *)obn->dup_group); id_us_plus((ID *)obn->dup_group);
// FIXME: add this for animdata too...
for(a=0; a<obn->totcol; a++) id_us_plus((ID *)obn->mat[a]); for(a=0; a<obn->totcol; a++) id_us_plus((ID *)obn->mat[a]);
@ -1575,14 +1569,14 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[][4])
} }
/* catch exceptions: curve paths used as a duplicator */ /* catch exceptions: curve paths used as a duplicator */
else if(enable_cu_speed) { else if(enable_cu_speed) {
ctime= bsystem_time(scene, ob, (float)scene->r.cfra, 0.0); /* ctime is now a proper var setting of Curve which gets set by Animato like any other var that's animated,
* but this will only work if it actually is animated...
#if 0 // XXX old animation system *
if(calc_ipo_spec(cu->ipo, CU_SPEED, &ctime)==0) { * we firstly calculate the modulus of cu->ctime/cu->pathlen to clamp ctime within the 0.0 to 1.0 times pathlen
ctime /= cu->pathlen; * range, then divide this (the modulus) by pathlen to get a value between 0.0 and 1.0
CLAMP(ctime, 0.0, 1.0); */
} ctime= fmod(cu->ctime, cu->pathlen) / cu->pathlen;
#endif // XXX old animation system CLAMP(ctime, 0.0, 1.0);
} }
else { else {
ctime= scene->r.cfra - give_timeoffset(ob); ctime= scene->r.cfra - give_timeoffset(ob);

@ -377,8 +377,6 @@ there was an error or when the user desides to cancel the operation.
char *unpackFile(ReportList *reports, char *abs_name, char *local_name, PackedFile *pf, int how) char *unpackFile(ReportList *reports, char *abs_name, char *local_name, PackedFile *pf, int how)
{ {
char menu[6 *(FILE_MAXDIR + FILE_MAXFILE + 100)];
char line[FILE_MAXDIR + FILE_MAXFILE + 100];
char *newname = NULL, *temp = NULL; char *newname = NULL, *temp = NULL;
// char newabs[FILE_MAXDIR + FILE_MAXFILE]; // char newabs[FILE_MAXDIR + FILE_MAXFILE];

@ -81,6 +81,10 @@
static void key_from_object(Object *ob, ParticleKey *key); static void key_from_object(Object *ob, ParticleKey *key);
static void get_cpa_texture(DerivedMesh *dm, Material *ma, int face_index, static void get_cpa_texture(DerivedMesh *dm, Material *ma, int face_index,
float *fuv, float *orco, ParticleTexture *ptex, int event); float *fuv, float *orco, ParticleTexture *ptex, int event);
static void get_child_modifier_parameters(ParticleSettings *part, ParticleThreadContext *ctx,
ChildParticle *cpa, short cpa_from, int cpa_num, float *cpa_fuv, float *orco, ParticleTexture *ptex);
static void do_child_modifiers(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSettings *part,
ParticleTexture *ptex, ParticleKey *par, float *par_rot, ChildParticle *cpa, float *orco, ParticleKey *state, float t);
/* few helpers for countall etc. */ /* few helpers for countall etc. */
int count_particles(ParticleSystem *psys){ int count_particles(ParticleSystem *psys){
@ -230,7 +234,7 @@ void psys_set_current_num(Object *ob, int index)
if(ob==0) return; if(ob==0) return;
for(psys=ob->particlesystem.first, i=0; psys; psys=psys->next, i++) { for(psys=ob->particlesystem.first, i=0; psys; psys=psys->next, i++) {
if(i == index - 1) if(i == index)
psys->flag |= PSYS_CURRENT; psys->flag |= PSYS_CURRENT;
else else
psys->flag &= ~PSYS_CURRENT; psys->flag &= ~PSYS_CURRENT;
@ -452,7 +456,7 @@ void psys_free(Object *ob, ParticleSystem * psys)
for(tpsys=ob->particlesystem.first; tpsys; tpsys=tpsys->next){ for(tpsys=ob->particlesystem.first; tpsys; tpsys=tpsys->next){
if(tpsys->part) if(tpsys->part)
{ {
if(ELEM(tpsys->part->draw_as,PART_DRAW_OB,PART_DRAW_GR)) if(ELEM(tpsys->part->ren_as,PART_DRAW_OB,PART_DRAW_GR))
{ {
nr++; nr++;
break; break;
@ -491,6 +495,7 @@ typedef struct ParticleRenderData {
ChildParticle *child; ChildParticle *child;
ParticleCacheKey **pathcache; ParticleCacheKey **pathcache;
ParticleCacheKey **childcache; ParticleCacheKey **childcache;
ListBase pathcachebufs, childcachebufs;
int totchild, totcached, totchildcache; int totchild, totcached, totchildcache;
DerivedMesh *dm; DerivedMesh *dm;
int totdmvert, totdmedge, totdmface; int totdmvert, totdmedge, totdmface;
@ -577,8 +582,12 @@ void psys_render_set(Object *ob, ParticleSystem *psys, float viewmat[][4], float
data->child= psys->child; data->child= psys->child;
data->totchild= psys->totchild; data->totchild= psys->totchild;
data->pathcache= psys->pathcache; data->pathcache= psys->pathcache;
data->pathcachebufs.first = psys->pathcachebufs.first;
data->pathcachebufs.last = psys->pathcachebufs.last;
data->totcached= psys->totcached; data->totcached= psys->totcached;
data->childcache= psys->childcache; data->childcache= psys->childcache;
data->childcachebufs.first = psys->childcachebufs.first;
data->childcachebufs.last = psys->childcachebufs.last;
data->totchildcache= psys->totchildcache; data->totchildcache= psys->totchildcache;
if(psmd->dm) if(psmd->dm)
@ -591,6 +600,8 @@ void psys_render_set(Object *ob, ParticleSystem *psys, float viewmat[][4], float
psys->pathcache= NULL; psys->pathcache= NULL;
psys->childcache= NULL; psys->childcache= NULL;
psys->totchild= psys->totcached= psys->totchildcache= 0; psys->totchild= psys->totcached= psys->totchildcache= 0;
psys->pathcachebufs.first = psys->pathcachebufs.last = NULL;
psys->childcachebufs.first = psys->childcachebufs.last = NULL;
Mat4CpyMat4(data->winmat, winmat); Mat4CpyMat4(data->winmat, winmat);
Mat4MulMat4(data->viewmat, ob->obmat, viewmat); Mat4MulMat4(data->viewmat, ob->obmat, viewmat);
@ -631,8 +642,12 @@ void psys_render_restore(Object *ob, ParticleSystem *psys)
psys->child= data->child; psys->child= data->child;
psys->totchild= data->totchild; psys->totchild= data->totchild;
psys->pathcache= data->pathcache; psys->pathcache= data->pathcache;
psys->pathcachebufs.first = data->pathcachebufs.first;
psys->pathcachebufs.last = data->pathcachebufs.last;
psys->totcached= data->totcached; psys->totcached= data->totcached;
psys->childcache= data->childcache; psys->childcache= data->childcache;
psys->childcachebufs.first = data->childcachebufs.first;
psys->childcachebufs.last = data->childcachebufs.last;
psys->totchildcache= data->totchildcache; psys->totchildcache= data->totchildcache;
psmd->dm= data->dm; psmd->dm= data->dm;
@ -663,7 +678,7 @@ int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot)
int *origindex, *facetotvert; int *origindex, *facetotvert;
int a, b, totorigface, totface, newtot, skipped; int a, b, totorigface, totface, newtot, skipped;
if(part->draw_as!=PART_DRAW_PATH || !(part->draw & PART_DRAW_REN_STRAND)) if(part->ren_as!=PART_DRAW_PATH || !(part->draw & PART_DRAW_REN_STRAND))
return tot; return tot;
if(!ctx->psys->renderdata) if(!ctx->psys->renderdata)
return tot; return tot;
@ -1992,13 +2007,11 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa,
ParticleData *pa=NULL; ParticleData *pa=NULL;
ParticleTexture ptex; ParticleTexture ptex;
float *cpa_fuv=0, *par_rot=0; float *cpa_fuv=0, *par_rot=0;
float co[3], orco[3], ornor[3], t, rough_t, cpa_1st[3], dvec[3]; float co[3], orco[3], ornor[3], t, cpa_1st[3], dvec[3];
float branch_begin, branch_end, branch_prob, branchfac, rough_rand; float branch_begin, branch_end, branch_prob, rough_rand;
float pa_rough1, pa_rough2, pa_roughe; float length, max_length = 1.0f, cur_length = 0.0f;
float length, pa_length, pa_clump, pa_kink, pa_effector;
float max_length = 1.0f, cur_length = 0.0f;
float eff_length, eff_vec[3]; float eff_length, eff_vec[3];
int k, cpa_num, guided = 0; int k, cpa_num;
short cpa_from; short cpa_from;
if(part->flag & PART_BRANCHING) { if(part->flag & PART_BRANCHING) {
@ -2059,9 +2072,11 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa,
psys_particle_on_emitter(ctx->psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa->fuv,foffset,co,ornor,0,0,orco,0); psys_particle_on_emitter(ctx->psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa->fuv,foffset,co,ornor,0,0,orco,0);
/* we need to save the actual root position of the child for positioning it accurately to the surface of the emitter */ if(part->path_start==0.0f) {
VECCOPY(cpa_1st,co); /* we need to save the actual root position of the child for positioning it accurately to the surface of the emitter */
Mat4MulVecfl(ob->obmat,cpa_1st); VECCOPY(cpa_1st,co);
Mat4MulVecfl(ob->obmat,cpa_1st);
}
pa=0; pa=0;
} }
@ -2098,43 +2113,13 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa,
#endif // XXX old animation system #endif // XXX old animation system
/* get different child parameters from textures & vgroups */ /* get different child parameters from textures & vgroups */
ptex.length=part->length*(1.0f - part->randlength*cpa->rand[0]); get_child_modifier_parameters(part, ctx, cpa, cpa_from, cpa_num, cpa_fuv, orco, &ptex);
ptex.clump=1.0;
ptex.kink=1.0;
ptex.rough= 1.0;
ptex.exist= 1.0;
get_cpa_texture(ctx->dm,ctx->ma,cpa_num,cpa_fuv,orco,&ptex,
MAP_PA_DENS|MAP_PA_LENGTH|MAP_PA_CLUMP|MAP_PA_KINK|MAP_PA_ROUGH);
pa_length=ptex.length;
pa_clump=ptex.clump;
pa_kink=ptex.kink;
pa_rough1=ptex.rough;
pa_rough2=ptex.rough;
pa_roughe=ptex.rough;
pa_effector= 1.0f;
if(ptex.exist < cpa->rand[1]) { if(ptex.exist < cpa->rand[1]) {
keys->steps = -1; keys->steps = -1;
return; return;
} }
if(ctx->vg_length)
pa_length*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_length);
if(ctx->vg_clump)
pa_clump*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_clump);
if(ctx->vg_kink)
pa_kink*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_kink);
if(ctx->vg_rough1)
pa_rough1*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_rough1);
if(ctx->vg_rough2)
pa_rough2*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_rough2);
if(ctx->vg_roughe)
pa_roughe*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_roughe);
if(ctx->vg_effector)
pa_effector*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_effector);
/* create the child path */ /* create the child path */
for(k=0,state=keys; k<=ctx->steps; k++,state++){ for(k=0,state=keys; k<=ctx->steps; k++,state++){
if(ctx->between){ if(ctx->between){
@ -2158,12 +2143,14 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa,
key[w]++; key[w]++;
w++; w++;
} }
if(k==0){ if(part->path_start==0.0f) {
/* calculate the offset between actual child root position and first position interpolated from parents */ if(k==0){
VECSUB(cpa_1st,cpa_1st,state->co); /* calculate the offset between actual child root position and first position interpolated from parents */
VECSUB(cpa_1st,cpa_1st,state->co);
}
/* apply offset for correct positioning */
VECADD(state->co,state->co,cpa_1st);
} }
/* apply offset for correct positioning */
VECADD(state->co,state->co,cpa_1st);
} }
else{ else{
/* offset the child from the parent position */ /* offset the child from the parent position */
@ -2177,7 +2164,7 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa,
if(part->flag & PART_CHILD_EFFECT) { if(part->flag & PART_CHILD_EFFECT) {
for(k=0,state=keys; k<=ctx->steps; k++,state++) { for(k=0,state=keys; k<=ctx->steps; k++,state++) {
if(k) { if(k) {
do_path_effectors(ctx->scene, ob, psys, cpa->pa[0], state, k, ctx->steps, keys->co, pa_effector, 0.0f, ctx->cfra, &eff_length, eff_vec); do_path_effectors(ctx->scene, ob, psys, cpa->pa[0], state, k, ctx->steps, keys->co, ptex.effector, 0.0f, ctx->cfra, &eff_length, eff_vec);
} }
else { else {
VecSubf(eff_vec,(state+1)->co,state->co); VecSubf(eff_vec,(state+1)->co,state->co);
@ -2203,67 +2190,50 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa,
} }
/* apply different deformations to the child path */ /* apply different deformations to the child path */
if(part->flag & PART_CHILD_EFFECT) do_child_modifiers(ctx->scene, ob, psys, part, &ptex, (ParticleKey *)par, par_rot, cpa, orco, (ParticleKey *)state, t);
/* state is safe to cast, since only co and vel are used */
guided = do_guide(ctx->scene, (ParticleKey*)state, cpa->parent, t, &(psys->effectors));
if(guided==0){ /* TODO: better branching */
if(part->kink) //if(part->flag & PART_BRANCHING && ctx->between == 0 && part->flag & PART_ANIM_BRANCHING)
do_prekink((ParticleKey*)state, (ParticleKey*)par, par_rot, t, // rough_t = t * rough_rand;
part->kink_freq * pa_kink, part->kink_shape, part->kink_amp, part->kink, part->kink_axis, ob->obmat); //else
// rough_t = t;
do_clump((ParticleKey*)state, (ParticleKey*)par, t, part->clumpfac, part->clumppow, pa_clump); /* TODO: better branching */
} //if(part->flag & PART_BRANCHING && ctx->between==0){
// if(branch_prob > part->branch_thres){
// branchfac=0.0f;
// }
// else{
// if(part->flag & PART_SYMM_BRANCHING){
// if(t < branch_begin || t > branch_end)
// branchfac=0.0f;
// else{
// if((t-branch_begin)/(branch_end-branch_begin)<0.5)
// branchfac=2.0f*(t-branch_begin)/(branch_end-branch_begin);
// else
// branchfac=2.0f*(branch_end-t)/(branch_end-branch_begin);
if(part->flag & PART_BRANCHING && ctx->between == 0 && part->flag & PART_ANIM_BRANCHING) // CLAMP(branchfac,0.0f,1.0f);
rough_t = t * rough_rand; // }
else // }
rough_t = t; // else{
// if(t < branch_begin){
// branchfac=0.0f;
// }
// else{
// branchfac=(t-branch_begin)/((1.0f-branch_begin)*0.5f);
// CLAMP(branchfac,0.0f,1.0f);
// }
// }
// }
if(part->rough1 != 0.0 && pa_rough1 != 0.0) // if(i<psys->totpart)
do_rough(orco, rough_t, pa_rough1*part->rough1, part->rough1_size, 0.0, (ParticleKey*)state); // VecLerpf(state->co, (pcache[i] + k)->co, state->co, branchfac);
// else
if(part->rough2 != 0.0 && pa_rough2 != 0.0) // /* this is not threadsafe, but should only happen for
do_rough(cpa->rand, rough_t, pa_rough2*part->rough2, part->rough2_size, part->rough2_thres, (ParticleKey*)state); // * branching particles particles, which are not threaded */
// VecLerpf(state->co, (cache[i - psys->totpart] + k)->co, state->co, branchfac);
if(part->rough_end != 0.0 && pa_roughe != 0.0) //}
do_rough_end(cpa->rand, rough_t, pa_roughe*part->rough_end, part->rough_end_shape, (ParticleKey*)state, (ParticleKey*)par);
if(part->flag & PART_BRANCHING && ctx->between==0){
if(branch_prob > part->branch_thres){
branchfac=0.0f;
}
else{
if(part->flag & PART_SYMM_BRANCHING){
if(t < branch_begin || t > branch_end)
branchfac=0.0f;
else{
if((t-branch_begin)/(branch_end-branch_begin)<0.5)
branchfac=2.0f*(t-branch_begin)/(branch_end-branch_begin);
else
branchfac=2.0f*(branch_end-t)/(branch_end-branch_begin);
CLAMP(branchfac,0.0f,1.0f);
}
}
else{
if(t < branch_begin){
branchfac=0.0f;
}
else{
branchfac=(t-branch_begin)/((1.0f-branch_begin)*0.5f);
CLAMP(branchfac,0.0f,1.0f);
}
}
}
if(i<psys->totpart)
VecLerpf(state->co, (pcache[i] + k)->co, state->co, branchfac);
else
/* this is not threadsafe, but should only happen for
* branching particles particles, which are not threaded */
VecLerpf(state->co, (cache[i - psys->totpart] + k)->co, state->co, branchfac);
}
/* we have to correct velocity because of kink & clump */ /* we have to correct velocity because of kink & clump */
if(k>1){ if(k>1){
@ -2287,9 +2257,9 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa,
else{ else{
/* initialize length calculation */ /* initialize length calculation */
if(part->flag&PART_ABS_LENGTH) if(part->flag&PART_ABS_LENGTH)
max_length= part->abslength*pa_length; max_length= part->abslength*ptex.length;
else else
max_length= pa_length; max_length= ptex.length;
cur_length= 0.0f; cur_length= 0.0f;
} }
@ -2383,7 +2353,36 @@ void psys_cache_child_paths(Scene *scene, Object *ob, ParticleSystem *psys, floa
psys_threads_free(pthreads); psys_threads_free(pthreads);
} }
static void get_pointcache_keys_for_time(ParticleSystem *psys, int index, float t, ParticleKey *key1, ParticleKey *key2)
{
PointCache *cache = psys->pointcache;
static PTCacheMem *pm = NULL;
if(cache->flag & PTCACHE_DISK_CACHE) {
/* TODO */
}
else {
if(index < 0) { /* initialize */
pm = cache->mem_cache.first;
if(pm)
pm = pm->next;
}
else {
if(pm) {
while(pm && pm->next && (float)pm->frame < t)
pm = pm->next;
copy_particle_key(key2, ((ParticleKey *)pm->data) + index, 1);
copy_particle_key(key1, ((ParticleKey *)(pm->prev)->data) + index, 1);
}
else if(cache->mem_cache.first) {
pm = cache->mem_cache.first;
copy_particle_key(key2, ((ParticleKey *)pm->data) + index, 1);
copy_particle_key(key1, ((ParticleKey *)pm->data) + index, 1);
}
}
}
}
/* Calculates paths ready for drawing/rendering. */ /* Calculates paths ready for drawing/rendering. */
/* -Usefull for making use of opengl vertex arrays for super fast strand drawing. */ /* -Usefull for making use of opengl vertex arrays for super fast strand drawing. */
/* -Makes child strands possible and creates them too into the cache. */ /* -Makes child strands possible and creates them too into the cache. */
@ -2409,7 +2408,7 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra
float birthtime = 0.0, dietime = 0.0; float birthtime = 0.0, dietime = 0.0;
float t, time = 0.0, keytime = 0.0, dfra = 1.0, frs_sec = scene->r.frs_sec; float t, time = 0.0, keytime = 0.0, dfra = 1.0, frs_sec = scene->r.frs_sec;
float col[3] = {0.5f, 0.5f, 0.5f}; float col[4] = {0.5f, 0.5f, 0.5f, 1.0f};
float prev_tangent[3], hairmat[4][4]; float prev_tangent[3], hairmat[4][4];
int k,i; int k,i;
int steps = (int)pow(2.0, (double)psys->part->draw_step); int steps = (int)pow(2.0, (double)psys->part->draw_step);
@ -2418,13 +2417,18 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra
float nosel_col[3]; float nosel_col[3];
float length, vec[3]; float length, vec[3];
float *vg_effector= NULL, effector=0.0f; float *vg_effector= NULL, effector=0.0f;
float *vg_length= NULL, pa_length=1.0f, max_length=1.0f, cur_length=0.0f; float *vg_length= NULL, pa_length=1.0f;
float len, dvec[3]; int keyed, baked;
/* we don't have anything valid to create paths from so let's quit here */ /* we don't have anything valid to create paths from so let's quit here */
if((psys->flag & PSYS_HAIR_DONE)==0 && (psys->flag & PSYS_KEYED)==0) if((psys->flag & PSYS_HAIR_DONE)==0 && (psys->flag & PSYS_KEYED)==0 && (psys->pointcache->flag & PTCACHE_BAKED)==0)
return; return;
BLI_srandom(psys->seed);
keyed = psys->flag & PSYS_KEYED;
baked = psys->pointcache->flag & PTCACHE_BAKED;
if(psys->renderdata) { if(psys->renderdata) {
steps = (int)pow(2.0, (double)psys->part->ren_step); steps = (int)pow(2.0, (double)psys->part->ren_step);
} }
@ -2488,7 +2492,8 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra
else memset(cache[i], 0, sizeof(*cache[i])*(steps+1)); else memset(cache[i], 0, sizeof(*cache[i])*(steps+1));
if(!edit && !psys->totchild) { if(!edit && !psys->totchild) {
pa_length = part->length * (1.0f - part->randlength*pa->r_ave[0]); //pa_length = part->length * (1.0f - part->randlength*pa->r_ave[0]);
pa_length = 1.0f - part->randlength * 0.5 * (1.0f + pa->r_ave[0]);
if(vg_length) if(vg_length)
pa_length *= psys_particle_value_from_verts(psmd->dm,part->from,pa,vg_length); pa_length *= psys_particle_value_from_verts(psmd->dm,part->from,pa,vg_length);
} }
@ -2499,13 +2504,19 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra
ekey = edit->keys[i]; ekey = edit->keys[i];
/*--get the first data points--*/ /*--get the first data points--*/
if(psys->flag & PSYS_KEYED) { if(keyed) {
kkey[0] = pa->keys; kkey[0] = pa->keys;
kkey[1] = kkey[0] + 1; kkey[1] = kkey[0] + 1;
birthtime = kkey[0]->time; birthtime = kkey[0]->time;
dietime = kkey[0][pa->totkey-1].time; dietime = kkey[0][pa->totkey-1].time;
} }
else if(baked) {
get_pointcache_keys_for_time(psys, -1, 0.0f, NULL, NULL);
birthtime = pa->time;
dietime = pa->dietime;
}
else { else {
hkey[0] = pa->hair; hkey[0] = pa->hair;
hkey[1] = hkey[0] + 1; hkey[1] = hkey[0] + 1;
@ -2516,6 +2527,25 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra
psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat); psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat);
} }
if(!edit) {
if(part->draw & PART_ABS_PATH_TIME) {
birthtime = MAX2(birthtime, part->path_start);
dietime = MIN2(dietime, part->path_end);
}
else {
float tb = birthtime;
birthtime = tb + part->path_start * (dietime - tb);
dietime = tb + part->path_end * (dietime - tb);
}
if(birthtime >= dietime) {
cache[i]->steps = -1;
continue;
}
dietime = birthtime + pa_length * (dietime - birthtime);
}
if(soft){ if(soft){
bp[0] = soft->bpoint + pa->bpi; bp[0] = soft->bpoint + pa->bpi;
bp[1] = bp[0] + 1; bp[1] = bp[0] + 1;
@ -2527,13 +2557,16 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra
t = birthtime + time * (dietime - birthtime); t = birthtime + time * (dietime - birthtime);
if(psys->flag & PSYS_KEYED) { if(keyed) {
while(kkey[1]->time < t) { while(kkey[1]->time < t) {
kkey[1]++; kkey[1]++;
} }
kkey[0] = kkey[1] - 1; kkey[0] = kkey[1] - 1;
} }
else if(baked) {
get_pointcache_keys_for_time(psys, i, t, keys+1, keys+2);
}
else { else {
while(hkey[1]->time < t) { while(hkey[1]->time < t) {
hkey[1]++; hkey[1]++;
@ -2548,17 +2581,19 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra
bp_to_particle(keys + 1, bp[0], hkey[0]); bp_to_particle(keys + 1, bp[0], hkey[0]);
bp_to_particle(keys + 2, bp[1], hkey[1]); bp_to_particle(keys + 2, bp[1], hkey[1]);
} }
else if(psys->flag & PSYS_KEYED) { else if(keyed) {
memcpy(keys + 1, kkey[0], sizeof(ParticleKey)); memcpy(keys + 1, kkey[0], sizeof(ParticleKey));
memcpy(keys + 2, kkey[1], sizeof(ParticleKey)); memcpy(keys + 2, kkey[1], sizeof(ParticleKey));
} }
else if(baked)
; /* keys already set */
else { else {
hair_to_particle(keys + 1, hkey[0]); hair_to_particle(keys + 1, hkey[0]);
hair_to_particle(keys + 2, hkey[1]); hair_to_particle(keys + 2, hkey[1]);
} }
if((psys->flag & PSYS_KEYED)==0) { if(!keyed && !baked) {
if(soft) { if(soft) {
if(hkey[0] != pa->hair) if(hkey[0] != pa->hair)
bp_to_particle(keys, bp[0] - 1, hkey[0] - 1); bp_to_particle(keys, bp[0] - 1, hkey[0] - 1);
@ -2591,18 +2626,18 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra
keytime = (t - keys[1].time) / dfra; keytime = (t - keys[1].time) / dfra;
/* convert velocity to timestep size */ /* convert velocity to timestep size */
if(psys->flag & PSYS_KEYED){ if(keyed || baked){
VecMulf(keys[1].vel, dfra / frs_sec); VecMulf(keys[1].vel, dfra / frs_sec);
VecMulf(keys[2].vel, dfra / frs_sec); VecMulf(keys[2].vel, dfra / frs_sec);
} }
/* now we should have in chronologiacl order k1<=k2<=t<=k3<=k4 with keytime between [0,1]->[k2,k3] (k1 & k4 used for cardinal & bspline interpolation)*/ /* now we should have in chronologiacl order k1<=k2<=t<=k3<=k4 with keytime between [0,1]->[k2,k3] (k1 & k4 used for cardinal & bspline interpolation)*/
psys_interpolate_particle((psys->flag & PSYS_KEYED) ? -1 /* signal for cubic interpolation */ psys_interpolate_particle((keyed || baked) ? -1 /* signal for cubic interpolation */
: ((psys->part->flag & PART_HAIR_BSPLINE) ? KEY_BSPLINE : KEY_CARDINAL) : ((psys->part->flag & PART_HAIR_BSPLINE) ? KEY_BSPLINE : KEY_CARDINAL)
,keys, keytime, &result, 0); ,keys, keytime, &result, 0);
/* the velocity needs to be converted back from cubic interpolation */ /* the velocity needs to be converted back from cubic interpolation */
if(psys->flag & PSYS_KEYED){ if(keyed || baked){
VecMulf(result.vel, frs_sec / dfra); VecMulf(result.vel, frs_sec / dfra);
} }
else if(soft==NULL) { /* softbody and keyed are allready in global space */ else if(soft==NULL) { /* softbody and keyed are allready in global space */
@ -2717,28 +2752,6 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra
} }
} }
if(!edit && !psys->totchild) {
/* check if path needs to be cut before actual end of data points */
if(k){
VECSUB(dvec,ca->co,(ca-1)->co);
if(part->flag&PART_ABS_LENGTH)
len=VecLength(dvec);
else
len=1.0f/(float)steps;
k=check_path_length(k,cache[i],ca,max_length,&cur_length,len,dvec);
}
else{
/* initialize length calculation */
if(part->flag&PART_ABS_LENGTH)
max_length= part->abslength*pa_length;
else
max_length= pa_length;
cur_length= 0.0f;
}
}
} }
} }
@ -2990,7 +3003,8 @@ static void default_particle_settings(ParticleSettings *part)
part->type= PART_EMITTER; part->type= PART_EMITTER;
part->distr= PART_DISTR_JIT; part->distr= PART_DISTR_JIT;
part->draw_as=PART_DRAW_DOT; part->draw_as = PART_DRAW_REND;
part->ren_as = PART_DRAW_HALO;
part->bb_uv_split=1; part->bb_uv_split=1;
part->bb_align=PART_BB_VIEW; part->bb_align=PART_BB_VIEW;
part->bb_split_offset=PART_BB_OFF_LINEAR; part->bb_split_offset=PART_BB_OFF_LINEAR;
@ -3046,6 +3060,8 @@ static void default_particle_settings(ParticleSettings *part)
part->rough_end_shape=1.0; part->rough_end_shape=1.0;
part->draw_line[0]=0.5; part->draw_line[0]=0.5;
part->path_start = 0.0f;
part->path_end = 1.0f;
part->banking=1.0; part->banking=1.0;
part->max_bank=1.0; part->max_bank=1.0;
@ -3282,7 +3298,7 @@ static void get_cpa_texture(DerivedMesh *dm, Material *ma, int face_index, float
if((event & mtex->pmapto) & MAP_PA_KINK) if((event & mtex->pmapto) & MAP_PA_KINK)
ptex->kink= texture_value_blend(def,ptex->kink,value,var,blend,neg & MAP_PA_KINK); ptex->kink= texture_value_blend(def,ptex->kink,value,var,blend,neg & MAP_PA_KINK);
if((event & mtex->pmapto) & MAP_PA_ROUGH) if((event & mtex->pmapto) & MAP_PA_ROUGH)
ptex->rough= texture_value_blend(def,ptex->rough,value,var,blend,neg & MAP_PA_ROUGH); ptex->rough1= ptex->rough2= ptex->roughe= texture_value_blend(def,ptex->rough1,value,var,blend,neg & MAP_PA_ROUGH);
if((event & mtex->pmapto) & MAP_PA_DENS) if((event & mtex->pmapto) & MAP_PA_DENS)
ptex->exist= texture_value_blend(def,ptex->exist,value,var,blend,neg & MAP_PA_DENS); ptex->exist= texture_value_blend(def,ptex->exist,value,var,blend,neg & MAP_PA_DENS);
} }
@ -3291,7 +3307,11 @@ static void get_cpa_texture(DerivedMesh *dm, Material *ma, int face_index, float
if(event & MAP_PA_LENGTH) { CLAMP(ptex->length,0.0,1.0); } if(event & MAP_PA_LENGTH) { CLAMP(ptex->length,0.0,1.0); }
if(event & MAP_PA_CLUMP) { CLAMP(ptex->clump,0.0,1.0); } if(event & MAP_PA_CLUMP) { CLAMP(ptex->clump,0.0,1.0); }
if(event & MAP_PA_KINK) { CLAMP(ptex->kink,0.0,1.0); } if(event & MAP_PA_KINK) { CLAMP(ptex->kink,0.0,1.0); }
if(event & MAP_PA_ROUGH) { CLAMP(ptex->rough,0.0,1.0); } if(event & MAP_PA_ROUGH) {
CLAMP(ptex->rough1,0.0,1.0);
CLAMP(ptex->rough2,0.0,1.0);
CLAMP(ptex->roughe,0.0,1.0);
}
if(event & MAP_PA_DENS) { CLAMP(ptex->exist,0.0,1.0); } if(event & MAP_PA_DENS) { CLAMP(ptex->exist,0.0,1.0); }
} }
void psys_get_texture(Object *ob, Material *ma, ParticleSystemModifierData *psmd, ParticleSystem *psys, ParticleData *pa, ParticleTexture *ptex, int event) void psys_get_texture(Object *ob, Material *ma, ParticleSystemModifierData *psmd, ParticleSystem *psys, ParticleData *pa, ParticleTexture *ptex, int event)
@ -3392,12 +3412,12 @@ float psys_get_size(Object *ob, Material *ma, ParticleSystemModifierData *psmd,
return size*part->size; return size*part->size;
} }
float psys_get_child_time(ParticleSystem *psys, ChildParticle *cpa, float cfra) float psys_get_child_time(ParticleSystem *psys, ChildParticle *cpa, float cfra, float *birthtime, float *dietime)
{ {
ParticleSettings *part = psys->part; ParticleSettings *part = psys->part;
float time, life;
if(part->childtype==PART_CHILD_FACES){ if(part->childtype==PART_CHILD_FACES){
float time;
int w=0; int w=0;
time=0.0; time=0.0;
while(w<4 && cpa->pa[w]>=0){ while(w<4 && cpa->pa[w]>=0){
@ -3405,12 +3425,21 @@ float psys_get_child_time(ParticleSystem *psys, ChildParticle *cpa, float cfra)
w++; w++;
} }
return (cfra-time)/(part->lifetime*(1.0f-part->randlife*cpa->rand[1])); life = part->lifetime*(1.0f-part->randlife*cpa->rand[1]);
} }
else{ else{
ParticleData *pa = psys->particles + cpa->parent; ParticleData *pa = psys->particles + cpa->parent;
return (cfra-pa->time)/pa->lifetime;
time = pa->time;
life = pa->lifetime;
} }
if(birthtime)
*birthtime = time;
if(dietime)
*dietime = time+life;
return (cfra-time)/life;
} }
float psys_get_child_size(ParticleSystem *psys, ChildParticle *cpa, float cfra, float *pa_time) float psys_get_child_size(ParticleSystem *psys, ChildParticle *cpa, float cfra, float *pa_time)
{ {
@ -3427,7 +3456,7 @@ float psys_get_child_size(ParticleSystem *psys, ChildParticle *cpa, float cfra,
if(pa_time) if(pa_time)
time=*pa_time; time=*pa_time;
else else
time=psys_get_child_time(psys,cpa,cfra); time=psys_get_child_time(psys,cpa,cfra,NULL,NULL);
/* correction for lifetime */ /* correction for lifetime */
calc_ipo(part->ipo, 100*time); calc_ipo(part->ipo, 100*time);
@ -3449,6 +3478,64 @@ float psys_get_child_size(ParticleSystem *psys, ChildParticle *cpa, float cfra,
return size; return size;
} }
static void get_child_modifier_parameters(ParticleSettings *part, ParticleThreadContext *ctx, ChildParticle *cpa, short cpa_from, int cpa_num, float *cpa_fuv, float *orco, ParticleTexture *ptex)
{
ptex->length=part->length*(1.0f - part->randlength*cpa->rand[0]);
ptex->clump=1.0;
ptex->kink=1.0;
ptex->rough1= 1.0;
ptex->rough2= 1.0;
ptex->roughe= 1.0;
ptex->exist= 1.0;
ptex->effector= 1.0;
get_cpa_texture(ctx->dm,ctx->ma,cpa_num,cpa_fuv,orco,ptex,
MAP_PA_DENS|MAP_PA_LENGTH|MAP_PA_CLUMP|MAP_PA_KINK|MAP_PA_ROUGH);
if(ptex->exist < cpa->rand[1])
return;
if(ctx->vg_length)
ptex->length*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_length);
if(ctx->vg_clump)
ptex->clump*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_clump);
if(ctx->vg_kink)
ptex->kink*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_kink);
if(ctx->vg_rough1)
ptex->rough1*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_rough1);
if(ctx->vg_rough2)
ptex->rough2*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_rough2);
if(ctx->vg_roughe)
ptex->roughe*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_roughe);
if(ctx->vg_effector)
ptex->effector*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_effector);
}
static void do_child_modifiers(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSettings *part, ParticleTexture *ptex, ParticleKey *par, float *par_rot, ChildParticle *cpa, float *orco, ParticleKey *state, float t)
{
int guided = 0;
if(part->flag & PART_CHILD_EFFECT)
/* state is safe to cast, since only co and vel are used */
guided = do_guide(scene, (ParticleKey*)state, cpa->parent, t, &(psys->effectors));
if(guided==0){
if(part->kink)
do_prekink(state, par, par_rot, t, part->kink_freq * ptex->kink, part->kink_shape,
part->kink_amp, part->kink, part->kink_axis, ob->obmat);
do_clump(state, par, t, part->clumpfac, part->clumppow, ptex->clump);
}
if(part->rough1 != 0.0 && ptex->rough1 != 0.0)
do_rough(orco, t, ptex->rough1*part->rough1, part->rough1_size, 0.0, state);
if(part->rough2 != 0.0 && ptex->rough2 != 0.0)
do_rough(cpa->rand, t, ptex->rough2*part->rough2, part->rough2_size, part->rough2_thres, state);
if(part->rough_end != 0.0 && ptex->roughe != 0.0)
do_rough_end(cpa->rand, t, ptex->roughe*part->rough_end, part->rough_end_shape, state, par);
}
/* get's hair (or keyed) particles state at the "path time" specified in state->time */ /* get's hair (or keyed) particles state at the "path time" specified in state->time */
void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, int p, ParticleKey *state, int vel) void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, int p, ParticleKey *state, int vel)
{ {
@ -3460,17 +3547,20 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i
ParticleTexture ptex; ParticleTexture ptex;
ParticleKey *kkey[2] = {NULL, NULL}; ParticleKey *kkey[2] = {NULL, NULL};
HairKey *hkey[2] = {NULL, NULL}; HairKey *hkey[2] = {NULL, NULL};
ParticleKey *par=0, keys[4]; ParticleKey *par=0, keys[4], tstate;
ParticleThreadContext ctx; /* fake thread context for child modifiers */
float t, real_t, dfra, keytime, frs_sec = scene->r.frs_sec; float t, real_t, dfra, keytime, frs_sec = scene->r.frs_sec;
float co[3], orco[3]; float co[3], orco[3];
float hairmat[4][4]; float hairmat[4][4];
float pa_clump = 0.0, pa_kink = 0.0;
int totparent = 0; int totparent = 0;
int totpart = psys->totpart; int totpart = psys->totpart;
int totchild = psys->totchild; int totchild = psys->totchild;
short between = 0, edit = 0; short between = 0, edit = 0;
int keyed = psys->flag & PSYS_KEYED;
int cached = !keyed && part->type != PART_HAIR;
float *cpa_fuv; int cpa_num; short cpa_from; float *cpa_fuv; int cpa_num; short cpa_from;
//if(psys_in_edit_mode(scene, psys)){ //if(psys_in_edit_mode(scene, psys)){
@ -3479,12 +3569,6 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i
// edit=1; // edit=1;
//} //}
/* user want's cubic interpolation but only without sb it possible */
//if(interpolation==PART_INTER_CUBIC && baked && psys->softflag==OB_SB_ENABLE)
// interpolation=PART_INTER_BSPLINE;
//else if(baked==0) /* it doesn't make sense to use other types for keyed */
// interpolation=PART_INTER_CUBIC;
t=state->time; t=state->time;
CLAMP(t, 0.0, 1.0); CLAMP(t, 0.0, 1.0);
@ -3497,20 +3581,29 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i
return; return;
} }
if(psys->flag & PSYS_KEYED) { if(keyed) {
kkey[0] = pa->keys; kkey[0] = pa->keys;
kkey[1] = kkey[0] + 1; kkey[1] = kkey[0] + 1;
real_t = kkey[0]->time + t * (kkey[0][pa->totkey-1].time - kkey[0]->time); if(state->time < 0.0f)
real_t = -state->time;
else
real_t = kkey[0]->time + t * (kkey[0][pa->totkey-1].time - kkey[0]->time);
}
else if(cached) {
get_pointcache_keys_for_time(psys, -1, 0.0f, NULL, NULL);
} }
else { else {
hkey[0] = pa->hair; hkey[0] = pa->hair;
hkey[1] = pa->hair + 1; hkey[1] = pa->hair + 1;
real_t = hkey[0]->time + (hkey[0][pa->totkey-1].time - hkey[0]->time) * t; if(state->time < 0.0f)
real_t = -state->time;
else
real_t = hkey[0]->time + t * (hkey[0][pa->totkey-1].time - hkey[0]->time);
} }
if(psys->flag & PSYS_KEYED) { if(keyed) {
while(kkey[1]->time < real_t) { while(kkey[1]->time < real_t) {
kkey[1]++; kkey[1]++;
} }
@ -3519,6 +3612,14 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i
memcpy(keys + 1, kkey[0], sizeof(ParticleKey)); memcpy(keys + 1, kkey[0], sizeof(ParticleKey));
memcpy(keys + 2, kkey[1], sizeof(ParticleKey)); memcpy(keys + 2, kkey[1], sizeof(ParticleKey));
} }
else if(cached) {
if(state->time < 0.0f) /* flag for time in frames */
real_t = -state->time;
else
real_t = pa->time + t * (pa->dietime - pa->time);
get_pointcache_keys_for_time(psys, p, real_t, keys+1, keys+2);
}
else { else {
while(hkey[1]->time < real_t) while(hkey[1]->time < real_t)
hkey[1]++; hkey[1]++;
@ -3529,63 +3630,35 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i
hair_to_particle(keys + 2, hkey[1]); hair_to_particle(keys + 2, hkey[1]);
} }
if((psys->flag & PSYS_KEYED)==0) { if(!keyed && !cached) {
//if(soft){
// if(key[0] != sbel.keys)
// DB_copy_key(&k1,key[0]-1);
// else
// DB_copy_key(&k1,&k2);
//}
//else{
if(hkey[0] != pa->hair) if(hkey[0] != pa->hair)
hair_to_particle(keys, hkey[0] - 1); hair_to_particle(keys, hkey[0] - 1);
else else
hair_to_particle(keys, hkey[0]); hair_to_particle(keys, hkey[0]);
//}
//if(soft){
// if(key[1] != sbel.keys + sbel.totkey-1)
// DB_copy_key(&k4,key[1]+1);
// else
// DB_copy_key(&k4,&k3);
//}
//else {
if(hkey[1] != pa->hair + pa->totkey - 1) if(hkey[1] != pa->hair + pa->totkey - 1)
hair_to_particle(keys + 3, hkey[1] + 1); hair_to_particle(keys + 3, hkey[1] + 1);
else else
hair_to_particle(keys + 3, hkey[1]); hair_to_particle(keys + 3, hkey[1]);
} }
//}
//psys_get_particle_on_path(scene, bsys,p,t,bkey,ckey[0]);
//if(part->rotfrom==PART_ROT_KEYS)
// QuatInterpol(state->rot,k2.rot,k3.rot,keytime);
//else{
// /* TODO: different rotations */
// float nvel[3];
// VECCOPY(nvel,state->vel);
// VecMulf(nvel,-1.0f);
// vectoquat(nvel, OB_POSX, OB_POSZ, state->rot);
//}
dfra = keys[2].time - keys[1].time; dfra = keys[2].time - keys[1].time;
keytime = (real_t - keys[1].time) / dfra; keytime = (real_t - keys[1].time) / dfra;
/* convert velocity to timestep size */ /* convert velocity to timestep size */
if(psys->flag & PSYS_KEYED){ if(keyed || cached){
VecMulf(keys[1].vel, dfra / frs_sec); VecMulf(keys[1].vel, dfra / frs_sec);
VecMulf(keys[2].vel, dfra / frs_sec); VecMulf(keys[2].vel, dfra / frs_sec);
QuatInterpol(state->rot,keys[1].rot,keys[2].rot,keytime); QuatInterpol(state->rot,keys[1].rot,keys[2].rot,keytime);
} }
psys_interpolate_particle((psys->flag & PSYS_KEYED) ? -1 /* signal for cubic interpolation */ psys_interpolate_particle((keyed || cached) ? -1 /* signal for cubic interpolation */
: ((psys->part->flag & PART_HAIR_BSPLINE) ? KEY_BSPLINE : KEY_CARDINAL) : ((psys->part->flag & PART_HAIR_BSPLINE) ? KEY_BSPLINE : KEY_CARDINAL)
,keys, keytime, state, 1); ,keys, keytime, state, 1);
/* the velocity needs to be converted back from cubic interpolation */ /* the velocity needs to be converted back from cubic interpolation */
if(psys->flag & PSYS_KEYED){ if(keyed || cached){
VecMulf(state->vel, frs_sec / dfra); VecMulf(state->vel, frs_sec / dfra);
} }
else { else {
@ -3609,6 +3682,9 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i
cpa=psys->child+p-totpart; cpa=psys->child+p-totpart;
if(state->time < 0.0f)
t = psys_get_child_time(psys, cpa, -state->time, NULL, NULL);
if(totchild && part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){ if(totchild && part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){
totparent=(int)(totchild*part->parents*0.3); totparent=(int)(totchild*part->parents*0.3);
@ -3624,7 +3700,7 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i
/* get parent states */ /* get parent states */
while(w<4 && cpa->pa[w]>=0){ while(w<4 && cpa->pa[w]>=0){
keys[w].time = t; keys[w].time = state->time;
psys_get_particle_on_path(scene, ob, psys, cpa->pa[w], keys+w, 1); psys_get_particle_on_path(scene, ob, psys, cpa->pa[w], keys+w, 1);
w++; w++;
} }
@ -3650,7 +3726,7 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i
else{ else{
/* get the parent state */ /* get the parent state */
keys->time = t; keys->time = state->time;
psys_get_particle_on_path(scene, ob, psys, cpa->parent, keys,1); psys_get_particle_on_path(scene, ob, psys, cpa->parent, keys,1);
/* get the original coordinates (orco) for texture usage */ /* get the original coordinates (orco) for texture usage */
@ -3672,15 +3748,11 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i
#endif // XXX old animation system #endif // XXX old animation system
/* get different child parameters from textures & vgroups */ /* get different child parameters from textures & vgroups */
ptex.clump=1.0; memset(&ctx, 0, sizeof(ParticleThreadContext));
ptex.kink=1.0; ctx.dm = psmd->dm;
ctx.ma = ma;
get_cpa_texture(psmd->dm,ma,cpa_num,cpa_fuv,orco,&ptex,MAP_PA_CLUMP|MAP_PA_KINK); /* TODO: assign vertex groups */
get_child_modifier_parameters(part, &ctx, cpa, cpa_from, cpa_num, cpa_fuv, orco, &ptex);
pa_clump=ptex.clump;
pa_kink=ptex.kink;
/* TODO: vertex groups */
if(between){ if(between){
int w=0; int w=0;
@ -3708,46 +3780,33 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i
} }
par = keys; par = keys;
//if(totparent){
// if(p-totpart>=totparent){ if(vel)
// key.time=t; copy_particle_key(&tstate, state, 1);
// psys_get_particle_on_path(ob,psys,totpart+cpa->parent,&key,1);
// bti->convert_dynamic_key(bsys,&key,par,cpar);
// }
// else
// par=0;
//}
//else
// DB_get_key_on_path(bsys,cpa->parent,t,par,cpar);
/* apply different deformations to the child path */ /* apply different deformations to the child path */
if(part->kink) do_child_modifiers(scene, ob, psys, part, &ptex, par, par->rot, cpa, orco, state, t);
do_prekink(state, par, par->rot, t, part->kink_freq * pa_kink, part->kink_shape,
part->kink_amp, part->kink, part->kink_axis, ob->obmat);
do_clump(state, par, t, part->clumpfac, part->clumppow, 1.0f); /* try to estimate correct velocity */
if(vel){
ParticleKey tstate;
float length = VecLength(state->vel);
if(part->rough1 != 0.0) if(t>=0.001f){
do_rough(orco, t, part->rough1, part->rough1_size, 0.0, state); tstate.time=t-0.001f;
psys_get_particle_on_path(scene,ob,psys,p,&tstate,0);
VECSUB(state->vel,state->co,tstate.co);
Normalize(state->vel);
}
else{
tstate.time=t+0.001f;
psys_get_particle_on_path(scene, ob,psys,p,&tstate,0);
VECSUB(state->vel,tstate.co,state->co);
Normalize(state->vel);
}
if(part->rough2 != 0.0) VecMulf(state->vel, length);
do_rough(cpa->rand, t, part->rough2, part->rough2_size, part->rough2_thres, state); }
if(part->rough_end != 0.0)
do_rough_end(cpa->rand, t, part->rough_end, part->rough_end_shape, state, par);
//if(vel){
// if(t>=0.001f){
// tstate.time=t-0.001f;
// psys_get_particle_on_path(scene,ob,psys,p,&tstate,0);
// VECSUB(state->vel,state->co,tstate.co);
// }
// else{
// tstate.time=t+0.001f;
// psys_get_particle_on_path(scene, ob,psys,p,&tstate,0);
// VECSUB(state->vel,tstate.co,state->co);
// }
//}
} }
} }
/* gets particle's state at a time, returns 1 if particle exists and can be seen and 0 if not */ /* gets particle's state at a time, returns 1 if particle exists and can be seen and 0 if not */
@ -3774,7 +3833,7 @@ int psys_get_particle_state(struct Scene *scene, Object *ob, ParticleSystem *psy
pa=psys->particles+p; pa=psys->particles+p;
if(between){ if(between){
state->time = psys_get_child_time(psys,&psys->child[p-totpart],cfra); state->time = psys_get_child_time(psys,&psys->child[p-totpart],cfra,NULL,NULL);
if(always==0) if(always==0)
if((state->time<0.0 && (part->flag & PART_UNBORN)==0) if((state->time<0.0 && (part->flag & PART_UNBORN)==0)

@ -2205,8 +2205,10 @@ void psys_get_pointcache_start_end(Scene *scene, ParticleSystem *psys, int *sfra
*sfra = MAX2(1, (int)part->sta); *sfra = MAX2(1, (int)part->sta);
*efra = MIN2((int)(part->end + part->lifetime + 1.0), scene->r.efra); *efra = MIN2((int)(part->end + part->lifetime + 1.0), scene->r.efra);
} }
static void particle_write_state(int index, ParticleSystem *psys, float *data) static void particle_write_state(int index, void *psys_ptr, float *data)
{ {
ParticleSystem *psys= psys_ptr;
memcpy(data, (float *)(&(psys->particles+index)->state), sizeof(ParticleKey)); memcpy(data, (float *)(&(psys->particles+index)->state), sizeof(ParticleKey));
} }
static void particle_read_state(int index, void *psys_ptr, float *data) static void particle_read_state(int index, void *psys_ptr, float *data)
@ -2225,7 +2227,7 @@ static void particle_cache_interpolate(int index, void *psys_ptr, float frs_sec,
ParticleSystem *psys= psys_ptr; ParticleSystem *psys= psys_ptr;
ParticleData *pa = psys->particles + index; ParticleData *pa = psys->particles + index;
ParticleKey keys[4]; ParticleKey keys[4];
float dfra, cfra1f = (float)cfra1, cfra2f(float); float dfra;
cfra = MIN2(cfra, pa->dietime); cfra = MIN2(cfra, pa->dietime);
cfra1 = MIN2(cfra1, pa->dietime); cfra1 = MIN2(cfra1, pa->dietime);
@ -4254,7 +4256,7 @@ static void psys_update_path_cache(Scene *scene, Object *ob, ParticleSystemModif
} }
} }
if((part->type==PART_HAIR || psys->flag&PSYS_KEYED) && ( psys_in_edit_mode(scene, psys) || (part->type==PART_HAIR if((part->type==PART_HAIR || psys->flag&PSYS_KEYED || psys->pointcache->flag & PTCACHE_BAKED) && ( psys_in_edit_mode(scene, psys) || (part->type==PART_HAIR
|| (part->ren_as == PART_DRAW_PATH && (part->draw_as == PART_DRAW_REND || psys->renderdata))))){ || (part->ren_as == PART_DRAW_PATH && (part->draw_as == PART_DRAW_REND || psys->renderdata))))){
psys_cache_paths(scene, ob, psys, cfra, 0); psys_cache_paths(scene, ob, psys, cfra, 0);
@ -4371,8 +4373,10 @@ static void cached_step(Scene *scene, Object *ob, ParticleSystemModifierData *ps
dietime = birthtime + (1 + pa->loop) * (pa->dietime - pa->time); dietime = birthtime + (1 + pa->loop) * (pa->dietime - pa->time);
/* update alive status and push events */ /* update alive status and push events */
if(pa->time > cfra) if(pa->time > cfra) {
pa->alive = PARS_UNBORN; pa->alive = PARS_UNBORN;
reset_particle(scene, pa, psys, psmd, ob, 0.0f, cfra, NULL, NULL, NULL);
}
else if(dietime <= cfra){ else if(dietime <= cfra){
if(dietime > psys->cfra){ if(dietime > psys->cfra){
state.time = dietime; state.time = dietime;
@ -4406,6 +4410,8 @@ static void cached_step(Scene *scene, Object *ob, ParticleSystemModifierData *ps
distribute_particles(scene, ob, psys, PART_FROM_CHILD); distribute_particles(scene, ob, psys, PART_FROM_CHILD);
} }
psys_update_path_cache(scene, ob,psmd,psys,cfra);
if(vg_size) if(vg_size)
MEM_freeN(vg_size); MEM_freeN(vg_size);
} }
@ -4433,10 +4439,17 @@ void psys_changed_type(ParticleSystem *psys)
if(ELEM3(part->draw_as, PART_DRAW_NOT, PART_DRAW_REND, PART_DRAW_PATH)==0) if(ELEM3(part->draw_as, PART_DRAW_NOT, PART_DRAW_REND, PART_DRAW_PATH)==0)
part->draw_as = PART_DRAW_REND; part->draw_as = PART_DRAW_REND;
CLAMP(part->path_start, 0.0f, 100.0f);
CLAMP(part->path_end, 0.0f, 100.0f);
} }
else else {
free_hair(psys, 1); free_hair(psys, 1);
CLAMP(part->path_start, part->sta, part->end + part->lifetime);
CLAMP(part->path_end, part->sta, part->end + part->lifetime);
}
psys->softflag= 0; psys->softflag= 0;
psys_reset(psys, PSYS_RESET_ALL); psys_reset(psys, PSYS_RESET_ALL);
@ -4629,9 +4642,8 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
totpart = psys->part->totpart; totpart = psys->part->totpart;
totchild = get_psys_tot_child(scene, psys); totchild = get_psys_tot_child(scene, psys);
if(oldtotpart != totpart || (psys->part->childtype && oldtotchild != totchild)) { if(oldtotpart != totpart || oldtotchild != totchild) {
only_children_changed = (oldtotpart == totpart); only_children_changed = (oldtotpart == totpart);
realloc_particles(ob, psys, totpart);
alloc = 1; alloc = 1;
distr= 1; distr= 1;
init= 1; init= 1;
@ -4647,11 +4659,12 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
if(alloc) { if(alloc) {
realloc_particles(ob, psys, totpart); realloc_particles(ob, psys, totpart);
if(usecache) if(usecache && !only_children_changed)
BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_ALL, 0); BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_ALL, 0);
} }
distribute_particles(scene, ob, psys, part->from); if(!only_children_changed)
distribute_particles(scene, ob, psys, part->from);
if((psys->part->type == PART_HAIR) && !(psys->flag & PSYS_HAIR_DONE)) if((psys->part->type == PART_HAIR) && !(psys->flag & PSYS_HAIR_DONE))
/* don't generate children while growing hair - waste of time */ /* don't generate children while growing hair - waste of time */
@ -4660,7 +4673,7 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
distribute_particles(scene, ob, psys, PART_FROM_CHILD); distribute_particles(scene, ob, psys, PART_FROM_CHILD);
} }
if(only_children_changed==0) { if(!only_children_changed) {
free_keyed_keys(psys); free_keyed_keys(psys);
initialize_all_particles(ob, psys, psmd); initialize_all_particles(ob, psys, psmd);
@ -4680,19 +4693,10 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
int result = get_particles_from_cache(scene, ob, psys, (float)framenr, &old_framenr); int result = get_particles_from_cache(scene, ob, psys, (float)framenr, &old_framenr);
if(result == PTCACHE_READ_EXACT || result == PTCACHE_READ_INTERPOLATED) { if(result == PTCACHE_READ_EXACT || result == PTCACHE_READ_INTERPOLATED) {
//if(part->phystype==PART_PHYS_KEYED && psys->flag&PSYS_FIRST_KEYED) {
// psys_count_keyed_targets(ob,psys);
// set_keyed_keys(scene, ob, psys);
//}
cached_step(scene, ob, psmd, psys, cfra); cached_step(scene, ob, psmd, psys, cfra);
psys->cfra=cfra; psys->cfra=cfra;
psys->recalc = 0; psys->recalc = 0;
//if(part->phystype==PART_PHYS_KEYED && psys->flag&PSYS_FIRST_KEYED) {
// psys_update_path_cache(scene, ob, psmd, psys, framenr);
//}
cache->simframe= framenr; cache->simframe= framenr;
cache->flag |= PTCACHE_SIMULATION_VALID; cache->flag |= PTCACHE_SIMULATION_VALID;

@ -643,8 +643,8 @@ int BKE_ptcache_write_cache(PTCacheWriter *writer)
return 0; return 0;
for(i=0; i<writer->totelem; i++) { for(i=0; i<writer->totelem; i++) {
writer->set_elem(i, writer->calldata, &temp); writer->set_elem(i, writer->calldata, temp);
BKE_ptcache_file_write_floats(pf, &temp, incr); BKE_ptcache_file_write_floats(pf, temp, incr);
} }
} }
} }
@ -677,8 +677,8 @@ int BKE_ptcache_write_cache(PTCacheWriter *writer)
pmdata = pm->data; pmdata = pm->data;
for(i=0; i<writer->totelem; i++, pmdata+=incr) { for(i=0; i<writer->totelem; i++, pmdata+=incr) {
writer->set_elem(i, writer->calldata, &temp); writer->set_elem(i, writer->calldata, temp);
memcpy(pmdata, &temp, elemsize); memcpy(pmdata, temp, elemsize);
} }
pm->frame = writer->cfra; pm->frame = writer->cfra;
@ -689,8 +689,8 @@ int BKE_ptcache_write_cache(PTCacheWriter *writer)
pmdata = pm->data; pmdata = pm->data;
for(i=0; i<writer->totelem; i++, pmdata+=incr) { for(i=0; i<writer->totelem; i++, pmdata+=incr) {
writer->set_elem(i, writer->calldata, &temp); writer->set_elem(i, writer->calldata, temp);
memcpy(pmdata, &temp, elemsize); memcpy(pmdata, temp, elemsize);
} }
pm->frame = writer->cfra; pm->frame = writer->cfra;
@ -1154,6 +1154,7 @@ void BKE_ptcache_quick_cache_all(Scene *scene)
baker.progressbar=NULL; baker.progressbar=NULL;
baker.progresscontext=NULL; baker.progresscontext=NULL;
baker.render=0; baker.render=0;
baker.anim_init = 0;
baker.scene=scene; baker.scene=scene;
if(count_quick_cache(scene, &baker.quick_step)) if(count_quick_cache(scene, &baker.quick_step))
@ -1171,7 +1172,7 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker)
float frameleno = scene->r.framelen; float frameleno = scene->r.framelen;
int cfrao = CFRA; int cfrao = CFRA;
int startframe = MAXFRAME; int startframe = MAXFRAME;
int endframe = CFRA; int endframe = baker->anim_init ? scene->r.sfra : CFRA;
int bake = baker->bake; int bake = baker->bake;
int render = baker->render; int render = baker->render;
int step = baker->quick_step; int step = baker->quick_step;
@ -1209,8 +1210,13 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker)
for(pid=pidlist.first; pid; pid=pid->next) { for(pid=pidlist.first; pid; pid=pid->next) {
cache = pid->cache; cache = pid->cache;
if((cache->flag & PTCACHE_BAKED)==0) { if((cache->flag & PTCACHE_BAKED)==0) {
if(pid->type==PTCACHE_TYPE_PARTICLES) if(pid->type==PTCACHE_TYPE_PARTICLES) {
/* skip hair particles */
if(((ParticleSystem*)pid->data)->part->type == PART_HAIR)
continue;
psys_get_pointcache_start_end(scene, pid->data, &cache->startframe, &cache->endframe); psys_get_pointcache_start_end(scene, pid->data, &cache->startframe, &cache->endframe);
}
if((cache->flag & PTCACHE_REDO_NEEDED || (cache->flag & PTCACHE_SIMULATION_VALID)==0) if((cache->flag & PTCACHE_REDO_NEEDED || (cache->flag & PTCACHE_SIMULATION_VALID)==0)
&& ((cache->flag & PTCACHE_QUICK_CACHE)==0 || render || bake)) && ((cache->flag & PTCACHE_QUICK_CACHE)==0 || render || bake))
@ -1265,6 +1271,10 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker)
BKE_ptcache_ids_from_object(&pidlist, base->object); BKE_ptcache_ids_from_object(&pidlist, base->object);
for(pid=pidlist.first; pid; pid=pid->next) { for(pid=pidlist.first; pid; pid=pid->next) {
/* skip hair particles */
if(pid->type==PTCACHE_TYPE_PARTICLES && ((ParticleSystem*)pid->data)->part->type == PART_HAIR)
continue;
cache = pid->cache; cache = pid->cache;
if(step > 1) if(step > 1)
@ -1282,7 +1292,9 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker)
scene->r.framelen = frameleno; scene->r.framelen = frameleno;
CFRA = cfrao; CFRA = cfrao;
scene_update_for_newframe(scene, scene->lay);
if(bake) /* already on cfra unless baking */
scene_update_for_newframe(scene, scene->lay);
/* TODO: call redraw all windows somehow */ /* TODO: call redraw all windows somehow */
} }

@ -78,6 +78,8 @@ static void spacetype_free(SpaceType *st)
} }
BLI_freelistN(&st->regiontypes); BLI_freelistN(&st->regiontypes);
BLI_freelistN(&st->toolshelf);
} }
void BKE_spacetypes_free(void) void BKE_spacetypes_free(void)

@ -184,11 +184,11 @@ void seq_free_sequence(Editing *ed, Sequence *seq)
if(seq->anim) IMB_free_anim(seq->anim); if(seq->anim) IMB_free_anim(seq->anim);
//XXX if(seq->hdaudio) sound_close_hdaudio(seq->hdaudio); //XXX if(seq->hdaudio) sound_close_hdaudio(seq->hdaudio);
/* XXX if (seq->type & SEQ_EFFECT) { if (seq->type & SEQ_EFFECT) {
struct SeqEffectHandle sh = get_sequence_effect(seq); struct SeqEffectHandle sh = get_sequence_effect(seq);
sh.free(seq); sh.free(seq);
}*/ }
if (ed->act_seq==seq) if (ed->act_seq==seq)
ed->act_seq= NULL; ed->act_seq= NULL;

@ -60,6 +60,7 @@
#include "BLI_edgehash.h" #include "BLI_edgehash.h"
#include "BIF_gl.h" #include "BIF_gl.h"
#include "BIF_glutil.h"
#include "GPU_draw.h" #include "GPU_draw.h"
#include "GPU_extensions.h" #include "GPU_extensions.h"

@ -0,0 +1,85 @@
/**
* $Id: BKE_nla.h 20999 2009-06-19 04:45:56Z aligorith $
*
* ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): Joshua Leung (full recode)
*
* ***** END GPL LICENSE BLOCK *****
*/
#ifndef NLA_PRIVATE
#define NLA_PRIVATE
/* --------------- NLA Evaluation DataTypes ----------------------- */
/* used for list of strips to accumulate at current time */
typedef struct NlaEvalStrip {
struct NlaEvalStrip *next, *prev;
NlaTrack *track; /* track that this strip belongs to */
NlaStrip *strip; /* strip that's being used */
short track_index; /* the index of the track within the list */
short strip_mode; /* which end of the strip are we looking at */
float strip_time; /* time at which which strip is being evaluated */
} NlaEvalStrip;
/* NlaEvalStrip->strip_mode */
enum {
/* standard evaluation */
NES_TIME_BEFORE = -1,
NES_TIME_WITHIN,
NES_TIME_AFTER,
/* transition-strip evaluations */
NES_TIME_TRANSITION_START,
NES_TIME_TRANSITION_END,
} eNlaEvalStrip_StripMode;
/* temp channel for accumulating data from NLA (avoids needing to clear all values first) */
// TODO: maybe this will be used as the 'cache' stuff needed for editable values too?
typedef struct NlaEvalChannel {
struct NlaEvalChannel *next, *prev;
PointerRNA ptr; /* pointer to struct containing property to use */
PropertyRNA *prop; /* RNA-property type to use (should be in the struct given) */
int index; /* array index (where applicable) */
float value; /* value of this channel */
} NlaEvalChannel;
/* --------------- NLA Functions (not to be used as a proper API) ----------------------- */
/* convert from strip time <-> global time */
float nlastrip_get_frame(NlaStrip *strip, float cframe, short mode);
/* --------------- NLA Evaluation (very-private stuff) ----------------------- */
/* these functions are only defined here to avoid problems with the order in which they get defined... */
NlaEvalStrip *nlastrips_ctime_get_strip(ListBase *list, ListBase *strips, short index, float ctime);
void nlastrip_evaluate(PointerRNA *ptr, ListBase *channels, ListBase *modifiers, NlaEvalStrip *nes);
void nladata_flush_channels(ListBase *channels);
#endif // NLA_PRIVATE

@ -88,6 +88,7 @@ typedef struct BArcIterator {
StoppedFct stopped; StoppedFct stopped;
float *p, *no; float *p, *no;
float size;
int length; int length;
int index; int index;

@ -72,6 +72,9 @@ void BLI_cleanup_dir(const char *relabase, char *dir); /* same as above but adds
/* go back one directory */ /* go back one directory */
int BLI_parent_dir(char *path); int BLI_parent_dir(char *path);
/* return whether directory is root and thus has no parent dir */
int BLI_has_parent(char *path);
/** /**
* Blender's path code replacement function. * Blender's path code replacement function.
* Bases @a path strings leading with "//" by the * Bases @a path strings leading with "//" by the

@ -218,7 +218,7 @@ void BLI_builddir(char *dirname, char *relname)
{ {
struct dirent *fname; struct dirent *fname;
struct dirlink *dlink; struct dirlink *dlink;
int rellen, newnum = 0, ignore; int rellen, newnum = 0;
char buf[256]; char buf[256];
DIR *dir; DIR *dir;

@ -494,6 +494,22 @@ void BLI_makestringcode(const char *relfile, char *file)
} }
} }
int BLI_has_parent(char *path)
{
int len;
int slashes = 0;
BLI_clean(path);
BLI_add_slash(path);
len = strlen(path)-1;
while (len) {
if ((path[len] == '\\') || (path[len] == '/'))
slashes++;
len--;
}
return slashes > 1;
}
int BLI_parent_dir(char *path) int BLI_parent_dir(char *path)
{ {
#ifdef WIN32 #ifdef WIN32
@ -738,9 +754,9 @@ void BLI_splitdirstring(char *di, char *fi)
void BLI_getlastdir(const char* dir, char *last, int maxlen) void BLI_getlastdir(const char* dir, char *last, int maxlen)
{ {
char *s = dir; const char *s = dir;
char *lslash = NULL; const char *lslash = NULL;
char *prevslash = NULL; const char *prevslash = NULL;
while (*s) { while (*s) {
if ((*s == '\\') || (*s == '/')) { if ((*s == '\\') || (*s == '/')) {
prevslash = lslash; prevslash = lslash;

@ -1667,10 +1667,26 @@ static void lib_link_constraint_channels(FileData *fd, ID *id, ListBase *chanbas
/* Data Linking ----------------------------- */ /* Data Linking ----------------------------- */
static void lib_link_fmodifiers(FileData *fd, ID *id, ListBase *list)
{
FModifier *fcm;
for (fcm= list->first; fcm; fcm= fcm->next) {
/* data for specific modifiers */
switch (fcm->type) {
case FMODIFIER_TYPE_PYTHON:
{
FMod_Python *data= (FMod_Python *)fcm->data;
data->script = newlibadr(fd, id->lib, data->script);
}
break;
}
}
}
static void lib_link_fcurves(FileData *fd, ID *id, ListBase *list) static void lib_link_fcurves(FileData *fd, ID *id, ListBase *list)
{ {
FCurve *fcu; FCurve *fcu;
FModifier *fcm;
/* relink ID-block references... */ /* relink ID-block references... */
for (fcu= list->first; fcu; fcu= fcu->next) { for (fcu= list->first; fcu; fcu= fcu->next) {
@ -1684,16 +1700,45 @@ static void lib_link_fcurves(FileData *fd, ID *id, ListBase *list)
} }
/* modifiers */ /* modifiers */
for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next) { lib_link_fmodifiers(fd, id, &fcu->modifiers);
/* data for specific modifiers */ }
switch (fcm->type) { }
case FMODIFIER_TYPE_PYTHON:
{
FMod_Python *data= (FMod_Python *)fcm->data; /* NOTE: this assumes that link_list has already been called on the list */
data->script = newlibadr(fd, id->lib, data->script); static void direct_link_fmodifiers(FileData *fd, ListBase *list)
} {
break; FModifier *fcm;
for (fcm= list->first; fcm; fcm= fcm->next) {
/* relink general data */
fcm->data = newdataadr(fd, fcm->data);
fcm->edata= NULL;
/* do relinking of data for specific types */
switch (fcm->type) {
case FMODIFIER_TYPE_GENERATOR:
{
FMod_Generator *data= (FMod_Generator *)fcm->data;
data->coefficients= newdataadr(fd, data->coefficients);
} }
break;
case FMODIFIER_TYPE_ENVELOPE:
{
FMod_Envelope *data= (FMod_Envelope *)fcm->data;
data->data= newdataadr(fd, data->data);
}
break;
case FMODIFIER_TYPE_PYTHON:
{
FMod_Python *data= (FMod_Python *)fcm->data;
data->prop = newdataadr(fd, data->prop);
IDP_DirectLinkProperty(data->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
}
break;
} }
} }
} }
@ -1702,7 +1747,6 @@ static void lib_link_fcurves(FileData *fd, ID *id, ListBase *list)
static void direct_link_fcurves(FileData *fd, ListBase *list) static void direct_link_fcurves(FileData *fd, ListBase *list)
{ {
FCurve *fcu; FCurve *fcu;
FModifier *fcm;
/* link F-Curve data to F-Curve again (non ID-libs) */ /* link F-Curve data to F-Curve again (non ID-libs) */
for (fcu= list->first; fcu; fcu= fcu->next) { for (fcu= list->first; fcu; fcu= fcu->next) {
@ -1730,37 +1774,7 @@ static void direct_link_fcurves(FileData *fd, ListBase *list)
/* modifiers */ /* modifiers */
link_list(fd, &fcu->modifiers); link_list(fd, &fcu->modifiers);
for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next) { direct_link_fmodifiers(fd, &fcu->modifiers);
/* relink general data */
fcm->data = newdataadr(fd, fcm->data);
fcm->edata= NULL;
/* do relinking of data for specific types */
switch (fcm->type) {
case FMODIFIER_TYPE_GENERATOR:
{
FMod_Generator *data= (FMod_Generator *)fcm->data;
data->coefficients= newdataadr(fd, data->coefficients);
}
break;
case FMODIFIER_TYPE_ENVELOPE:
{
FMod_Envelope *data= (FMod_Envelope *)fcm->data;
data->data= newdataadr(fd, data->data);
}
break;
case FMODIFIER_TYPE_PYTHON:
{
FMod_Python *data= (FMod_Python *)fcm->data;
data->prop = newdataadr(fd, data->prop);
IDP_DirectLinkProperty(data->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
}
break;
}
}
} }
} }
@ -1812,6 +1826,65 @@ static void direct_link_action(FileData *fd, bAction *act)
} }
} }
static void lib_link_nladata_strips(FileData *fd, ID *id, ListBase *list)
{
NlaStrip *strip;
for (strip= list->first; strip; strip= strip->next) {
/* check strip's children */
lib_link_nladata_strips(fd, id, &strip->strips);
/* reassign the counted-reference to action */
strip->act = newlibadr_us(fd, id->lib, strip->act);
}
}
static void lib_link_nladata(FileData *fd, ID *id, ListBase *list)
{
NlaTrack *nlt;
/* we only care about the NLA strips inside the tracks */
for (nlt= list->first; nlt; nlt= nlt->next) {
lib_link_nladata_strips(fd, id, &nlt->strips);
}
}
/* This handles Animato NLA-Strips linking
* NOTE: this assumes that link_list has already been called on the list
*/
static void direct_link_nladata_strips(FileData *fd, ListBase *list)
{
NlaStrip *strip;
for (strip= list->first; strip; strip= strip->next) {
/* strip's child strips */
link_list(fd, &strip->strips);
direct_link_nladata_strips(fd, &strip->strips);
/* strip's F-Curves */
link_list(fd, &strip->fcurves);
direct_link_fcurves(fd, &strip->fcurves);
/* strip's F-Modifiers */
link_list(fd, &strip->modifiers);
direct_link_fcurves(fd, &strip->modifiers);
}
}
/* NOTE: this assumes that link_list has already been called on the list */
static void direct_link_nladata(FileData *fd, ListBase *list)
{
NlaTrack *nlt;
for (nlt= list->first; nlt; nlt= nlt->next) {
/* relink list of strips */
link_list(fd, &nlt->strips);
/* relink strip data */
direct_link_nladata_strips(fd, &nlt->strips);
}
}
/* ------- */ /* ------- */
static void lib_link_keyingsets(FileData *fd, ID *id, ListBase *list) static void lib_link_keyingsets(FileData *fd, ID *id, ListBase *list)
@ -1854,6 +1927,7 @@ static void lib_link_animdata(FileData *fd, ID *id, AnimData *adt)
/* link action data */ /* link action data */
adt->action= newlibadr_us(fd, id->lib, adt->action); adt->action= newlibadr_us(fd, id->lib, adt->action);
adt->tmpact= newlibadr_us(fd, id->lib, adt->tmpact);
/* link drivers */ /* link drivers */
lib_link_fcurves(fd, id, &adt->drivers); lib_link_fcurves(fd, id, &adt->drivers);
@ -1861,7 +1935,7 @@ static void lib_link_animdata(FileData *fd, ID *id, AnimData *adt)
/* overrides don't have lib-link for now, so no need to do anything */ /* overrides don't have lib-link for now, so no need to do anything */
/* link NLA-data */ /* link NLA-data */
// TODO... lib_link_nladata(fd, id, &adt->nla_tracks);
} }
static void direct_link_animdata(FileData *fd, AnimData *adt) static void direct_link_animdata(FileData *fd, AnimData *adt)
@ -1878,7 +1952,12 @@ static void direct_link_animdata(FileData *fd, AnimData *adt)
// TODO... // TODO...
/* link NLA-data */ /* link NLA-data */
// TODO... link_list(fd, &adt->nla_tracks);
direct_link_nladata(fd, &adt->nla_tracks);
/* clear temp pointers that may have been set... */
// TODO: it's probably only a small cost to reload this anyway...
adt->actstrip= NULL;
} }
/* ************ READ NODE TREE *************** */ /* ************ READ NODE TREE *************** */
@ -2641,6 +2720,7 @@ static void direct_link_image(FileData *fd, Image *ima)
ima->anim= NULL; ima->anim= NULL;
ima->rr= NULL; ima->rr= NULL;
ima->repbind= NULL; ima->repbind= NULL;
ima->render_text= newdataadr(fd, ima->render_text);
ima->packedfile = direct_link_packedfile(fd, ima->packedfile); ima->packedfile = direct_link_packedfile(fd, ima->packedfile);
ima->preview = direct_link_preview_image(fd, ima->preview); ima->preview = direct_link_preview_image(fd, ima->preview);
@ -4472,13 +4552,10 @@ void lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *curscene)
SpaceFile *sfile= (SpaceFile *)sl; SpaceFile *sfile= (SpaceFile *)sl;
sfile->files= NULL; sfile->files= NULL;
sfile->folders_prev= NULL;
sfile->folders_next= NULL;
sfile->params= NULL; sfile->params= NULL;
sfile->op= NULL; sfile->op= NULL;
/* XXX needs checking - best solve in filesel itself
if(sfile->libfiledata)
BLO_blendhandle_close(sfile->libfiledata);
sfile->libfiledata= 0;
*/
} }
else if(sl->spacetype==SPACE_IMASEL) { else if(sl->spacetype==SPACE_IMASEL) {
SpaceImaSel *simasel= (SpaceImaSel *)sl; SpaceImaSel *simasel= (SpaceImaSel *)sl;
@ -4710,6 +4787,11 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
sipo->ads= newdataadr(fd, sipo->ads); sipo->ads= newdataadr(fd, sipo->ads);
sipo->ghostCurves.first= sipo->ghostCurves.last= NULL; sipo->ghostCurves.first= sipo->ghostCurves.last= NULL;
} }
else if (sl->spacetype==SPACE_NLA) {
SpaceNla *snla= (SpaceNla*)sl;
snla->ads= newdataadr(fd, snla->ads);
}
else if (sl->spacetype==SPACE_OUTLINER) { else if (sl->spacetype==SPACE_OUTLINER) {
SpaceOops *soops= (SpaceOops*) sl; SpaceOops *soops= (SpaceOops*) sl;
@ -9011,14 +9093,10 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
*/ */
//do_versions_ipos_to_animato(main); //do_versions_ipos_to_animato(main);
/* struct audio data moved to renderdata */ /* toolsettings */
for(scene= main->scene.first; scene; scene= scene->id.next) { for(scene= main->scene.first; scene; scene= scene->id.next)
scene->r.audio = scene->audio; scene->r.audio = scene->audio;
if(!scene->toolsettings->uv_selectmode)
scene->toolsettings->uv_selectmode= UV_SELECT_VERTEX;
}
/* shader, composit and texture node trees have id.name empty, put something in /* shader, composit and texture node trees have id.name empty, put something in
* to have them show in RNA viewer and accessible otherwise. * to have them show in RNA viewer and accessible otherwise.
*/ */
@ -9057,6 +9135,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
part->draw_as = PART_DRAW_REND; part->draw_as = PART_DRAW_REND;
} }
} }
part->path_end = 1.0f;
} }
/* set old pointcaches to have disk cache flag */ /* set old pointcaches to have disk cache flag */
for(ob = main->object.first; ob; ob= ob->id.next) { for(ob = main->object.first; ob; ob= ob->id.next) {
@ -9086,7 +9165,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
void *olddata = ob->data; void *olddata = ob->data;
ob->data = me; ob->data = me;
if(me && me->mr) { if(me && me->id.lib==NULL && me->mr) { /* XXX - library meshes crash on loading most yoFrankie levels, the multires pointer gets invalid - Campbell */
MultiresLevel *lvl; MultiresLevel *lvl;
ModifierData *md; ModifierData *md;
MultiresModifierData *mmd; MultiresModifierData *mmd;
@ -9152,10 +9231,19 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
for(sce = main->scene.first; sce; sce = sce->id.next) { for(sce = main->scene.first; sce; sce = sce->id.next) {
ts= sce->toolsettings; ts= sce->toolsettings;
if(ts->normalsize == 0.0) { if(ts->normalsize == 0.0 || !ts->uv_selectmode || ts->vgroup_weight == 0.0) {
ts->normalsize= 0.1f; ts->normalsize= 0.1f;
ts->selectmode= SCE_SELECT_VERTEX; ts->selectmode= SCE_SELECT_VERTEX;
/* autokeying - setting should be taken from the user-prefs
* but the userprefs version may not have correct flags set
* (i.e. will result in blank box when enabled)
*/
ts->autokey_mode= U.autokey_mode; ts->autokey_mode= U.autokey_mode;
if (ts->autokey_mode == 0)
ts->autokey_mode= 2; /* 'add/replace' but not on */
ts->uv_selectmode= UV_SELECT_VERTEX;
ts->vgroup_weight= 1.0f;
} }
} }
} }
@ -9488,12 +9576,27 @@ static void expand_keyingsets(FileData *fd, Main *mainvar, ListBase *list)
} }
} }
static void expand_animdata_nlastrips(FileData *fd, Main *mainvar, ListBase *list)
{
NlaStrip *strip;
for (strip= list->first; strip; strip= strip->next) {
/* check child strips */
expand_animdata_nlastrips(fd, mainvar, &strip->strips);
/* relink referenced action */
expand_doit(fd, mainvar, strip->act);
}
}
static void expand_animdata(FileData *fd, Main *mainvar, AnimData *adt) static void expand_animdata(FileData *fd, Main *mainvar, AnimData *adt)
{ {
FCurve *fcd; FCurve *fcd;
NlaTrack *nlt;
/* own action */ /* own action */
expand_doit(fd, mainvar, adt->action); expand_doit(fd, mainvar, adt->action);
expand_doit(fd, mainvar, adt->tmpact);
/* drivers - assume that these F-Curves have driver data to be in this list... */ /* drivers - assume that these F-Curves have driver data to be in this list... */
for (fcd= adt->drivers.first; fcd; fcd= fcd->next) { for (fcd= adt->drivers.first; fcd; fcd= fcd->next) {
@ -9503,6 +9606,10 @@ static void expand_animdata(FileData *fd, Main *mainvar, AnimData *adt)
for (dtar= driver->targets.first; dtar; dtar= dtar->next) for (dtar= driver->targets.first; dtar; dtar= dtar->next)
expand_doit(fd, mainvar, dtar->id); expand_doit(fd, mainvar, dtar->id);
} }
/* nla-data - referenced actions */
for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next)
expand_animdata_nlastrips(fd, mainvar, &nlt->strips);
} }
static void expand_particlesettings(FileData *fd, Main *mainvar, ParticleSettings *part) static void expand_particlesettings(FileData *fd, Main *mainvar, ParticleSettings *part)

@ -781,10 +781,59 @@ static void write_actuators(WriteData *wd, ListBase *lb)
} }
} }
static void write_fmodifiers(WriteData *wd, ListBase *fmodifiers)
{
FModifier *fcm;
/* Modifiers */
for (fcm= fmodifiers->first; fcm; fcm= fcm->next) {
FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
/* Write the specific data */
if (fmi && fcm->data) {
/* firstly, just write the plain fmi->data struct */
writestruct(wd, DATA, fmi->structName, 1, fcm->data);
/* do any modifier specific stuff */
switch (fcm->type) {
case FMODIFIER_TYPE_GENERATOR:
{
FMod_Generator *data= (FMod_Generator *)fcm->data;
/* write coefficients array */
if (data->coefficients)
writedata(wd, DATA, sizeof(float)*(data->arraysize), data->coefficients);
}
break;
case FMODIFIER_TYPE_ENVELOPE:
{
FMod_Envelope *data= (FMod_Envelope *)fcm->data;
/* write envelope data */
if (data->data)
writedata(wd, DATA, sizeof(FCM_EnvelopeData)*(data->totvert), data->data);
}
break;
case FMODIFIER_TYPE_PYTHON:
{
FMod_Python *data = (FMod_Python *)fcm->data;
/* Write ID Properties -- and copy this comment EXACTLY for easy finding
of library blocks that implement this.*/
IDP_WriteProperty(data->prop, wd);
}
break;
}
}
/* Write the modifier */
writestruct(wd, DATA, "FModifier", 1, fcm);
}
}
static void write_fcurves(WriteData *wd, ListBase *fcurves) static void write_fcurves(WriteData *wd, ListBase *fcurves)
{ {
FCurve *fcu; FCurve *fcu;
FModifier *fcm;
for (fcu=fcurves->first; fcu; fcu=fcu->next) { for (fcu=fcurves->first; fcu; fcu=fcu->next) {
/* F-Curve */ /* F-Curve */
@ -815,50 +864,8 @@ static void write_fcurves(WriteData *wd, ListBase *fcurves)
} }
} }
/* Modifiers */ /* write F-Modifiers */
for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next) { write_fmodifiers(wd, &fcu->modifiers);
FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
/* Write the specific data */
if (fmi && fcm->data) {
/* firstly, just write the plain fmi->data struct */
writestruct(wd, DATA, fmi->structName, 1, fcm->data);
/* do any modifier specific stuff */
switch (fcm->type) {
case FMODIFIER_TYPE_GENERATOR:
{
FMod_Generator *data= (FMod_Generator *)fcm->data;
/* write coefficients array */
if (data->coefficients)
writedata(wd, DATA, sizeof(float)*(data->arraysize), data->coefficients);
}
break;
case FMODIFIER_TYPE_ENVELOPE:
{
FMod_Envelope *data= (FMod_Envelope *)fcm->data;
/* write envelope data */
if (data->data)
writedata(wd, DATA, sizeof(FCM_EnvelopeData)*(data->totvert), data->data);
}
break;
case FMODIFIER_TYPE_PYTHON:
{
FMod_Python *data = (FMod_Python *)fcm->data;
/* Write ID Properties -- and copy this comment EXACTLY for easy finding
of library blocks that implement this.*/
IDP_WriteProperty(data->prop, wd);
}
break;
}
}
/* Write the modifier */
writestruct(wd, DATA, "FModifier", 1, fcm);
}
} }
} }
@ -909,6 +916,37 @@ static void write_keyingsets(WriteData *wd, ListBase *list)
} }
} }
static void write_nlastrips(WriteData *wd, ListBase *strips)
{
NlaStrip *strip;
for (strip= strips->first; strip; strip= strip->next) {
/* write the strip first */
writestruct(wd, DATA, "NlaStrip", 1, strip);
/* write the strip's F-Curves and modifiers */
write_fcurves(wd, &strip->fcurves);
write_fmodifiers(wd, &strip->modifiers);
/* write the strip's children */
write_nlastrips(wd, &strip->strips);
}
}
static void write_nladata(WriteData *wd, ListBase *nlabase)
{
NlaTrack *nlt;
/* write all the tracks */
for (nlt= nlabase->first; nlt; nlt= nlt->next) {
/* write the track first */
writestruct(wd, DATA, "NlaTrack", 1, nlt);
/* write the track's strips */
write_nlastrips(wd, &nlt->strips);
}
}
static void write_animdata(WriteData *wd, AnimData *adt) static void write_animdata(WriteData *wd, AnimData *adt)
{ {
AnimOverride *aor; AnimOverride *aor;
@ -920,14 +958,17 @@ static void write_animdata(WriteData *wd, AnimData *adt)
write_fcurves(wd, &adt->drivers); write_fcurves(wd, &adt->drivers);
/* write overrides */ /* write overrides */
// FIXME: are these needed?
for (aor= adt->overrides.first; aor; aor= aor->next) { for (aor= adt->overrides.first; aor; aor= aor->next) {
/* overrides consist of base data + rna_path */ /* overrides consist of base data + rna_path */
writestruct(wd, DATA, "AnimOverride", 1, aor); writestruct(wd, DATA, "AnimOverride", 1, aor);
writedata(wd, DATA, strlen(aor->rna_path)+1, aor->rna_path); writedata(wd, DATA, strlen(aor->rna_path)+1, aor->rna_path);
} }
// TODO write the remaps (if they are needed)
/* write NLA data */ /* write NLA data */
// XXX todo... write_nladata(wd, &adt->nla_tracks);
} }
static void write_constraints(WriteData *wd, ListBase *conlist) static void write_constraints(WriteData *wd, ListBase *conlist)
@ -1439,7 +1480,10 @@ static void write_images(WriteData *wd, ListBase *idbase)
write_previews(wd, ima->preview); write_previews(wd, ima->preview);
} /* exception: render text only saved in undo files (wd->current) */
if (ima->render_text && wd->current)
writedata(wd, DATA, IMA_RW_MAXTEXT, ima->render_text);
}
ima= ima->id.next; ima= ima->id.next;
} }
/* flush helps the compression for undo-save */ /* flush helps the compression for undo-save */
@ -1896,7 +1940,10 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
writestruct(wd, DATA, "SpaceSound", 1, sl); writestruct(wd, DATA, "SpaceSound", 1, sl);
} }
else if(sl->spacetype==SPACE_NLA){ else if(sl->spacetype==SPACE_NLA){
writestruct(wd, DATA, "SpaceNla", 1, sl); SpaceNla *snla= (SpaceNla *)sl;
writestruct(wd, DATA, "SpaceNla", 1, snla);
if(snla->ads) writestruct(wd, DATA, "bDopeSheet", 1, snla->ads);
} }
else if(sl->spacetype==SPACE_TIME){ else if(sl->spacetype==SPACE_TIME){
writestruct(wd, DATA, "SpaceTime", 1, sl); writestruct(wd, DATA, "SpaceTime", 1, sl);

@ -64,6 +64,10 @@ IF(WITH_FFMPEG)
ADD_DEFINITIONS(-DWITH_FFMPEG) ADD_DEFINITIONS(-DWITH_FFMPEG)
ENDIF(WITH_FFMPEG) ENDIF(WITH_FFMPEG)
IF(NOT WITH_ELBEEM)
ADD_DEFINITIONS(-DDISABLE_ELBEEM)
ENDIF(NOT WITH_ELBEEM)
IF(WITH_PYTHON) IF(WITH_PYTHON)
SET(INC ${INC} ${PYTHON_INC}) SET(INC ${INC} ${PYTHON_INC})
ELSE(WITH_PYTHON) ELSE(WITH_PYTHON)

@ -63,9 +63,10 @@
#include "RNA_access.h" #include "RNA_access.h"
#include "RNA_define.h" #include "RNA_define.h"
#include "BKE_animsys.h"
#include "BKE_action.h" #include "BKE_action.h"
#include "BKE_depsgraph.h" #include "BKE_depsgraph.h"
#include "BKE_ipo.h" #include "BKE_fcurve.h"
#include "BKE_key.h" #include "BKE_key.h"
#include "BKE_material.h" #include "BKE_material.h"
#include "BKE_object.h" #include "BKE_object.h"
@ -87,43 +88,16 @@
/* ************************************************************************** */ /* ************************************************************************** */
/* CHANNELS API */ /* CHANNELS API */
/* -------------------------- Internal Macros ------------------------------- */
/* set/clear/toggle macro
* - channel - channel with a 'flag' member that we're setting
* - smode - 0=clear, 1=set, 2=toggle
* - sflag - bitflag to set
*/
#define ACHANNEL_SET_FLAG(channel, smode, sflag) \
{ \
if (smode == ACHANNEL_SETFLAG_TOGGLE) (channel)->flag ^= (sflag); \
else if (smode == ACHANNEL_SETFLAG_ADD) (channel)->flag |= (sflag); \
else (channel)->flag &= ~(sflag); \
}
/* set/clear/toggle macro, where the flag is negative
* - channel - channel with a 'flag' member that we're setting
* - smode - 0=clear, 1=set, 2=toggle
* - sflag - bitflag to set
*/
#define ACHANNEL_SET_FLAG_NEG(channel, smode, sflag) \
{ \
if (smode == ACHANNEL_SETFLAG_TOGGLE) (channel)->flag ^= (sflag); \
else if (smode == ACHANNEL_SETFLAG_ADD) (channel)->flag &= ~(sflag); \
else (channel)->flag |= (sflag); \
}
/* -------------------------- Exposed API ----------------------------------- */ /* -------------------------- Exposed API ----------------------------------- */
/* Set the given animation-channel as the active one for the active context */ /* Set the given animation-channel as the active one for the active context */
void ANIM_set_active_channel (void *data, short datatype, int filter, void *channel_data, short channel_type) void ANIM_set_active_channel (bAnimContext *ac, void *data, short datatype, int filter, void *channel_data, short channel_type)
{ {
ListBase anim_data = {NULL, NULL}; ListBase anim_data = {NULL, NULL};
bAnimListElem *ale; bAnimListElem *ale;
/* try to build list of filtered items */ /* try to build list of filtered items */
// XXX we don't need/supply animcontext for now, since in this case, there's nothing really essential there that isn't already covered ANIM_animdata_filter(ac, &anim_data, filter, data, datatype);
ANIM_animdata_filter(NULL, &anim_data, filter, data, datatype);
if (anim_data.first == NULL) if (anim_data.first == NULL)
return; return;
@ -149,11 +123,18 @@ void ANIM_set_active_channel (void *data, short datatype, int filter, void *chan
ACHANNEL_SET_FLAG(fcu, ACHANNEL_SETFLAG_CLEAR, FCURVE_ACTIVE); ACHANNEL_SET_FLAG(fcu, ACHANNEL_SETFLAG_CLEAR, FCURVE_ACTIVE);
} }
break; break;
case ANIMTYPE_NLATRACK:
{
NlaTrack *nlt= (NlaTrack *)ale->data;
ACHANNEL_SET_FLAG(nlt, ACHANNEL_SETFLAG_CLEAR, NLATRACK_ACTIVE);
}
break;
} }
} }
/* set active flag */ /* set active flag */
if (channel_data) { if (channel_data != NULL) {
switch (channel_type) { switch (channel_type) {
case ANIMTYPE_GROUP: case ANIMTYPE_GROUP:
{ {
@ -167,6 +148,12 @@ void ANIM_set_active_channel (void *data, short datatype, int filter, void *chan
fcu->flag |= FCURVE_ACTIVE; fcu->flag |= FCURVE_ACTIVE;
} }
break; break;
case ANIMTYPE_NLATRACK:
{
NlaTrack *nlt= (NlaTrack *)channel_data;
nlt->flag |= NLATRACK_ACTIVE;
}
break;
} }
} }
@ -217,6 +204,10 @@ void ANIM_deselect_anim_channels (void *data, short datatype, short test, short
if (ale->flag & FCURVE_SELECTED) if (ale->flag & FCURVE_SELECTED)
sel= ACHANNEL_SETFLAG_CLEAR; sel= ACHANNEL_SETFLAG_CLEAR;
break; break;
case ANIMTYPE_NLATRACK:
if (ale->flag & NLATRACK_SELECTED)
sel= ACHANNEL_SETFLAG_CLEAR;
break;
} }
} }
} }
@ -263,6 +254,14 @@ void ANIM_deselect_anim_channels (void *data, short datatype, short test, short
fcu->flag &= ~FCURVE_ACTIVE; fcu->flag &= ~FCURVE_ACTIVE;
} }
break; break;
case ANIMTYPE_NLATRACK:
{
NlaTrack *nlt= (NlaTrack *)ale->data;
ACHANNEL_SET_FLAG(nlt, sel, NLATRACK_SELECTED);
nlt->flag &= ~NLATRACK_ACTIVE;
}
break;
} }
} }
@ -273,6 +272,47 @@ void ANIM_deselect_anim_channels (void *data, short datatype, short test, short
/* ************************************************************************** */ /* ************************************************************************** */
/* OPERATORS */ /* OPERATORS */
/* ****************** Operator Utilities ********************************** */
/* poll callback for being in an Animation Editor channels list region */
int animedit_poll_channels_active (bContext *C)
{
ScrArea *sa= CTX_wm_area(C);
/* channels region test */
// TODO: could enhance with actually testing if channels region?
if (ELEM(NULL, sa, CTX_wm_region(C)))
return 0;
/* animation editor test */
if (ELEM3(sa->spacetype, SPACE_ACTION, SPACE_IPO, SPACE_NLA) == 0)
return 0;
return 1;
}
/* poll callback for Animation Editor channels list region + not in NLA-tweakmode for NLA */
int animedit_poll_channels_nla_tweakmode_off (bContext *C)
{
ScrArea *sa= CTX_wm_area(C);
Scene *scene = CTX_data_scene(C);
/* channels region test */
// TODO: could enhance with actually testing if channels region?
if (ELEM(NULL, sa, CTX_wm_region(C)))
return 0;
/* animation editor test */
if (ELEM3(sa->spacetype, SPACE_ACTION, SPACE_IPO, SPACE_NLA) == 0)
return 0;
/* NLA TweakMode test */
if (sa->spacetype == SPACE_NLA) {
if ((scene == NULL) || (scene->flag & SCE_NLA_EDIT_ON))
return 0;
}
return 1;
}
/* ****************** Rearrange Channels Operator ******************* */ /* ****************** Rearrange Channels Operator ******************* */
/* This operator only works for Action Editor mode for now, as having it elsewhere makes things difficult */ /* This operator only works for Action Editor mode for now, as having it elsewhere makes things difficult */
@ -575,8 +615,8 @@ static int animchannels_rearrange_exec(bContext *C, wmOperator *op)
mode= RNA_enum_get(op->ptr, "direction"); mode= RNA_enum_get(op->ptr, "direction");
rearrange_action_channels(&ac, mode); rearrange_action_channels(&ac, mode);
/* set notifier tha things have changed */ /* send notifier that things have changed */
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_CHANNELS); WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_EDIT, NULL);
return OPERATOR_FINISHED; return OPERATOR_FINISHED;
} }
@ -652,6 +692,121 @@ void ANIM_OT_channels_move_bottom (wmOperatorType *ot)
#endif // XXX old animation system - needs to be updated for new system... #endif // XXX old animation system - needs to be updated for new system...
/* ******************** Delete Channel Operator *********************** */
static int animchannels_delete_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
/* cannot delete in shapekey */
if (ac.datatype == ANIMCONT_SHAPEKEY)
return OPERATOR_CANCELLED;
/* do groups only first (unless in Drivers mode, where there are none) */
if (ac.datatype != ANIMCONT_DRIVERS) {
/* filter data */
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_CHANNELS | ANIMFILTER_FOREDIT);
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
/* delete selected groups and their associated channels */
for (ale= anim_data.first; ale; ale= ale->next) {
/* only groups - don't check other types yet, since they may no-longer exist */
if (ale->type == ANIMTYPE_GROUP) {
bActionGroup *agrp= (bActionGroup *)ale->data;
AnimData *adt= BKE_animdata_from_id(ale->id);
FCurve *fcu, *fcn;
/* skip this group if no AnimData available, as we can't safely remove the F-Curves */
if (adt == NULL)
continue;
/* delete all of the Group's F-Curves, but no others */
for (fcu= agrp->channels.first; fcu && fcu->grp==agrp; fcu= fcn) {
fcn= fcu->next;
/* remove from group and action, then free */
action_groups_remove_channel(adt->action, fcu);
free_fcurve(fcu);
}
/* free the group itself */
if (adt->action)
BLI_freelinkN(&adt->action->groups, agrp);
else
MEM_freeN(agrp);
}
}
/* cleanup */
BLI_freelistN(&anim_data);
}
/* now do F-Curves */
if (ac.datatype != ANIMCONT_GPENCIL) {
/* filter data */
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT);
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
/* delete selected F-Curves */
for (ale= anim_data.first; ale; ale= ale->next) {
/* only F-Curves, and only if we can identify its parent */
if (ale->type == ANIMTYPE_FCURVE) {
AnimData *adt= BKE_animdata_from_id(ale->id);
FCurve *fcu= (FCurve *)ale->data;
/* if no AnimData, we've got nowhere to remove the F-Curve from */
if (adt == NULL)
continue;
/* remove from whatever list it came from
* - Action Group
* - Action
* - Drivers
* - TODO... some others?
*/
if (fcu->grp)
action_groups_remove_channel(adt->action, fcu);
else if (adt->action)
BLI_remlink(&adt->action->curves, fcu);
else if (ac.datatype == ANIMCONT_DRIVERS)
BLI_remlink(&adt->drivers, fcu);
/* free the F-Curve itself */
free_fcurve(fcu);
}
}
/* cleanup */
BLI_freelistN(&anim_data);
}
/* send notifier that things have changed */
WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_EDIT, NULL);
return OPERATOR_FINISHED;
}
void ANIM_OT_channels_delete (wmOperatorType *ot)
{
/* identifiers */
ot->name= "Delete Channels";
ot->idname= "ANIM_OT_channels_delete";
/* api callbacks */
ot->exec= animchannels_delete_exec;
ot->poll= animedit_poll_channels_active;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
/* ******************** Toggle Channel Visibility Operator *********************** */ /* ******************** Toggle Channel Visibility Operator *********************** */
@ -668,7 +823,7 @@ static int animchannels_visibility_toggle_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED; return OPERATOR_CANCELLED;
/* filter data */ /* filter data */
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_CURVESONLY); filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL);
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
/* See if we should be making showing all selected or hiding */ /* See if we should be making showing all selected or hiding */
@ -676,21 +831,35 @@ static int animchannels_visibility_toggle_exec(bContext *C, wmOperator *op)
if (vis == ACHANNEL_SETFLAG_CLEAR) if (vis == ACHANNEL_SETFLAG_CLEAR)
break; break;
if (ale->flag & FCURVE_VISIBLE) if ((ale->type == ANIMTYPE_FCURVE) && (ale->flag & FCURVE_VISIBLE))
vis= ACHANNEL_SETFLAG_CLEAR;
else if ((ale->type == ANIMTYPE_GROUP) && !(ale->flag & AGRP_NOTVISIBLE))
vis= ACHANNEL_SETFLAG_CLEAR; vis= ACHANNEL_SETFLAG_CLEAR;
} }
/* Now set the flags */ /* Now set the flags */
for (ale= anim_data.first; ale; ale= ale->next) { for (ale= anim_data.first; ale; ale= ale->next) {
FCurve *fcu= (FCurve *)ale->data; switch (ale->type) {
ACHANNEL_SET_FLAG(fcu, vis, FCURVE_VISIBLE); case ANIMTYPE_FCURVE: /* F-Curve */
{
FCurve *fcu= (FCurve *)ale->data;
ACHANNEL_SET_FLAG(fcu, vis, FCURVE_VISIBLE);
}
break;
case ANIMTYPE_GROUP: /* Group */
{
bActionGroup *agrp= (bActionGroup *)ale->data;
ACHANNEL_SET_FLAG_NEG(agrp, vis, AGRP_NOTVISIBLE);
}
break;
}
} }
/* cleanup */ /* cleanup */
BLI_freelistN(&anim_data); BLI_freelistN(&anim_data);
/* set notifier tha things have changed */ /* send notifier that things have changed */
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_CHANNELS); WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_EDIT, NULL);
return OPERATOR_FINISHED; return OPERATOR_FINISHED;
} }
@ -889,6 +1058,12 @@ static void setflag_anim_channels (bAnimContext *ac, short setting, short mode,
case ACHANNEL_SETTING_EXPAND: case ACHANNEL_SETTING_EXPAND:
ACHANNEL_SET_FLAG(agrp, mode, AGRP_EXPANDED); ACHANNEL_SET_FLAG(agrp, mode, AGRP_EXPANDED);
break; break;
case ACHANNEL_SETTING_MUTE:
ACHANNEL_SET_FLAG(agrp, mode, AGRP_MUTED);
break;
case ACHANNEL_SETTING_VISIBLE:
ACHANNEL_SET_FLAG_NEG(agrp, mode, AGRP_NOTVISIBLE);
break;
} }
} }
break; break;
@ -947,8 +1122,8 @@ static int animchannels_setflag_exec(bContext *C, wmOperator *op)
/* modify setting */ /* modify setting */
setflag_anim_channels(&ac, setting, mode, 1); setflag_anim_channels(&ac, setting, mode, 1);
/* set notifier tha things have changed */ /* send notifier that things have changed */
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_CHANNELS); WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_EDIT, NULL);
return OPERATOR_FINISHED; return OPERATOR_FINISHED;
} }
@ -963,7 +1138,7 @@ void ANIM_OT_channels_setting_enable (wmOperatorType *ot)
/* api callbacks */ /* api callbacks */
ot->invoke= WM_menu_invoke; ot->invoke= WM_menu_invoke;
ot->exec= animchannels_setflag_exec; ot->exec= animchannels_setflag_exec;
ot->poll= ED_operator_areaactive; ot->poll= animedit_poll_channels_active;
/* flags */ /* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
@ -984,7 +1159,7 @@ void ANIM_OT_channels_setting_disable (wmOperatorType *ot)
/* api callbacks */ /* api callbacks */
ot->invoke= WM_menu_invoke; ot->invoke= WM_menu_invoke;
ot->exec= animchannels_setflag_exec; ot->exec= animchannels_setflag_exec;
ot->poll= ED_operator_areaactive; ot->poll= animedit_poll_channels_active;
/* flags */ /* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
@ -1005,7 +1180,7 @@ void ANIM_OT_channels_setting_toggle (wmOperatorType *ot)
/* api callbacks */ /* api callbacks */
ot->invoke= WM_menu_invoke; ot->invoke= WM_menu_invoke;
ot->exec= animchannels_setflag_exec; ot->exec= animchannels_setflag_exec;
ot->poll= ED_operator_areaactive; ot->poll= animedit_poll_channels_active;
/* flags */ /* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
@ -1026,7 +1201,7 @@ void ANIM_OT_channels_editable_toggle (wmOperatorType *ot)
/* api callbacks */ /* api callbacks */
ot->exec= animchannels_setflag_exec; ot->exec= animchannels_setflag_exec;
ot->poll= ED_operator_areaactive; ot->poll= animedit_poll_channels_active;
/* flags */ /* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
@ -1056,8 +1231,8 @@ static int animchannels_expand_exec (bContext *C, wmOperator *op)
/* modify setting */ /* modify setting */
setflag_anim_channels(&ac, ACHANNEL_SETTING_EXPAND, ACHANNEL_SETFLAG_ADD, onlysel); setflag_anim_channels(&ac, ACHANNEL_SETTING_EXPAND, ACHANNEL_SETFLAG_ADD, onlysel);
/* set notifier that things have changed */ /* send notifier that things have changed */
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_CHANNELS); WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_EDIT, NULL);
return OPERATOR_FINISHED; return OPERATOR_FINISHED;
} }
@ -1070,7 +1245,7 @@ void ANIM_OT_channels_expand (wmOperatorType *ot)
/* api callbacks */ /* api callbacks */
ot->exec= animchannels_expand_exec; ot->exec= animchannels_expand_exec;
ot->poll= ED_operator_areaactive; ot->poll= animedit_poll_channels_active;
/* flags */ /* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
@ -1097,8 +1272,8 @@ static int animchannels_collapse_exec (bContext *C, wmOperator *op)
/* modify setting */ /* modify setting */
setflag_anim_channels(&ac, ACHANNEL_SETTING_EXPAND, ACHANNEL_SETFLAG_CLEAR, onlysel); setflag_anim_channels(&ac, ACHANNEL_SETTING_EXPAND, ACHANNEL_SETFLAG_CLEAR, onlysel);
/* set notifier that things have changed */ /* send notifier that things have changed */
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_CHANNELS); WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_EDIT, NULL);
return OPERATOR_FINISHED; return OPERATOR_FINISHED;
} }
@ -1111,7 +1286,7 @@ void ANIM_OT_channels_collapse (wmOperatorType *ot)
/* api callbacks */ /* api callbacks */
ot->exec= animchannels_collapse_exec; ot->exec= animchannels_collapse_exec;
ot->poll= ED_operator_areaactive; ot->poll= animedit_poll_channels_active;
/* flags */ /* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
@ -1136,8 +1311,8 @@ static int animchannels_deselectall_exec(bContext *C, wmOperator *op)
else else
ANIM_deselect_anim_channels(ac.data, ac.datatype, 1, ACHANNEL_SETFLAG_ADD); ANIM_deselect_anim_channels(ac.data, ac.datatype, 1, ACHANNEL_SETFLAG_ADD);
/* set notifier tha things have changed */ /* send notifier that things have changed */
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_CHANNELS); WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_SELECT, NULL);
return OPERATOR_FINISHED; return OPERATOR_FINISHED;
} }
@ -1150,7 +1325,7 @@ void ANIM_OT_channels_select_all_toggle (wmOperatorType *ot)
/* api callbacks */ /* api callbacks */
ot->exec= animchannels_deselectall_exec; ot->exec= animchannels_deselectall_exec;
ot->poll= ED_operator_areaactive; ot->poll= animedit_poll_channels_nla_tweakmode_off;
/* flags */ /* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
@ -1218,6 +1393,14 @@ static void borderselect_anim_channels (bAnimContext *ac, rcti *rect, short sele
ACHANNEL_SET_FLAG(gpl, selectmode, GP_LAYER_SELECT); ACHANNEL_SET_FLAG(gpl, selectmode, GP_LAYER_SELECT);
} }
break; break;
case ANIMTYPE_NLATRACK: /* nla-track */
{
NlaTrack *nlt= (NlaTrack *)ale->data;
ACHANNEL_SET_FLAG(nlt, selectmode, NLATRACK_SELECTED);
}
break;
} }
} }
@ -1257,6 +1440,9 @@ static int animchannels_borderselect_exec(bContext *C, wmOperator *op)
/* apply borderselect animation channels */ /* apply borderselect animation channels */
borderselect_anim_channels(&ac, &rect, selectmode); borderselect_anim_channels(&ac, &rect, selectmode);
/* send notifier that things have changed */
WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_SELECT, NULL);
return OPERATOR_FINISHED; return OPERATOR_FINISHED;
} }
@ -1271,7 +1457,7 @@ void ANIM_OT_channels_select_border(wmOperatorType *ot)
ot->exec= animchannels_borderselect_exec; ot->exec= animchannels_borderselect_exec;
ot->modal= WM_border_select_modal; ot->modal= WM_border_select_modal;
ot->poll= ED_operator_areaactive; ot->poll= animedit_poll_channels_nla_tweakmode_off;
/* flags */ /* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
@ -1291,11 +1477,12 @@ void ANIM_OT_channels_select_border(wmOperatorType *ot)
* NOTE: eventually, this should probably be phased out when many of these things are replaced with buttons * NOTE: eventually, this should probably be phased out when many of these things are replaced with buttons
*/ */
static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, short selectmode) static int mouse_anim_channels (bAnimContext *ac, float x, int channel_index, short selectmode)
{ {
ListBase anim_data = {NULL, NULL}; ListBase anim_data = {NULL, NULL};
bAnimListElem *ale; bAnimListElem *ale;
int filter; int filter;
int notifierFlags = 0;
/* get the channel that was clicked on */ /* get the channel that was clicked on */
/* filter channels */ /* filter channels */
@ -1309,7 +1496,7 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s
printf("Error: animation channel (index = %d) not found in mouse_anim_channels() \n", channel_index); printf("Error: animation channel (index = %d) not found in mouse_anim_channels() \n", channel_index);
BLI_freelistN(&anim_data); BLI_freelistN(&anim_data);
return; return 0;
} }
/* selectmode -1 is a special case for ActionGroups only, which selects all of the channels underneath it only... */ /* selectmode -1 is a special case for ActionGroups only, which selects all of the channels underneath it only... */
@ -1317,7 +1504,7 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s
if ((selectmode == -1) && (ale->type != ANIMTYPE_GROUP)) { if ((selectmode == -1) && (ale->type != ANIMTYPE_GROUP)) {
/* normal channels should not behave normally in this case */ /* normal channels should not behave normally in this case */
BLI_freelistN(&anim_data); BLI_freelistN(&anim_data);
return; return 0;
} }
/* action to take depends on what channel we've got */ /* action to take depends on what channel we've got */
@ -1329,6 +1516,8 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s
if (x < 16) { if (x < 16) {
/* toggle expand */ /* toggle expand */
sce->flag ^= SCE_DS_COLLAPSED; sce->flag ^= SCE_DS_COLLAPSED;
notifierFlags |= ND_ANIMCHAN_EDIT;
} }
else { else {
/* set selection status */ /* set selection status */
@ -1339,6 +1528,8 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s
else { else {
sce->flag |= SCE_DS_SELECTED; sce->flag |= SCE_DS_SELECTED;
} }
notifierFlags |= ND_ANIMCHAN_SELECT;
} }
} }
break; break;
@ -1352,6 +1543,8 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s
if (x < 16) { if (x < 16) {
/* toggle expand */ /* toggle expand */
ob->nlaflag ^= OB_ADS_COLLAPSED; // XXX ob->nlaflag ^= OB_ADS_COLLAPSED; // XXX
notifierFlags |= ND_ANIMCHAN_EDIT;
} }
else { else {
/* set selection status */ /* set selection status */
@ -1376,6 +1569,8 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s
/* xxx should be ED_base_object_activate(), but we need context pointer for that... */ /* xxx should be ED_base_object_activate(), but we need context pointer for that... */
//set_active_base(base); //set_active_base(base);
notifierFlags |= ND_ANIMCHAN_SELECT;
} }
} }
break; break;
@ -1383,18 +1578,21 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s
{ {
bAction *act= (bAction *)ale->data; bAction *act= (bAction *)ale->data;
act->flag ^= ACT_COLLAPSED; act->flag ^= ACT_COLLAPSED;
notifierFlags |= ND_ANIMCHAN_EDIT;
} }
break; break;
case ANIMTYPE_FILLDRIVERS: case ANIMTYPE_FILLDRIVERS:
{ {
AnimData *adt= (AnimData* )ale->data; AnimData *adt= (AnimData* )ale->data;
adt->flag ^= ADT_DRIVERS_COLLAPSED; adt->flag ^= ADT_DRIVERS_COLLAPSED;
notifierFlags |= ND_ANIMCHAN_EDIT;
} }
break; break;
case ANIMTYPE_FILLMATD: case ANIMTYPE_FILLMATD:
{ {
Object *ob= (Object *)ale->data; Object *ob= (Object *)ale->data;
ob->nlaflag ^= OB_ADS_SHOWMATS; // XXX ob->nlaflag ^= OB_ADS_SHOWMATS; // XXX
notifierFlags |= ND_ANIMCHAN_EDIT;
} }
break; break;
@ -1402,36 +1600,42 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s
{ {
Material *ma= (Material *)ale->data; Material *ma= (Material *)ale->data;
ma->flag ^= MA_DS_EXPAND; ma->flag ^= MA_DS_EXPAND;
notifierFlags |= ND_ANIMCHAN_EDIT;
} }
break; break;
case ANIMTYPE_DSLAM: case ANIMTYPE_DSLAM:
{ {
Lamp *la= (Lamp *)ale->data; Lamp *la= (Lamp *)ale->data;
la->flag ^= LA_DS_EXPAND; la->flag ^= LA_DS_EXPAND;
notifierFlags |= ND_ANIMCHAN_EDIT;
} }
break; break;
case ANIMTYPE_DSCAM: case ANIMTYPE_DSCAM:
{ {
Camera *ca= (Camera *)ale->data; Camera *ca= (Camera *)ale->data;
ca->flag ^= CAM_DS_EXPAND; ca->flag ^= CAM_DS_EXPAND;
notifierFlags |= ND_ANIMCHAN_EDIT;
} }
break; break;
case ANIMTYPE_DSCUR: case ANIMTYPE_DSCUR:
{ {
Curve *cu= (Curve *)ale->data; Curve *cu= (Curve *)ale->data;
cu->flag ^= CU_DS_EXPAND; cu->flag ^= CU_DS_EXPAND;
notifierFlags |= ND_ANIMCHAN_EDIT;
} }
break; break;
case ANIMTYPE_DSSKEY: case ANIMTYPE_DSSKEY:
{ {
Key *key= (Key *)ale->data; Key *key= (Key *)ale->data;
key->flag ^= KEYBLOCK_DS_EXPAND; key->flag ^= KEYBLOCK_DS_EXPAND;
notifierFlags |= ND_ANIMCHAN_EDIT;
} }
break; break;
case ANIMTYPE_DSWOR: case ANIMTYPE_DSWOR:
{ {
World *wo= (World *)ale->data; World *wo= (World *)ale->data;
wo->flag ^= WO_DS_EXPAND; wo->flag ^= WO_DS_EXPAND;
notifierFlags |= ND_ANIMCHAN_EDIT;
} }
break; break;
@ -1443,10 +1647,22 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s
if ((x < (offset+17)) && (agrp->channels.first)) { if ((x < (offset+17)) && (agrp->channels.first)) {
/* toggle expand */ /* toggle expand */
agrp->flag ^= AGRP_EXPANDED; agrp->flag ^= AGRP_EXPANDED;
notifierFlags |= ND_ANIMCHAN_EDIT;
}
else if ((x < (offset+32)) && (ac->spacetype==SPACE_IPO)) {
/* toggle visibility (of grouped F-Curves in Graph editor) */
agrp->flag ^= AGRP_NOTVISIBLE;
notifierFlags |= ND_ANIMCHAN_EDIT;
} }
else if (x >= (ACHANNEL_NAMEWIDTH-ACHANNEL_BUTTON_WIDTH)) { else if (x >= (ACHANNEL_NAMEWIDTH-ACHANNEL_BUTTON_WIDTH)) {
/* toggle protection/locking */ /* toggle protection/locking */
agrp->flag ^= AGRP_PROTECTED; agrp->flag ^= AGRP_PROTECTED;
notifierFlags |= ND_ANIMCHAN_EDIT;
}
else if (x >= (ACHANNEL_NAMEWIDTH-2*ACHANNEL_BUTTON_WIDTH)) {
/* toggle mute */
agrp->flag ^= AGRP_MUTED;
notifierFlags |= ND_ANIMCHAN_EDIT;
} }
else { else {
/* select/deselect group */ /* select/deselect group */
@ -1474,7 +1690,9 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s
/* if group is selected now, make group the 'active' one in the visible list */ /* if group is selected now, make group the 'active' one in the visible list */
if (agrp->flag & AGRP_SELECTED) if (agrp->flag & AGRP_SELECTED)
ANIM_set_active_channel(ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP); ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP);
notifierFlags |= ND_ANIMCHAN_SELECT;
} }
} }
break; break;
@ -1495,16 +1713,20 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s
if (x >= (ACHANNEL_NAMEWIDTH-ACHANNEL_BUTTON_WIDTH)) { if (x >= (ACHANNEL_NAMEWIDTH-ACHANNEL_BUTTON_WIDTH)) {
/* toggle protection (only if there's a toggle there) */ /* toggle protection (only if there's a toggle there) */
if (fcu->bezt) if (fcu->bezt) {
fcu->flag ^= FCURVE_PROTECTED; fcu->flag ^= FCURVE_PROTECTED;
notifierFlags |= ND_ANIMCHAN_EDIT;
}
} }
else if (x >= (ACHANNEL_NAMEWIDTH-2*ACHANNEL_BUTTON_WIDTH)) { else if (x >= (ACHANNEL_NAMEWIDTH-2*ACHANNEL_BUTTON_WIDTH)) {
/* toggle mute */ /* toggle mute */
fcu->flag ^= FCURVE_MUTED; fcu->flag ^= FCURVE_MUTED;
notifierFlags |= ND_ANIMCHAN_EDIT;
} }
else if ((x < (offset+17)) && (ac->spacetype==SPACE_IPO)) { else if ((x < (offset+17)) && (ac->spacetype==SPACE_IPO)) {
/* toggle visibility */ /* toggle visibility */
fcu->flag ^= FCURVE_VISIBLE; fcu->flag ^= FCURVE_VISIBLE;
notifierFlags |= ND_ANIMCHAN_EDIT;
} }
else { else {
/* select/deselect */ /* select/deselect */
@ -1520,7 +1742,9 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s
/* if F-Curve is selected now, make F-Curve the 'active' one in the visible list */ /* if F-Curve is selected now, make F-Curve the 'active' one in the visible list */
if (fcu->flag & FCURVE_SELECTED) if (fcu->flag & FCURVE_SELECTED)
ANIM_set_active_channel(ac->data, ac->datatype, filter, fcu, ANIMTYPE_FCURVE); ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ANIMTYPE_FCURVE);
notifierFlags |= ND_ANIMCHAN_SELECT;
} }
} }
break; break;
@ -1530,6 +1754,8 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s
/* toggle expand */ /* toggle expand */
gpd->flag ^= GP_DATA_EXPAND; gpd->flag ^= GP_DATA_EXPAND;
notifierFlags |= ND_ANIMCHAN_EDIT;
} }
break; break;
case ANIMTYPE_GPLAYER: case ANIMTYPE_GPLAYER:
@ -1568,6 +1794,9 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s
/* free channels */ /* free channels */
BLI_freelistN(&anim_data); BLI_freelistN(&anim_data);
/* return notifier flags */
return notifierFlags;
} }
/* ------------------- */ /* ------------------- */
@ -1580,6 +1809,7 @@ static int animchannels_mouseclick_invoke(bContext *C, wmOperator *op, wmEvent *
ARegion *ar; ARegion *ar;
View2D *v2d; View2D *v2d;
int mval[2], channel_index; int mval[2], channel_index;
int notifierFlags = 0;
short selectmode; short selectmode;
float x, y; float x, y;
@ -1614,10 +1844,10 @@ static int animchannels_mouseclick_invoke(bContext *C, wmOperator *op, wmEvent *
UI_view2d_listview_view_to_cell(v2d, ACHANNEL_NAMEWIDTH, ACHANNEL_STEP, 0, (float)ACHANNEL_HEIGHT_HALF, x, y, NULL, &channel_index); UI_view2d_listview_view_to_cell(v2d, ACHANNEL_NAMEWIDTH, ACHANNEL_STEP, 0, (float)ACHANNEL_HEIGHT_HALF, x, y, NULL, &channel_index);
/* handle mouse-click in the relevant channel then */ /* handle mouse-click in the relevant channel then */
mouse_anim_channels(&ac, x, channel_index, selectmode); notifierFlags= mouse_anim_channels(&ac, x, channel_index, selectmode);
/* set notifier tha things have changed */ /* set notifier that things have changed */
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_CHANNELS); WM_event_add_notifier(C, NC_ANIMATION|notifierFlags, NULL);
return OPERATOR_FINISHED; return OPERATOR_FINISHED;
} }
@ -1630,7 +1860,7 @@ void ANIM_OT_channels_click (wmOperatorType *ot)
/* api callbacks */ /* api callbacks */
ot->invoke= animchannels_mouseclick_invoke; ot->invoke= animchannels_mouseclick_invoke;
ot->poll= ED_operator_areaactive; ot->poll= animedit_poll_channels_active;
/* flags */ /* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
@ -1653,6 +1883,8 @@ void ED_operatortypes_animchannels(void)
WM_operatortype_append(ANIM_OT_channels_setting_disable); WM_operatortype_append(ANIM_OT_channels_setting_disable);
WM_operatortype_append(ANIM_OT_channels_setting_toggle); WM_operatortype_append(ANIM_OT_channels_setting_toggle);
WM_operatortype_append(ANIM_OT_channels_delete);
// XXX does this need to be a separate operator? // XXX does this need to be a separate operator?
WM_operatortype_append(ANIM_OT_channels_editable_toggle); WM_operatortype_append(ANIM_OT_channels_editable_toggle);
@ -1686,6 +1918,10 @@ void ED_keymap_animchannels(wmWindowManager *wm)
/* borderselect */ /* borderselect */
WM_keymap_add_item(keymap, "ANIM_OT_channels_select_border", BKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "ANIM_OT_channels_select_border", BKEY, KM_PRESS, 0, 0);
/* delete */
WM_keymap_add_item(keymap, "ANIM_OT_channels_delete", XKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "ANIM_OT_channels_delete", DELKEY, KM_PRESS, 0, 0);
/* settings */ /* settings */
WM_keymap_add_item(keymap, "ANIM_OT_channels_setting_toggle", WKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "ANIM_OT_channels_setting_toggle", WKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "ANIM_OT_channels_setting_enable", WKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0); WM_keymap_add_item(keymap, "ANIM_OT_channels_setting_enable", WKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0);

@ -77,72 +77,6 @@ void ED_anim_object_flush_update(const bContext *C, Object *ob)
} }
/* **************************** animation tool notifiers ******************************** */
/* Send notifiers on behalf of animation editing tools, based on various context info
* - data_changed: eAnimData_Changed
*/
void ANIM_animdata_send_notifiers (bContext *C, bAnimContext *ac, short data_changed)
{
/* types of notifiers to send, depends on the editor context */
switch (ac->datatype) {
case ANIMCONT_DOPESHEET: /* dopesheet */
case ANIMCONT_FCURVES: /* fcurve editor */
case ANIMCONT_DRIVERS: /* drivers editor */ // XXX probably this will need separate handling, since these are part of dependency system
{
/* what action was taken */
switch (data_changed) {
case ANIM_CHANGED_KEYFRAMES_VALUES:
/* keyframe values changed, so transform may have changed */
// XXX what about other cases? maybe we need general ND_KEYFRAMES or ND_ANIMATION?
WM_event_add_notifier(C, NC_OBJECT|ND_KEYS|ND_TRANSFORM, NULL);
break;
case ANIM_CHANGED_KEYFRAMES_SELECT:
WM_event_add_notifier(C, NC_OBJECT|ND_KEYS, NULL);
break;
case ANIM_CHANGED_CHANNELS:
// XXX err... check available datatypes in dopesheet first?
// FIXME: this currently doesn't work (to update own view)
WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE|ND_OB_SELECT, ac->scene);
WM_event_add_notifier(C, NC_OBJECT|ND_BONE_ACTIVE|ND_BONE_SELECT, NULL);
break;
}
// XXX for now, at least update own editor!
ED_area_tag_redraw(CTX_wm_area(C));
}
break;
case ANIMCONT_ACTION: /* action editor */
{
Object *obact= CTX_data_active_object(C);
switch (data_changed) {
case ANIM_CHANGED_KEYFRAMES_VALUES:
/* keyframe values changed, so transform may have changed */
// XXX what about other cases? maybe we need general ND_KEYFRAMES or ND_ANIMATION?
WM_event_add_notifier(C, NC_OBJECT|ND_KEYS|ND_TRANSFORM, obact);
break;
case ANIM_CHANGED_KEYFRAMES_SELECT:
WM_event_add_notifier(C, NC_OBJECT|ND_KEYS, obact);
break;
case ANIM_CHANGED_CHANNELS:
// XXX err... check available datatypes in dopesheet first?
// FIXME: this currently doesn't work (to update own view)
WM_event_add_notifier(C, NC_OBJECT|ND_BONE_ACTIVE|ND_BONE_SELECT, obact);
break;
}
// XXX for now, at least update own editor!
ED_area_tag_redraw(CTX_wm_area(C));
}
break;
default: /* some other data... just update area for now */
ED_area_tag_redraw(CTX_wm_area(C));
}
}
/* **************************** pose <-> action syncing ******************************** */ /* **************************** pose <-> action syncing ******************************** */
/* Summary of what needs to be synced between poses and actions: /* Summary of what needs to be synced between poses and actions:
* 1) Flags * 1) Flags
@ -152,6 +86,10 @@ void ANIM_animdata_send_notifiers (bContext *C, bAnimContext *ac, short data_cha
* 3) Grouping (only for pose to action for now) * 3) Grouping (only for pose to action for now)
*/ */
/* XXX OBSOLETE CODE WARNING:
* With the Animato system, the code below is somewhat obsolete now...
*/
/* Notifier from Action/Dopesheet (this may be extended to include other things such as Python...) /* Notifier from Action/Dopesheet (this may be extended to include other things such as Python...)
* Channels in action changed, so update pose channels/groups to reflect changes. * Channels in action changed, so update pose channels/groups to reflect changes.
* *

@ -43,10 +43,12 @@
#include "BLI_blenlib.h" #include "BLI_blenlib.h"
#include "BKE_animsys.h"
#include "BKE_action.h" #include "BKE_action.h"
#include "BKE_context.h" #include "BKE_context.h"
#include "BKE_global.h" #include "BKE_global.h"
#include "BKE_fcurve.h" #include "BKE_fcurve.h"
#include "BKE_nla.h"
#include "BKE_object.h" #include "BKE_object.h"
#include "BKE_screen.h" #include "BKE_screen.h"
#include "BKE_utildefines.h" #include "BKE_utildefines.h"
@ -165,7 +167,7 @@ void ANIM_draw_cfra (const bContext *C, View2D *v2d, short flag)
glLineWidth(2.0); glLineWidth(2.0);
glBegin(GL_LINE_STRIP); glBegin(GL_LINE_STRIP);
vec[1]= v2d->cur.ymin; vec[1]= v2d->cur.ymin-500.0f; /* XXX arbitrary... want it go to bottom */
glVertex2fv(vec); glVertex2fv(vec);
vec[1]= v2d->cur.ymax; vec[1]= v2d->cur.ymax;
@ -232,37 +234,16 @@ void ANIM_draw_previewrange (const bContext *C, View2D *v2d)
/* *************************************************** */ /* *************************************************** */
/* NLA-MAPPING UTILITIES (required for drawing and also editing keyframes) */ /* NLA-MAPPING UTILITIES (required for drawing and also editing keyframes) */
/* Obtain the Object providing NLA-scaling for the given channel (if applicable) */ /* Obtain the AnimData block providing NLA-mapping for the given channel (if applicable) */
Object *ANIM_nla_mapping_get(bAnimContext *ac, bAnimListElem *ale) AnimData *ANIM_nla_mapping_get(bAnimContext *ac, bAnimListElem *ale)
{ {
/* sanity checks */ /* sanity checks */
if (ac == NULL) if (ac == NULL)
return NULL; return NULL;
/* handling depends on the type of animation-context we've got */ /* handling depends on the type of animation-context we've got */
if (ac->datatype == ANIMCONT_ACTION) { if (ale && ale->id)
/* Action Editor (action mode) or Graph Editor (ipo mode): return BKE_animdata_from_id(ale->id);
* Only use if editor is not pinned, and active object has action
*/
if (ac->obact && ac->obact->action) {
SpaceAction *saction= (SpaceAction *)ac->sa->spacedata.first;
if (saction->pin == 0)
return ac->obact;
}
}
else if ((ac->datatype == ANIMCONT_DOPESHEET) && (ale)) {
/* Dopesheet:
* Only if channel is available, and is owned by an Object with an Action
*/
if ((ale->id) && (GS(ale->id->name) == ID_OB)) {
Object *ob= (Object *)ale->id;
if (ob->action)
return ob;
}
}
// XXX todo: add F-Curves mode (Graph Editor) ...
/* no appropriate object found */ /* no appropriate object found */
return NULL; return NULL;
@ -273,7 +254,8 @@ Object *ANIM_nla_mapping_get(bAnimContext *ac, bAnimListElem *ale)
* (where this is called) is single-threaded anyway * (where this is called) is single-threaded anyway
*/ */
// XXX was called: map_active_strip() // XXX was called: map_active_strip()
void ANIM_nla_mapping_draw(gla2DDrawInfo *di, Object *ob, short restore) // TODO: should this be depreceated?
void ANIM_nla_mapping_draw(gla2DDrawInfo *di, AnimData *adt, short restore)
{ {
static rctf stored; static rctf stored;
@ -288,8 +270,8 @@ void ANIM_nla_mapping_draw(gla2DDrawInfo *di, Object *ob, short restore)
gla2DGetMap(di, &stored); gla2DGetMap(di, &stored);
map= stored; map= stored;
map.xmin= get_action_frame(ob, map.xmin); map.xmin= BKE_nla_tweakedit_remap(adt, map.xmin, NLATIME_CONVERT_MAP);
map.xmax= get_action_frame(ob, map.xmax); map.xmax= BKE_nla_tweakedit_remap(adt, map.xmax, NLATIME_CONVERT_MAP);
if (map.xmin == map.xmax) map.xmax += 1.0f; if (map.xmin == map.xmax) map.xmax += 1.0f;
gla2DSetMap(di, &map); gla2DSetMap(di, &map);
@ -298,36 +280,38 @@ void ANIM_nla_mapping_draw(gla2DDrawInfo *di, Object *ob, short restore)
/* ------------------- */ /* ------------------- */
/* helper function for ANIM_nla_mapping_apply_ipocurve() -> "restore", i.e. mapping points back to IPO-time */ /* helper function for ANIM_nla_mapping_apply_fcurve() -> "restore", i.e. mapping points back to action-time */
static short bezt_nlamapping_restore(BeztEditData *bed, BezTriple *bezt) static short bezt_nlamapping_restore(BeztEditData *bed, BezTriple *bezt)
{ {
/* object providing scaling is stored in 'data', only_keys option is stored in i1 */ /* AnimData block providing scaling is stored in 'data', only_keys option is stored in i1 */
Object *ob= (Object *)bed->data; AnimData *adt= (AnimData *)bed->data;
short only_keys= (short)bed->i1; short only_keys= (short)bed->i1;
/* adjust BezTriple handles only if allowed to */ /* adjust BezTriple handles only if allowed to */
if (only_keys == 0) { if (only_keys == 0) {
bezt->vec[0][0]= get_action_frame(ob, bezt->vec[0][0]); bezt->vec[0][0]= BKE_nla_tweakedit_remap(adt, bezt->vec[0][0], NLATIME_CONVERT_UNMAP);
bezt->vec[2][0]= get_action_frame(ob, bezt->vec[2][0]); bezt->vec[2][0]= BKE_nla_tweakedit_remap(adt, bezt->vec[2][0], NLATIME_CONVERT_UNMAP);
} }
bezt->vec[1][0]= get_action_frame(ob, bezt->vec[1][0]);
bezt->vec[1][0]= BKE_nla_tweakedit_remap(adt, bezt->vec[1][0], NLATIME_CONVERT_UNMAP);
return 0; return 0;
} }
/* helper function for ANIM_nla_mapping_apply_ipocurve() -> "apply", i.e. mapping points to NLA-mapped global time */ /* helper function for ANIM_nla_mapping_apply_fcurve() -> "apply", i.e. mapping points to NLA-mapped global time */
static short bezt_nlamapping_apply(BeztEditData *bed, BezTriple *bezt) static short bezt_nlamapping_apply(BeztEditData *bed, BezTriple *bezt)
{ {
/* object providing scaling is stored in 'data', only_keys option is stored in i1 */ /* AnimData block providing scaling is stored in 'data', only_keys option is stored in i1 */
Object *ob= (Object *)bed->data; AnimData *adt= (AnimData *)bed->data;
short only_keys= (short)bed->i1; short only_keys= (short)bed->i1;
/* adjust BezTriple handles only if allowed to */ /* adjust BezTriple handles only if allowed to */
if (only_keys == 0) { if (only_keys == 0) {
bezt->vec[0][0]= get_action_frame_inv(ob, bezt->vec[0][0]); bezt->vec[0][0]= BKE_nla_tweakedit_remap(adt, bezt->vec[0][0], NLATIME_CONVERT_MAP);
bezt->vec[2][0]= get_action_frame_inv(ob, bezt->vec[2][0]); bezt->vec[2][0]= BKE_nla_tweakedit_remap(adt, bezt->vec[2][0], NLATIME_CONVERT_MAP);
} }
bezt->vec[1][0]= get_action_frame_inv(ob, bezt->vec[1][0]);
bezt->vec[1][0]= BKE_nla_tweakedit_remap(adt, bezt->vec[1][0], NLATIME_CONVERT_MAP);
return 0; return 0;
} }
@ -338,17 +322,17 @@ static short bezt_nlamapping_apply(BeztEditData *bed, BezTriple *bezt)
* - restore = whether to map points back to non-mapped time * - restore = whether to map points back to non-mapped time
* - only_keys = whether to only adjust the location of the center point of beztriples * - only_keys = whether to only adjust the location of the center point of beztriples
*/ */
void ANIM_nla_mapping_apply_fcurve(Object *ob, FCurve *fcu, short restore, short only_keys) void ANIM_nla_mapping_apply_fcurve (AnimData *adt, FCurve *fcu, short restore, short only_keys)
{ {
BeztEditData bed; BeztEditData bed;
BeztEditFunc map_cb; BeztEditFunc map_cb;
/* init edit data /* init edit data
* - ob is stored in 'data' * - AnimData is stored in 'data'
* - only_keys is stored in 'i1' * - only_keys is stored in 'i1'
*/ */
memset(&bed, 0, sizeof(BeztEditData)); memset(&bed, 0, sizeof(BeztEditData));
bed.data= (void *)ob; bed.data= (void *)adt;
bed.i1= (int)only_keys; bed.i1= (int)only_keys;
/* get editing callback */ /* get editing callback */

@ -195,7 +195,7 @@ static short actedit_get_context (bAnimContext *ac, SpaceAction *saction)
} }
} }
/* ----------- Private Stuff - IPO Editor ------------- */ /* ----------- Private Stuff - Graph Editor ------------- */
/* Get data being edited in Graph Editor (depending on current 'mode') */ /* Get data being edited in Graph Editor (depending on current 'mode') */
static short graphedit_get_context (bAnimContext *ac, SpaceIpo *sipo) static short graphedit_get_context (bAnimContext *ac, SpaceIpo *sipo)
@ -237,6 +237,26 @@ static short graphedit_get_context (bAnimContext *ac, SpaceIpo *sipo)
} }
} }
/* ----------- Private Stuff - NLA Editor ------------- */
/* Get data being edited in Graph Editor (depending on current 'mode') */
static short nlaedit_get_context (bAnimContext *ac, SpaceNla *snla)
{
/* init dopesheet data if non-existant (i.e. for old files) */
if (snla->ads == NULL)
snla->ads= MEM_callocN(sizeof(bDopeSheet), "NlaEdit DopeSheet");
/* sync settings with current view status, then return appropriate data */
/* update scene-pointer (no need to check for pinning yet, as not implemented) */
snla->ads->source= (ID *)ac->scene;
snla->ads->filterflag |= ADS_FILTER_ONLYNLA;
ac->datatype= ANIMCONT_NLA;
ac->data= snla->ads;
return 1;
}
/* ----------- Public API --------------- */ /* ----------- Public API --------------- */
/* Obtain current anim-data context, given that context info from Blender context has already been set /* Obtain current anim-data context, given that context info from Blender context has already been set
@ -264,6 +284,13 @@ short ANIM_animdata_context_getdata (bAnimContext *ac)
ok= graphedit_get_context(ac, sipo); ok= graphedit_get_context(ac, sipo);
} }
break; break;
case SPACE_NLA:
{
SpaceNla *snla= (SpaceNla *)sa->spacedata.first;
ok= nlaedit_get_context(ac, snla);
}
break;
} }
} }
@ -313,6 +340,68 @@ short ANIM_animdata_get_context (const bContext *C, bAnimContext *ac)
/* quick macro to test if AnimData is usable for drivers */ /* quick macro to test if AnimData is usable for drivers */
#define ANIMDATA_HAS_DRIVERS(id) ((id)->adt && (id)->adt->drivers.first) #define ANIMDATA_HAS_DRIVERS(id) ((id)->adt && (id)->adt->drivers.first)
/* quick macro to test if AnimData is usable for NLA */
#define ANIMDATA_HAS_NLA(id) ((id)->adt && (id)->adt->nla_tracks.first)
/* Quick macro to test for all three avove usability tests, performing the appropriate provided
* action for each when the AnimData context is appropriate.
*
* Priority order for this goes (most important, to least): AnimData blocks, NLA, Drivers, Keyframes.
*
* For this to work correctly, a standard set of data needs to be available within the scope that this
* gets called in:
* - ListBase anim_data;
* - bDopeSheet *ads;
* - bAnimListElem *ale;
* - int items;
*
* - id: ID block which should have an AnimData pointer following it immediately, to use
* - adtOk: line or block of code to execute for AnimData-blocks case (usually ANIMDATA_ADD_ANIMDATA)
* - nlaOk: line or block of code to execute for NLA case
* - driversOk: line or block of code to execute for Drivers case
* - keysOk: line or block of code for Keyframes case
*/
#define ANIMDATA_FILTER_CASES(id, adtOk, nlaOk, driversOk, keysOk) \
{\
if (filter_mode & ANIMFILTER_ANIMDATA) {\
if ((id)->adt) {\
adtOk\
}\
}\
else if (ads->filterflag & ADS_FILTER_ONLYNLA) {\
if (ANIMDATA_HAS_NLA(id)) {\
nlaOk\
}\
else if (!(ads->filterflag & ADS_FILTER_NLA_NOACT) && ANIMDATA_HAS_KEYS(id)) {\
nlaOk\
}\
}\
else if (ads->filterflag & ADS_FILTER_ONLYDRIVERS) {\
if (ANIMDATA_HAS_DRIVERS(id)) {\
driversOk\
}\
}\
else {\
if (ANIMDATA_HAS_KEYS(id)) {\
keysOk\
}\
}\
}
/* quick macro to add a pointer to an AnimData block as a channel */
#define ANIMDATA_ADD_ANIMDATA(id) \
{\
ale= make_new_animlistelem((id)->adt, ANIMTYPE_ANIMDATA, NULL, ANIMTYPE_NONE, (ID *)id);\
if (ale) {\
BLI_addtail(anim_data, ale);\
items++;\
}\
}
/* quick macro to test if a anim-channel (F-Curve, Group, etc.) is selected in an acceptable way */ /* quick macro to test if a anim-channel (F-Curve, Group, etc.) is selected in an acceptable way */
#define ANIMCHANNEL_SELOK(test_func) \ #define ANIMCHANNEL_SELOK(test_func) \
( !(filter_mode & (ANIMFILTER_SEL|ANIMFILTER_UNSEL)) || \ ( !(filter_mode & (ANIMFILTER_SEL|ANIMFILTER_UNSEL)) || \
@ -494,6 +583,25 @@ bAnimListElem *make_new_animlistelem (void *data, short datatype, void *owner, s
ale->datatype= ALE_GPFRAME; ale->datatype= ALE_GPFRAME;
} }
break; break;
case ANIMTYPE_NLATRACK:
{
NlaTrack *nlt= (NlaTrack *)data;
ale->flag= nlt->flag;
// XXX or should this be done some other way?
ale->key_data= &nlt->strips;
ale->datatype= ALE_NLASTRIP;
}
break;
case ANIMTYPE_NLAACTION:
{
/* nothing to include for now... nothing editable from NLA-perspective here */
ale->key_data= NULL;
ale->datatype= ALE_NONE;
}
break;
} }
} }
@ -522,7 +630,6 @@ static int animdata_filter_fcurves (ListBase *anim_data, FCurve *first, bActionG
if ( ANIMCHANNEL_SELOK(SEL_FCU(fcu)) ) { if ( ANIMCHANNEL_SELOK(SEL_FCU(fcu)) ) {
/* only include if this curve is active */ /* only include if this curve is active */
if (!(filter_mode & ANIMFILTER_ACTIVE) || (fcu->flag & FCURVE_ACTIVE)) { if (!(filter_mode & ANIMFILTER_ACTIVE) || (fcu->flag & FCURVE_ACTIVE)) {
/* owner/ownertype will be either object or action-channel, depending if it was dopesheet or part of an action */
ale= make_new_animlistelem(fcu, ANIMTYPE_FCURVE, owner, ownertype, owner_id); ale= make_new_animlistelem(fcu, ANIMTYPE_FCURVE, owner, ownertype, owner_id);
if (ale) { if (ale) {
@ -575,25 +682,30 @@ static int animdata_filter_action (ListBase *anim_data, bAction *act, int filter
* cases when we should include F-Curves inside group: * cases when we should include F-Curves inside group:
* - we don't care about visibility * - we don't care about visibility
* - group is expanded * - group is expanded
* - we're interested in keyframes, but not if they appear in selected channels * - we just need the F-Curves present
*/ */
// XXX what was the selection check here for again? if ( (!(filter_mode & ANIMFILTER_VISIBLE) || EXPANDED_AGRP(agrp)) || (filter_mode & ANIMFILTER_CURVESONLY) )
if ( (!(filter_mode & ANIMFILTER_VISIBLE) || EXPANDED_AGRP(agrp)) ||
( /*ANIMCHANNEL_SELOK(SEL_AGRP(agrp)) &&*/ (filter_mode & ANIMFILTER_CURVESONLY) ) )
{ {
if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_AGRP(agrp)) { /* for the Graph Editor, curves may be set to not be visible in the view to lessen clutter,
// XXX the 'owner' info here needs review... * but to do this, we need to check that the group doesn't have it's not-visible flag set preventing
items += animdata_filter_fcurves(anim_data, agrp->channels.first, agrp, owner, ownertype, filter_mode, owner_id); * all its sub-curves to be shown
*/
if ( !(filter_mode & ANIMFILTER_CURVEVISIBLE) || !(agrp->flag & AGRP_NOTVISIBLE) )
{
if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_AGRP(agrp)) {
// XXX the 'owner' info here needs review...
items += animdata_filter_fcurves(anim_data, agrp->channels.first, agrp, owner, ownertype, filter_mode, owner_id);
/* remove group from filtered list if last element is group /* remove group from filtered list if last element is group
* (i.e. only if group had channels, which were all hidden) * (i.e. only if group had channels, which were all hidden)
*/ */
// XXX this is really hacky... it should be fixed in a much more elegant way! // XXX this is really hacky... it should be fixed in a much more elegant way!
if ( (ale) && (anim_data->last == ale) && if ( (ale) && (anim_data->last == ale) &&
(ale->data == agrp) && (agrp->channels.first) ) (ale->data == agrp) && (agrp->channels.first) )
{ {
BLI_freelinkN(anim_data, ale); BLI_freelinkN(anim_data, ale);
items--; items--;
}
} }
} }
} }
@ -610,6 +722,83 @@ static int animdata_filter_action (ListBase *anim_data, bAction *act, int filter
return items; return items;
} }
/* Include NLA-Data for NLA-Editor:
* - when ANIMFILTER_CHANNELS is used, that means we should be filtering the list for display
* Although the evaluation order is from the first track to the last and then apply the Action on top,
* we present this in the UI as the Active Action followed by the last track to the first so that we
* get the evaluation order presented as per a stack.
* - for normal filtering (i.e. for editing), we only need the NLA-tracks but they can be in 'normal' evaluation
* order, i.e. first to last. Otherwise, some tools may get screwed up.
*/
static int animdata_filter_nla (ListBase *anim_data, AnimData *adt, int filter_mode, void *owner, short ownertype, ID *owner_id)
{
bAnimListElem *ale;
NlaTrack *nlt;
NlaTrack *first=NULL, *next=NULL;
int items = 0;
/* if showing channels, include active action */
if (filter_mode & ANIMFILTER_CHANNELS) {
/* there isn't really anything editable here, so skip if need editable */
// TODO: currently, selection isn't checked since it doesn't matter
if ((filter_mode & ANIMFILTER_FOREDIT) == 0) {
/* just add the action track now (this MUST appear for drawing)
* - as AnimData may not have an action, we pass a dummy pointer just to get the list elem created, then
* overwrite this with the real value - REVIEW THIS...
*/
ale= make_new_animlistelem((void *)(&adt->action), ANIMTYPE_NLAACTION, owner, ownertype, owner_id);
ale->data= (adt->action) ? adt->action : NULL;
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
}
/* first track to include will be the last one if we're filtering by channels */
first= adt->nla_tracks.last;
}
else {
/* first track to include will the the first one (as per normal) */
first= adt->nla_tracks.first;
}
/* loop over NLA Tracks - assume that the caller of this has already checked that these should be included */
for (nlt= first; nlt; nlt= next) {
/* 'next' NLA-Track to use depends on whether we're filtering for drawing or not */
if (filter_mode & ANIMFILTER_CHANNELS)
next= nlt->prev;
else
next= nlt->next;
/* if we're in NLA-tweakmode, don't show this track if it was disabled (due to tweaking) for now
* - active track should still get shown though (even though it has disabled flag set)
*/
// FIXME: the channels after should still get drawn, just 'differently', and after an active-action channel
if ((adt->flag & ADT_NLA_EDIT_ON) && (nlt->flag & NLATRACK_DISABLED) && !(nlt->flag & NLATRACK_ACTIVE))
continue;
/* only work with this channel and its subchannels if it is editable */
if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_NLT(nlt)) {
/* only include this track if selected in a way consistent with the filtering requirements */
if ( ANIMCHANNEL_SELOK(SEL_NLT(nlt)) ) {
/* only include if this track is active */
if (!(filter_mode & ANIMFILTER_ACTIVE) || (nlt->flag & NLATRACK_ACTIVE)) {
ale= make_new_animlistelem(nlt, ANIMTYPE_NLATRACK, owner, ownertype, owner_id);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
}
}
}
}
/* return the number of items added to the list */
return items;
}
static int animdata_filter_shapekey (ListBase *anim_data, Key *key, int filter_mode, void *owner, short ownertype, ID *owner_id) static int animdata_filter_shapekey (ListBase *anim_data, Key *key, int filter_mode, void *owner, short ownertype, ID *owner_id)
{ {
bAnimListElem *ale; bAnimListElem *ale;
@ -752,19 +941,19 @@ static int animdata_filter_dopesheet_mats (ListBase *anim_data, bDopeSheet *ads,
/* firstly check that we actuallly have some materials, by gathering all materials in a temp list */ /* firstly check that we actuallly have some materials, by gathering all materials in a temp list */
for (a=0; a < ob->totcol; a++) { for (a=0; a < ob->totcol; a++) {
Material *ma= give_current_material(ob, a); Material *ma= give_current_material(ob, a);
short ok = 0;
/* for now, if no material returned, skip (this shouldn't confuse the user I hope) */ /* for now, if no material returned, skip (this shouldn't confuse the user I hope) */
if (ELEM(NULL, ma, ma->adt)) if (ELEM(NULL, ma, ma->adt))
continue; continue;
if ((ads->filterflag & ADS_FILTER_ONLYDRIVERS)==0) { /* check if ok */
if (ANIMDATA_HAS_KEYS(ma) == 0) ANIMDATA_FILTER_CASES(ma,
continue; { /* AnimData blocks - do nothing... */ },
} ok=1;,
else { ok=1;,
if (ANIMDATA_HAS_DRIVERS(ma) == 0) ok=1;)
continue; if (ok == 0) continue;
}
/* make a temp list elem for this */ /* make a temp list elem for this */
ld= MEM_callocN(sizeof(LinkData), "DopeSheet-MaterialCache"); ld= MEM_callocN(sizeof(LinkData), "DopeSheet-MaterialCache");
@ -801,16 +990,13 @@ static int animdata_filter_dopesheet_mats (ListBase *anim_data, bDopeSheet *ads,
} }
} }
/* add material's F-Curve or Driver channels? */ /* add material's animation data */
if (FILTER_MAT_OBJD(ma) || (filter_mode & ANIMFILTER_CURVESONLY)) { if (FILTER_MAT_OBJD(ma) || (filter_mode & ANIMFILTER_CURVESONLY)) {
if ((ads->filterflag & ADS_FILTER_ONLYDRIVERS)==0) { ANIMDATA_FILTER_CASES(ma,
// XXX the 'owner' info here is still subject to improvement { /* AnimData blocks - do nothing... */ },
items += animdata_filter_action(anim_data, ma->adt->action, filter_mode, ma, ANIMTYPE_DSMAT, (ID *)ma); items += animdata_filter_nla(anim_data, ma->adt, filter_mode, ma, ANIMTYPE_DSMAT, (ID *)ma);,
} items += animdata_filter_fcurves(anim_data, ma->adt->drivers.first, NULL, ma, ANIMTYPE_DSMAT, filter_mode, (ID *)ma);,
else { items += animdata_filter_action(anim_data, ma->adt->action, filter_mode, ma, ANIMTYPE_DSMAT, (ID *)ma);)
// need to make the ownertype normal object here... (maybe type should be a separate one for clarity?)
items += animdata_filter_fcurves(anim_data, ma->adt->drivers.first, NULL, ma, ANIMTYPE_DSMAT, filter_mode, (ID *)ma);
}
} }
} }
} }
@ -871,15 +1057,12 @@ static int animdata_filter_dopesheet_obdata (ListBase *anim_data, bDopeSheet *ad
/* add object-data animation channels? */ /* add object-data animation channels? */
if ((expanded) || (filter_mode & ANIMFILTER_CURVESONLY)) { if ((expanded) || (filter_mode & ANIMFILTER_CURVESONLY)) {
/* Action or Drivers? */ /* filtering for channels - nla, drivers, keyframes */
if ((ads->filterflag & ADS_FILTER_ONLYDRIVERS) == 0) { ANIMDATA_FILTER_CASES(iat,
// XXX the 'owner' info here is still subject to improvement { /* AnimData blocks - do nothing... */ },
items += animdata_filter_action(anim_data, iat->adt->action, filter_mode, iat, type, (ID *)iat); items+= animdata_filter_nla(anim_data, iat->adt, filter_mode, iat, type, (ID *)iat);,
} items+= animdata_filter_fcurves(anim_data, adt->drivers.first, NULL, iat, type, filter_mode, (ID *)iat);,
else { items += animdata_filter_action(anim_data, iat->adt->action, filter_mode, iat, type, (ID *)iat);)
// need to make the ownertype normal object here... (maybe type should be a separate one for clarity?)
items += animdata_filter_fcurves(anim_data, adt->drivers.first, NULL, iat, type, filter_mode, (ID *)iat);
}
} }
/* return the number of items added to the list */ /* return the number of items added to the list */
@ -889,12 +1072,14 @@ static int animdata_filter_dopesheet_obdata (ListBase *anim_data, bDopeSheet *ad
static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode) static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
{ {
bAnimListElem *ale=NULL; bAnimListElem *ale=NULL;
AnimData *adt = NULL;
Object *ob= base->object; Object *ob= base->object;
Key *key= ob_get_key(ob); Key *key= ob_get_key(ob);
short obdata_ok = 0;
int items = 0; int items = 0;
/* add this object as a channel first */ /* add this object as a channel first */
if ((filter_mode & ANIMFILTER_CURVESONLY) == 0) { if ((filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) == 0) {
/* check if filtering by selection */ /* check if filtering by selection */
if ANIMCHANNEL_SELOK((base->flag & SELECT)) { if ANIMCHANNEL_SELOK((base->flag & SELECT)) {
ale= make_new_animlistelem(base, ANIMTYPE_OBJECT, NULL, ANIMTYPE_NONE, NULL); ale= make_new_animlistelem(base, ANIMTYPE_OBJECT, NULL, ANIMTYPE_NONE, NULL);
@ -906,76 +1091,64 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B
} }
/* if collapsed, don't go any further (unless adding keyframes only) */ /* if collapsed, don't go any further (unless adding keyframes only) */
if ( (EXPANDED_OBJC(ob) == 0) && !(filter_mode & ANIMFILTER_CURVESONLY) ) if ( (EXPANDED_OBJC(ob) == 0) && !(filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) )
return items; return items;
/* Action or Drivers */ /* Action, Drivers, or NLA */
if ((ads->filterflag & ADS_FILTER_ONLYDRIVERS) == 0) { if (ob->adt) {
/* Action? */ adt= ob->adt;
if (ANIMDATA_HAS_KEYS(ob) /*&& !(ads->filterflag & ADS_FILTER_NOACTS)*/) { ANIMDATA_FILTER_CASES(ob,
AnimData *adt= ob->adt; { /* AnimData blocks - do nothing... */ },
{ /* nla */
/* add NLA tracks */
items += animdata_filter_nla(anim_data, adt, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob);
},
{ /* drivers */
/* include drivers-expand widget? */
if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLDRIVERS, base, ANIMTYPE_OBJECT, (ID *)ob);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
}
/* include action-expand widget? */ /* add F-Curve channels (drivers are F-Curves) */
if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) { if (EXPANDED_DRVD(adt) || !(filter_mode & ANIMFILTER_CHANNELS)) {
ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLACTD, base, ANIMTYPE_OBJECT, (ID *)ob); // need to make the ownertype normal object here... (maybe type should be a separate one for clarity?)
if (ale) { items += animdata_filter_fcurves(anim_data, adt->drivers.first, NULL, ob, ANIMTYPE_OBJECT, filter_mode, (ID *)ob);
BLI_addtail(anim_data, ale); }
items++; },
{ /* action (keyframes) */
/* include action-expand widget? */
if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLACTD, base, ANIMTYPE_OBJECT, (ID *)ob);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
}
/* add F-Curve channels? */
if (EXPANDED_ACTC(adt->action) || !(filter_mode & ANIMFILTER_CHANNELS)) {
// need to make the ownertype normal object here... (maybe type should be a separate one for clarity?)
items += animdata_filter_action(anim_data, adt->action, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob);
} }
} }
);
/* add F-Curve channels? */
if (EXPANDED_ACTC(adt->action) || !(filter_mode & ANIMFILTER_CHANNELS)) {
// need to make the ownertype normal object here... (maybe type should be a separate one for clarity?)
items += animdata_filter_action(anim_data, adt->action, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob);
}
}
} }
else {
/* Drivers */
if (ANIMDATA_HAS_DRIVERS(ob)) {
AnimData *adt= ob->adt;
/* include drivers-expand widget? */
if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLDRIVERS, base, ANIMTYPE_OBJECT, (ID *)ob);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
}
/* add F-Curve channels (drivers are F-Curves) */
if (EXPANDED_DRVD(adt) || !(filter_mode & ANIMFILTER_CHANNELS)) {
// need to make the ownertype normal object here... (maybe type should be a separate one for clarity?)
items += animdata_filter_fcurves(anim_data, adt->drivers.first, NULL, ob, ANIMTYPE_OBJECT, filter_mode, (ID *)ob);
}
}
}
/* ShapeKeys? */ /* ShapeKeys? */
if ((key) && !(ads->filterflag & ADS_FILTER_NOSHAPEKEYS)) { if ((key) && !(ads->filterflag & ADS_FILTER_NOSHAPEKEYS)) {
/* Animation or Drivers */ adt= key->adt;
if ((ads->filterflag & ADS_FILTER_ONLYDRIVERS) == 0) { ANIMDATA_FILTER_CASES(key,
/* include shapekey-expand widget? */ { /* AnimData blocks - do nothing... */ },
if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) { { /* nla */
ale= make_new_animlistelem(key, ANIMTYPE_DSSKEY, base, ANIMTYPE_OBJECT, (ID *)ob); /* add NLA tracks */
if (ale) { items += animdata_filter_nla(anim_data, adt, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob);
BLI_addtail(anim_data, ale); },
items++; { /* drivers */
}
}
/* add channels */
if (FILTER_SKE_OBJD(key) || (filter_mode & ANIMFILTER_CURVESONLY)) {
items += animdata_filter_shapekey(anim_data, key, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob);
}
}
else {
/* Drivers */
if (ANIMDATA_HAS_DRIVERS(key)) {
AnimData *adt= key->adt;
/* include shapekey-expand widget? */ /* include shapekey-expand widget? */
if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) { if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
ale= make_new_animlistelem(key, ANIMTYPE_DSSKEY, base, ANIMTYPE_OBJECT, (ID *)ob); ale= make_new_animlistelem(key, ANIMTYPE_DSSKEY, base, ANIMTYPE_OBJECT, (ID *)ob);
@ -985,16 +1158,29 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B
} }
} }
/* add F-Curve channels (drivers are F-Curves) */ /* add channels */
if (FILTER_SKE_OBJD(key)/*EXPANDED_DRVD(adt)*/ || !(filter_mode & ANIMFILTER_CHANNELS)) { if (FILTER_SKE_OBJD(key) || (filter_mode & ANIMFILTER_CURVESONLY)) {
// XXX owner info is messed up now... items += animdata_filter_shapekey(anim_data, key, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob);
items += animdata_filter_fcurves(anim_data, adt->drivers.first, NULL, ob, ANIMTYPE_OBJECT, filter_mode, (ID *)key); }
},
{ /* action (keyframes) */
/* include shapekey-expand widget? */
if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
ale= make_new_animlistelem(key, ANIMTYPE_DSSKEY, base, ANIMTYPE_OBJECT, (ID *)ob);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
}
/* add channels */
if (FILTER_SKE_OBJD(key) || (filter_mode & ANIMFILTER_CURVESONLY)) {
items += animdata_filter_shapekey(anim_data, key, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob);
} }
} }
} );
} }
/* Materials? */ /* Materials? */
if ((ob->totcol) && !(ads->filterflag & ADS_FILTER_NOMAT)) if ((ob->totcol) && !(ads->filterflag & ADS_FILTER_NOMAT))
items += animdata_filter_dopesheet_mats(anim_data, ads, base, filter_mode); items += animdata_filter_dopesheet_mats(anim_data, ads, base, filter_mode);
@ -1006,14 +1192,11 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B
Camera *ca= (Camera *)ob->data; Camera *ca= (Camera *)ob->data;
if ((ads->filterflag & ADS_FILTER_NOCAM) == 0) { if ((ads->filterflag & ADS_FILTER_NOCAM) == 0) {
if ((ads->filterflag & ADS_FILTER_ONLYDRIVERS)==0) { ANIMDATA_FILTER_CASES(ca,
if (ANIMDATA_HAS_KEYS(ca)) { /* AnimData blocks - do nothing... */ },
items += animdata_filter_dopesheet_obdata(anim_data, ads, base, filter_mode); obdata_ok= 1;,
} obdata_ok= 1;,
else { obdata_ok= 1;)
if (ANIMDATA_HAS_DRIVERS(ca))
items += animdata_filter_dopesheet_obdata(anim_data, ads, base, filter_mode);
}
} }
} }
break; break;
@ -1022,14 +1205,11 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B
Lamp *la= (Lamp *)ob->data; Lamp *la= (Lamp *)ob->data;
if ((ads->filterflag & ADS_FILTER_NOLAM) == 0) { if ((ads->filterflag & ADS_FILTER_NOLAM) == 0) {
if ((ads->filterflag & ADS_FILTER_ONLYDRIVERS)==0) { ANIMDATA_FILTER_CASES(la,
if (ANIMDATA_HAS_KEYS(la)) { /* AnimData blocks - do nothing... */ },
items += animdata_filter_dopesheet_obdata(anim_data, ads, base, filter_mode); obdata_ok= 1;,
} obdata_ok= 1;,
else { obdata_ok= 1;)
if (ANIMDATA_HAS_DRIVERS(la))
items += animdata_filter_dopesheet_obdata(anim_data, ads, base, filter_mode);
}
} }
} }
break; break;
@ -1038,18 +1218,17 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B
Curve *cu= (Curve *)ob->data; Curve *cu= (Curve *)ob->data;
if ((ads->filterflag & ADS_FILTER_NOCUR) == 0) { if ((ads->filterflag & ADS_FILTER_NOCUR) == 0) {
if ((ads->filterflag & ADS_FILTER_ONLYDRIVERS)==0) { ANIMDATA_FILTER_CASES(cu,
if (ANIMDATA_HAS_KEYS(cu)) { /* AnimData blocks - do nothing... */ },
items += animdata_filter_dopesheet_obdata(anim_data, ads, base, filter_mode); obdata_ok= 1;,
} obdata_ok= 1;,
else { obdata_ok= 1;)
if (ANIMDATA_HAS_DRIVERS(cu))
items += animdata_filter_dopesheet_obdata(anim_data, ads, base, filter_mode);
}
} }
} }
break; break;
} }
if (obdata_ok)
items += animdata_filter_dopesheet_obdata(anim_data, ads, base, filter_mode);
/* return the number of items added to the list */ /* return the number of items added to the list */
return items; return items;
@ -1058,11 +1237,12 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B
static int animdata_filter_dopesheet_scene (ListBase *anim_data, bDopeSheet *ads, Scene *sce, int filter_mode) static int animdata_filter_dopesheet_scene (ListBase *anim_data, bDopeSheet *ads, Scene *sce, int filter_mode)
{ {
World *wo= sce->world; World *wo= sce->world;
AnimData *adt= NULL;
bAnimListElem *ale; bAnimListElem *ale;
int items = 0; int items = 0;
/* add scene as a channel first (even if we aren't showing scenes we still need to show the scene's sub-data */ /* add scene as a channel first (even if we aren't showing scenes we still need to show the scene's sub-data */
if ((filter_mode & ANIMFILTER_CURVESONLY) == 0) { if ((filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) == 0) {
/* check if filtering by selection */ /* check if filtering by selection */
if (ANIMCHANNEL_SELOK( (sce->flag & SCE_DS_SELECTED) )) { if (ANIMCHANNEL_SELOK( (sce->flag & SCE_DS_SELECTED) )) {
ale= make_new_animlistelem(sce, ANIMTYPE_SCENE, NULL, ANIMTYPE_NONE, NULL); ale= make_new_animlistelem(sce, ANIMTYPE_SCENE, NULL, ANIMTYPE_NONE, NULL);
@ -1074,77 +1254,63 @@ static int animdata_filter_dopesheet_scene (ListBase *anim_data, bDopeSheet *ads
} }
/* if collapsed, don't go any further (unless adding keyframes only) */ /* if collapsed, don't go any further (unless adding keyframes only) */
if ( (EXPANDED_SCEC(sce) == 0) && !(filter_mode & ANIMFILTER_CURVESONLY) ) if ( (EXPANDED_SCEC(sce) == 0) && !(filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) )
return items; return items;
/* Action or Drivers */ /* Action, Drivers, or NLA for Scene */
if ((ads->filterflag & ADS_FILTER_ONLYDRIVERS) == 0) { if ((ads->filterflag & ADS_FILTER_NOSCE) == 0) {
/* Action? */ adt= sce->adt;
if (ANIMDATA_HAS_KEYS(sce) && !(ads->filterflag & ADS_FILTER_NOSCE)) { ANIMDATA_FILTER_CASES(sce,
AnimData *adt= sce->adt; { /* AnimData blocks - do nothing... */ },
{ /* nla */
/* add NLA tracks */
items += animdata_filter_nla(anim_data, adt, filter_mode, sce, ANIMTYPE_SCENE, (ID *)sce);
},
{ /* drivers */
/* include drivers-expand widget? */
if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLDRIVERS, sce, ANIMTYPE_SCENE, (ID *)sce);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
}
/* include action-expand widget? */ /* add F-Curve channels (drivers are F-Curves) */
if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) { if (EXPANDED_DRVD(adt) || !(filter_mode & ANIMFILTER_CHANNELS)) {
ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLACTD, sce, ANIMTYPE_SCENE, (ID *)sce); items += animdata_filter_fcurves(anim_data, adt->drivers.first, NULL, sce, ANIMTYPE_SCENE, filter_mode, (ID *)sce);
if (ale) { }
BLI_addtail(anim_data, ale); },
items++; { /* action */
/* include action-expand widget? */
if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLACTD, sce, ANIMTYPE_SCENE, (ID *)sce);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
}
/* add F-Curve channels? */
if (EXPANDED_ACTC(adt->action) || !(filter_mode & ANIMFILTER_CHANNELS)) {
items += animdata_filter_action(anim_data, adt->action, filter_mode, sce, ANIMTYPE_SCENE, (ID *)sce);
} }
} }
)
/* add F-Curve channels? */
if (EXPANDED_ACTC(adt->action) || !(filter_mode & ANIMFILTER_CHANNELS)) {
items += animdata_filter_action(anim_data, adt->action, filter_mode, sce, ANIMTYPE_SCENE, (ID *)sce);
}
}
}
else {
/* Drivers */
if (ANIMDATA_HAS_DRIVERS(sce) && !(ads->filterflag & ADS_FILTER_NOSCE)) {
AnimData *adt= sce->adt;
/* include drivers-expand widget? */
if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLDRIVERS, sce, ANIMTYPE_SCENE, (ID *)sce);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
}
/* add F-Curve channels (drivers are F-Curves) */
if (EXPANDED_DRVD(adt) || !(filter_mode & ANIMFILTER_CHANNELS)) {
items += animdata_filter_fcurves(anim_data, adt->drivers.first, NULL, sce, ANIMTYPE_SCENE, filter_mode, (ID *)sce);
}
}
} }
/* world */ /* world */
if ((wo && wo->adt) && !(ads->filterflag & ADS_FILTER_NOWOR)) { if ((wo && wo->adt) && !(ads->filterflag & ADS_FILTER_NOWOR)) {
/* Animation or Drivers */ /* Action, Drivers, or NLA for World */
if ((ads->filterflag & ADS_FILTER_ONLYDRIVERS) == 0) { adt= wo->adt;
AnimData *adt= wo->adt; ANIMDATA_FILTER_CASES(wo,
{ /* AnimData blocks - do nothing... */ },
/* include world-expand widget? */ { /* nla */
if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) { /* add NLA tracks */
ale= make_new_animlistelem(wo, ANIMTYPE_DSWOR, sce, ANIMTYPE_SCENE, (ID *)sce); items += animdata_filter_nla(anim_data, adt, filter_mode, wo, ANIMTYPE_DSWOR, (ID *)wo);
if (ale) { },
BLI_addtail(anim_data, ale); { /* drivers */
items++; /* include world-expand widget? */
}
}
/* add channels */
if (FILTER_WOR_SCED(wo) || (filter_mode & ANIMFILTER_CURVESONLY)) {
items += animdata_filter_action(anim_data, adt->action, filter_mode, wo, ANIMTYPE_DSWOR, (ID *)wo);
}
}
else {
/* Drivers */
if (ANIMDATA_HAS_DRIVERS(wo)) {
AnimData *adt= wo->adt;
/* include shapekey-expand widget? */
if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) { if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
ale= make_new_animlistelem(wo, ANIMTYPE_DSWOR, sce, ANIMTYPE_SCENE, (ID *)wo); ale= make_new_animlistelem(wo, ANIMTYPE_DSWOR, sce, ANIMTYPE_SCENE, (ID *)wo);
if (ale) { if (ale) {
@ -1158,8 +1324,23 @@ static int animdata_filter_dopesheet_scene (ListBase *anim_data, bDopeSheet *ads
// XXX owner info is messed up now... // XXX owner info is messed up now...
items += animdata_filter_fcurves(anim_data, adt->drivers.first, NULL, wo, ANIMTYPE_DSWOR, filter_mode, (ID *)wo); items += animdata_filter_fcurves(anim_data, adt->drivers.first, NULL, wo, ANIMTYPE_DSWOR, filter_mode, (ID *)wo);
} }
},
{ /* action */
/* include world-expand widget? */
if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
ale= make_new_animlistelem(wo, ANIMTYPE_DSWOR, sce, ANIMTYPE_SCENE, (ID *)sce);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
}
/* add channels */
if (FILTER_WOR_SCED(wo) || (filter_mode & ANIMFILTER_CURVESONLY)) {
items += animdata_filter_action(anim_data, adt->action, filter_mode, wo, ANIMTYPE_DSWOR, (ID *)wo);
}
} }
} )
} }
/* return the number of items added to the list */ /* return the number of items added to the list */
@ -1171,6 +1352,7 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int
{ {
Scene *sce= (Scene *)ads->source; Scene *sce= (Scene *)ads->source;
Base *base; Base *base;
bAnimListElem *ale;
int items = 0; int items = 0;
/* check that we do indeed have a scene */ /* check that we do indeed have a scene */
@ -1182,22 +1364,32 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int
/* scene-linked animation */ /* scene-linked animation */
// TODO: sequencer, composite nodes - are we to include those here too? // TODO: sequencer, composite nodes - are we to include those here too?
{ {
short sceOk, worOk; short sceOk= 0, worOk= 0;
/* check filtering-flags if ok */ /* check filtering-flags if ok */
if (ads->filterflag) { ANIMDATA_FILTER_CASES(sce,
if (ads->filterflag & ADS_FILTER_ONLYDRIVERS) { {
sceOk= (ANIMDATA_HAS_DRIVERS(sce) && !(ads->filterflag & ADS_FILTER_NOSCE)); /* for the special AnimData blocks only case, we only need to add
worOk= ((sce->world) && ANIMDATA_HAS_DRIVERS(sce->world) && !(ads->filterflag & ADS_FILTER_NOWOR)); * the block if it is valid... then other cases just get skipped (hence ok=0)
} */
else { ANIMDATA_ADD_ANIMDATA(sce);
sceOk= (ANIMDATA_HAS_KEYS(sce) && !(ads->filterflag & ADS_FILTER_NOSCE)); sceOk=0;
worOk= ((sce->world) && ANIMDATA_HAS_KEYS(sce->world) && !(ads->filterflag & ADS_FILTER_NOWOR)); },
} sceOk= !(ads->filterflag & ADS_FILTER_NOSCE);,
} sceOk= !(ads->filterflag & ADS_FILTER_NOSCE);,
else { sceOk= !(ads->filterflag & ADS_FILTER_NOSCE);)
sceOk= (ANIMDATA_HAS_KEYS(sce)); if (sce->world) {
worOk= ((sce->world) && ANIMDATA_HAS_KEYS(sce->world)); ANIMDATA_FILTER_CASES(sce->world,
{
/* for the special AnimData blocks only case, we only need to add
* the block if it is valid... then other cases just get skipped (hence ok=0)
*/
ANIMDATA_ADD_ANIMDATA(sce->world);
worOk=0;
},
worOk= !(ads->filterflag & ADS_FILTER_NOWOR);,
worOk= !(ads->filterflag & ADS_FILTER_NOWOR);,
worOk= !(ads->filterflag & ADS_FILTER_NOWOR);)
} }
/* check if not all bad (i.e. so there is something to show) */ /* check if not all bad (i.e. so there is something to show) */
@ -1239,13 +1431,33 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int
} }
/* check filters for datatypes */ /* check filters for datatypes */
if (ads->filterflag & ADS_FILTER_ONLYDRIVERS) { /* object */
actOk= (ANIMDATA_HAS_DRIVERS(ob)); actOk= 0;
keyOk= ((key) && ANIMDATA_HAS_DRIVERS(key) && !(ads->filterflag & ADS_FILTER_NOSHAPEKEYS)); keyOk= 0;
} ANIMDATA_FILTER_CASES(ob,
else { {
actOk= ANIMDATA_HAS_KEYS(ob); /* for the special AnimData blocks only case, we only need to add
keyOk= ((key) && ANIMDATA_HAS_KEYS(key) && !(ads->filterflag & ADS_FILTER_NOSHAPEKEYS)); * the block if it is valid... then other cases just get skipped (hence ok=0)
*/
ANIMDATA_ADD_ANIMDATA(ob);
actOk=0;
},
actOk= 1;,
actOk= 1;,
actOk= 1;)
if (key) {
/* shapekeys */
ANIMDATA_FILTER_CASES(key,
{
/* for the special AnimData blocks only case, we only need to add
* the block if it is valid... then other cases just get skipped (hence ok=0)
*/
ANIMDATA_ADD_ANIMDATA(key);
keyOk=0;
},
keyOk= 1;,
keyOk= 1;,
keyOk= 1;)
} }
/* materials - only for geometric types */ /* materials - only for geometric types */
@ -1260,18 +1472,20 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int
Material *ma= give_current_material(ob, a); Material *ma= give_current_material(ob, a);
/* if material has relevant animation data, break */ /* if material has relevant animation data, break */
if (ads->filterflag & ADS_FILTER_ONLYDRIVERS) { ANIMDATA_FILTER_CASES(ma,
if (ANIMDATA_HAS_DRIVERS(ma)) { {
matOk= 1; /* for the special AnimData blocks only case, we only need to add
break; * the block if it is valid... then other cases just get skipped (hence ok=0)
} */
} ANIMDATA_ADD_ANIMDATA(ma);
else { matOk=0;
if (ANIMDATA_HAS_KEYS(ma)) { },
matOk= 1; matOk= 1;,
break; matOk= 1;,
} matOk= 1;)
}
if (matOk)
break;
} }
} }
@ -1280,19 +1494,52 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int
case OB_CAMERA: /* ------- Camera ------------ */ case OB_CAMERA: /* ------- Camera ------------ */
{ {
Camera *ca= (Camera *)ob->data; Camera *ca= (Camera *)ob->data;
if (ads->filterflag & ADS_FILTER_ONLYDRIVERS) dataOk= 0;
dataOk= (ANIMDATA_HAS_DRIVERS(ca) && !(ads->filterflag & ADS_FILTER_NOCAM)); ANIMDATA_FILTER_CASES(ca,
else if ((ads->filterflag & ADS_FILTER_NOCAM)==0) {
dataOk= (ANIMDATA_HAS_KEYS(ca) && !(ads->filterflag & ADS_FILTER_NOCAM)); /* for the special AnimData blocks only case, we only need to add
* the block if it is valid... then other cases just get skipped (hence ok=0)
*/
ANIMDATA_ADD_ANIMDATA(ca);
dataOk=0;
},
dataOk= !(ads->filterflag & ADS_FILTER_NOCAM);,
dataOk= !(ads->filterflag & ADS_FILTER_NOCAM);,
dataOk= !(ads->filterflag & ADS_FILTER_NOCAM);)
} }
break; break;
case OB_LAMP: /* ---------- Lamp ----------- */ case OB_LAMP: /* ---------- Lamp ----------- */
{ {
Lamp *la= (Lamp *)ob->data; Lamp *la= (Lamp *)ob->data;
if (ads->filterflag & ADS_FILTER_ONLYDRIVERS) dataOk= 0;
dataOk= (ANIMDATA_HAS_DRIVERS(la) && !(ads->filterflag & ADS_FILTER_NOLAM)); ANIMDATA_FILTER_CASES(la,
else if ((ads->filterflag & ADS_FILTER_NOLAM)==0) {
dataOk= (ANIMDATA_HAS_KEYS(la) && !(ads->filterflag & ADS_FILTER_NOLAM)); /* for the special AnimData blocks only case, we only need to add
* the block if it is valid... then other cases just get skipped (hence ok=0)
*/
ANIMDATA_ADD_ANIMDATA(la);
dataOk=0;
},
dataOk= !(ads->filterflag & ADS_FILTER_NOLAM);,
dataOk= !(ads->filterflag & ADS_FILTER_NOLAM);,
dataOk= !(ads->filterflag & ADS_FILTER_NOLAM);)
}
break;
case OB_CURVE: /* ------- Curve ---------- */
{
Curve *cu= (Curve *)ob->data;
dataOk= 0;
ANIMDATA_FILTER_CASES(cu,
if ((ads->filterflag & ADS_FILTER_NOCUR)==0) {
/* for the special AnimData blocks only case, we only need to add
* the block if it is valid... then other cases just get skipped (hence ok=0)
*/
ANIMDATA_ADD_ANIMDATA(cu);
dataOk=0;
},
dataOk= !(ads->filterflag & ADS_FILTER_NOCUR);,
dataOk= !(ads->filterflag & ADS_FILTER_NOCUR);,
dataOk= !(ads->filterflag & ADS_FILTER_NOCUR);)
} }
break; break;
default: /* --- other --- */ default: /* --- other --- */
@ -1400,6 +1647,7 @@ int ANIM_animdata_filter (bAnimContext *ac, ListBase *anim_data, int filter_mode
case ANIMCONT_DOPESHEET: case ANIMCONT_DOPESHEET:
case ANIMCONT_FCURVES: case ANIMCONT_FCURVES:
case ANIMCONT_DRIVERS: case ANIMCONT_DRIVERS:
case ANIMCONT_NLA:
items= animdata_filter_dopesheet(anim_data, data, filter_mode); items= animdata_filter_dopesheet(anim_data, data, filter_mode);
break; break;
} }

@ -976,7 +976,7 @@ static void MARKER_OT_delete(wmOperatorType *ot)
/* ************************** registration **********************************/ /* ************************** registration **********************************/
/* called in screen_ops.c:ED_operatortypes_screen() */ /* called in screen_ops.c:ED_operatortypes_screen() */
void ED_marker_operatortypes(void) void ED_operatortypes_marker(void)
{ {
WM_operatortype_append(MARKER_OT_add); WM_operatortype_append(MARKER_OT_add);
WM_operatortype_append(MARKER_OT_move); WM_operatortype_append(MARKER_OT_move);

@ -83,10 +83,12 @@ static void change_frame_apply(bContext *C, wmOperator *op)
Scene *scene= CTX_data_scene(C); Scene *scene= CTX_data_scene(C);
int cfra; int cfra;
/* get frame, and clamp to MINFRAME */ /* get frame, and clamp to MINAFRAME
* - not MINFRAME, since it's useful to be able to key a few-frames back
*/
cfra= RNA_int_get(op->ptr, "frame"); cfra= RNA_int_get(op->ptr, "frame");
if (cfra < MINFRAME) cfra= MINFRAME; if (cfra < MINAFRAME) cfra= MINAFRAME;
CFRA= cfra; CFRA= cfra;
WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene); WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
@ -209,7 +211,7 @@ void ANIM_OT_change_frame(wmOperatorType *ot)
ot->modal= change_frame_modal; ot->modal= change_frame_modal;
/* rna */ /* rna */
RNA_def_int(ot->srna, "frame", 0, 1, MAXFRAME, "Frame", "", 1, MAXFRAME); RNA_def_int(ot->srna, "frame", 0, MINAFRAME, MAXFRAME, "Frame", "", MINAFRAME, MAXFRAME);
} }
/* ****************** set preview range operator ****************************/ /* ****************** set preview range operator ****************************/

@ -1,5 +1,30 @@
/* Testing code for 2.5 animation system /**
* Copyright 2009, Joshua Leung * $Id$
*
* ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): Joshua Leung (full recode)
*
* ***** END GPL LICENSE BLOCK *****
*/ */
#include <stdio.h> #include <stdio.h>
@ -94,7 +119,7 @@ FCurve *verify_driver_fcurve (ID *id, const char rna_path[], const int array_ind
fcu->driver= MEM_callocN(sizeof(ChannelDriver), "ChannelDriver"); fcu->driver= MEM_callocN(sizeof(ChannelDriver), "ChannelDriver");
/* add simple generator modifier for driver so that there is some visible representation */ /* add simple generator modifier for driver so that there is some visible representation */
fcurve_add_modifier(fcu, FMODIFIER_TYPE_GENERATOR); add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR);
/* just add F-Curve to end of driver list */ /* just add F-Curve to end of driver list */
BLI_addtail(&adt->drivers, fcu); BLI_addtail(&adt->drivers, fcu);

@ -0,0 +1,679 @@
/**
* $Id:
*
* ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2009 Blender Foundation.
* All rights reserved.
*
*
* Contributor(s): Blender Foundation, Joshua Leung
*
* ***** END GPL LICENSE BLOCK *****
*/
/* User-Interface Stuff for F-Modifiers:
* This file defines the (C-Coded) templates + editing callbacks needed
* by the interface stuff or F-Modifiers, as used by F-Curves in the Graph Editor,
* and NLA-Strips in the NLA Editor.
*/
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <float.h>
#include "DNA_anim_types.h"
#include "DNA_action_types.h"
#include "DNA_object_types.h"
#include "DNA_space_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_userdef_types.h"
#include "MEM_guardedalloc.h"
#include "BLI_arithb.h"
#include "BLI_blenlib.h"
#include "BLI_editVert.h"
#include "BLI_rand.h"
#include "BKE_animsys.h"
#include "BKE_action.h"
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_customdata.h"
#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
#include "BKE_object.h"
#include "BKE_global.h"
#include "BKE_nla.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
#include "BKE_utildefines.h"
#include "BIF_gl.h"
#include "WM_api.h"
#include "WM_types.h"
#include "RNA_access.h"
#include "RNA_define.h"
#include "ED_anim_api.h"
#include "ED_keyframing.h"
#include "ED_screen.h"
#include "ED_types.h"
#include "ED_util.h"
#include "UI_interface.h"
#include "UI_resources.h"
#include "UI_view2d.h"
// XXX! --------------------------------
/* temporary definition for limits of float number buttons (FLT_MAX tends to infinity with old system) */
#define UI_FLT_MAX 10000.0f
/* ********************************************** */
#define B_REDR 1
#define B_FMODIFIER_REDRAW 20
/* macro for use here to draw background box and set height */
// XXX for now, roundbox has it's callback func set to NULL to not intercept events
#define DRAW_BACKDROP(height) \
{ \
uiDefBut(block, ROUNDBOX, B_REDR, "", -3, yco-height, width+3, height-1, NULL, 5.0, 0.0, 12.0, (float)rb_col, ""); \
}
/* callback to verify modifier data */
static void validate_fmodifier_cb (bContext *C, void *fcm_v, void *dummy)
{
FModifier *fcm= (FModifier *)fcm_v;
FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
/* call the verify callback on the modifier if applicable */
if (fmi && fmi->verify_data)
fmi->verify_data(fcm);
}
/* callback to set the active modifier */
static void activate_fmodifier_cb (bContext *C, void *fmods_v, void *fcm_v)
{
ListBase *modifiers = (ListBase *)fmods_v;
FModifier *fcm= (FModifier *)fcm_v;
/* call API function to set the active modifier for active modifier-stack */
set_active_fmodifier(modifiers, fcm);
}
/* callback to remove the given modifier */
static void delete_fmodifier_cb (bContext *C, void *fmods_v, void *fcm_v)
{
ListBase *modifiers = (ListBase *)fmods_v;
FModifier *fcm= (FModifier *)fcm_v;
/* remove the given F-Modifier from the active modifier-stack */
remove_fmodifier(modifiers, fcm);
}
/* --------------- */
/* draw settings for generator modifier */
static void draw_modifier__generator(uiLayout *layout, ID *id, FModifier *fcm, short width)
{
FMod_Generator *data= (FMod_Generator *)fcm->data;
uiLayout *col, *row;
uiBlock *block;
uiBut *but;
PointerRNA ptr;
/* init the RNA-pointer */
RNA_pointer_create(id, &RNA_FModifierFunctionGenerator, fcm, &ptr);
/* basic settings (backdrop + mode selector + some padding) */
col= uiLayoutColumn(layout, 1);
block= uiLayoutGetBlock(layout);
uiBlockBeginAlign(block);
but= uiDefButR(block, MENU, B_FMODIFIER_REDRAW, NULL, 0, 0, width-30, UI_UNIT_Y, &ptr, "mode", -1, 0, 0, -1, -1, NULL);
uiButSetFunc(but, validate_fmodifier_cb, fcm, NULL);
uiDefButR(block, TOG, B_FMODIFIER_REDRAW, NULL, 0, 0, width-30, UI_UNIT_Y, &ptr, "additive", -1, 0, 0, -1, -1, NULL);
uiBlockEndAlign(block);
/* now add settings for individual modes */
switch (data->mode) {
case FCM_GENERATOR_POLYNOMIAL: /* polynomial expression */
{
float *cp = NULL;
char xval[32];
unsigned int i;
/* draw polynomial order selector */
row= uiLayoutRow(layout, 0);
block= uiLayoutGetBlock(row);
but= uiDefButI(block, NUM, B_FMODIFIER_REDRAW, "Poly Order: ", 10,0,width-30,19, &data->poly_order, 1, 100, 0, 0, "'Order' of the Polynomial - for a polynomial with n terms, 'order' is n-1");
uiButSetFunc(but, validate_fmodifier_cb, fcm, NULL);
/* draw controls for each coefficient and a + sign at end of row */
row= uiLayoutRow(layout, 1);
block= uiLayoutGetBlock(row);
uiDefBut(block, LABEL, 1, "y = ", 0, 0, 50, 20, NULL, 0.0, 0.0, 0, 0, "");
cp= data->coefficients;
for (i=0; (i < data->arraysize) && (cp); i++, cp++) {
/* coefficient */
uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 0, 0, 150, 20, cp, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Coefficient for polynomial");
/* 'x' param (and '+' if necessary) */
if (i) {
if (i == 1)
strcpy(xval, "x");
else
sprintf(xval, "x^%d", i);
uiDefBut(block, LABEL, 1, xval, 0, 0, 50, 20, NULL, 0.0, 0.0, 0, 0, "Power of x");
}
if ( (i != (data->arraysize - 1)) || ((i==0) && data->arraysize==2) ) {
uiDefBut(block, LABEL, 1, "+", 0,0 , 30, 20, NULL, 0.0, 0.0, 0, 0, "");
/* next coefficient on a new row */
row= uiLayoutRow(layout, 1);
block= uiLayoutGetBlock(row);
}
}
}
break;
case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* factorised polynomial expression */
{
float *cp = NULL;
unsigned int i;
/* draw polynomial order selector */
row= uiLayoutRow(layout, 0);
block= uiLayoutGetBlock(row);
but= uiDefButI(block, NUM, B_FMODIFIER_REDRAW, "Poly Order: ", 0,0,width-30,19, &data->poly_order, 1, 100, 0, 0, "'Order' of the Polynomial - for a polynomial with n terms, 'order' is n-1");
uiButSetFunc(but, validate_fmodifier_cb, fcm, NULL);
/* draw controls for each pair of coefficients */
row= uiLayoutRow(layout, 1);
block= uiLayoutGetBlock(row);
uiDefBut(block, LABEL, 1, "y=", 0, 0, 50, 20, NULL, 0.0, 0.0, 0, 0, "");
cp= data->coefficients;
for (i=0; (i < data->poly_order) && (cp); i++, cp+=2) {
/* opening bracket */
uiDefBut(block, LABEL, 1, "(", 0, 0, 20, 20, NULL, 0.0, 0.0, 0, 0, "");
/* coefficients */
uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 0, 0, 100, 20, cp, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Coefficient of x");
uiDefBut(block, LABEL, 1, "x+", 0, 0, 40, 20, NULL, 0.0, 0.0, 0, 0, "");
uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 0, 0, 100, 20, cp+1, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Second coefficient");
/* closing bracket and '+' sign */
if ( (i != (data->poly_order - 1)) || ((i==0) && data->poly_order==2) ) {
uiDefBut(block, LABEL, 1, ") +", 0, 0, 30, 20, NULL, 0.0, 0.0, 0, 0, "");
/* set up new row for the next pair of coefficients*/
row= uiLayoutRow(layout, 1);
block= uiLayoutGetBlock(row);
}
else
uiDefBut(block, LABEL, 1, ")", 0, 0, 20, 20, NULL, 0.0, 0.0, 0, 0, "");
}
}
break;
}
}
/* --------------- */
/* draw settings for noise modifier */
static void draw_modifier__fn_generator(uiLayout *layout, ID *id, FModifier *fcm, short width)
{
uiLayout *col;
PointerRNA ptr;
/* init the RNA-pointer */
RNA_pointer_create(id, &RNA_FModifierFunctionGenerator, fcm, &ptr);
/* add the settings */
col= uiLayoutColumn(layout, 1);
uiItemR(col, "", 0, &ptr, "type", 0, 0, 0);
uiItemR(col, NULL, 0, &ptr, "additive", 0, 0, 1);
col= uiLayoutColumn(layout, 0); // no grouping for now
uiItemR(col, NULL, 0, &ptr, "amplitude", 0, 0, 0);
uiItemR(col, NULL, 0, &ptr, "phase_multiplier", 0, 0, 0);
uiItemR(col, NULL, 0, &ptr, "phase_offset", 0, 0, 0);
uiItemR(col, NULL, 0, &ptr, "value_offset", 0, 0, 0);
}
/* --------------- */
/* draw settings for cycles modifier */
static void draw_modifier__cycles(uiLayout *layout, ID *id, FModifier *fcm, short width)
{
uiLayout *split, *col;
PointerRNA ptr;
/* init the RNA-pointer */
RNA_pointer_create(id, &RNA_FModifierCycles, fcm, &ptr);
/* split into 2 columns
* NOTE: the mode comboboxes shouldn't get labels, otherwise there isn't enough room
*/
split= uiLayoutSplit(layout, 0.5f);
/* before range */
col= uiLayoutColumn(split, 1);
uiItemL(col, "Before:", 0);
uiItemR(col, "", 0, &ptr, "before_mode", 0, 0, 0);
uiItemR(col, NULL, 0, &ptr, "before_cycles", 0, 0, 0);
/* after range */
col= uiLayoutColumn(split, 1);
uiItemL(col, "After:", 0);
uiItemR(col, "", 0, &ptr, "after_mode", 0, 0, 0);
uiItemR(col, NULL, 0, &ptr, "after_cycles", 0, 0, 0);
}
/* --------------- */
/* draw settings for noise modifier */
static void draw_modifier__noise(uiLayout *layout, ID *id, FModifier *fcm, short width)
{
uiLayout *split, *col;
PointerRNA ptr;
/* init the RNA-pointer */
RNA_pointer_create(id, &RNA_FModifierNoise, fcm, &ptr);
/* blending mode */
uiItemR(layout, NULL, 0, &ptr, "modification", 0, 0, 0);
/* split into 2 columns */
split= uiLayoutSplit(layout, 0.5f);
/* col 1 */
col= uiLayoutColumn(split, 0);
uiItemR(col, NULL, 0, &ptr, "size", 0, 0, 0);
uiItemR(col, NULL, 0, &ptr, "strength", 0, 0, 0);
/* col 2 */
col= uiLayoutColumn(split, 0);
uiItemR(col, NULL, 0, &ptr, "phase", 0, 0, 0);
uiItemR(col, NULL, 0, &ptr, "depth", 0, 0, 0);
}
/* --------------- */
#define BINARYSEARCH_FRAMEEQ_THRESH 0.0001
/* Binary search algorithm for finding where to insert Envelope Data Point.
* Returns the index to insert at (data already at that index will be offset if replace is 0)
*/
static int binarysearch_fcm_envelopedata_index (FCM_EnvelopeData array[], float frame, int arraylen, short *exists)
{
int start=0, end=arraylen;
int loopbreaker= 0, maxloop= arraylen * 2;
/* initialise exists-flag first */
*exists= 0;
/* sneaky optimisations (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
*/
if ((arraylen <= 0) || (array == NULL)) {
printf("Warning: binarysearch_fcm_envelopedata_index() encountered invalid array \n");
return 0;
}
else {
/* check whether to add before/after/on */
float framenum;
/* 'First' Point (when only one point, this case is used) */
framenum= array[0].time;
if (IS_EQT(frame, framenum, BINARYSEARCH_FRAMEEQ_THRESH)) {
*exists = 1;
return 0;
}
else if (frame < framenum)
return 0;
/* 'Last' Point */
framenum= array[(arraylen-1)].time;
if (IS_EQT(frame, framenum, BINARYSEARCH_FRAMEEQ_THRESH)) {
*exists= 1;
return (arraylen - 1);
}
else if (frame > framenum)
return arraylen;
}
/* most of the time, this loop is just to find where to put it
* - 'loopbreaker' is just here to prevent infinite loops
*/
for (loopbreaker=0; (start <= end) && (loopbreaker < maxloop); loopbreaker++) {
/* compute and get midpoint */
int mid = start + ((end - start) / 2); /* we calculate the midpoint this way to avoid int overflows... */
float midfra= array[mid].time;
/* check if exactly equal to midpoint */
if (IS_EQT(frame, midfra, BINARYSEARCH_FRAMEEQ_THRESH)) {
*exists = 1;
return mid;
}
/* repeat in upper/lower half */
if (frame > midfra)
start= mid + 1;
else if (frame < midfra)
end= mid - 1;
}
/* print error if loop-limit exceeded */
if (loopbreaker == (maxloop-1)) {
printf("Error: binarysearch_fcm_envelopedata_index() was taking too long \n");
// include debug info
printf("\tround = %d: start = %d, end = %d, arraylen = %d \n", loopbreaker, start, end, arraylen);
}
/* not found, so return where to place it */
return start;
}
/* callback to add new envelope data point */
// TODO: should we have a separate file for things like this?
static void fmod_envelope_addpoint_cb (bContext *C, void *fcm_dv, void *dummy)
{
Scene *scene= CTX_data_scene(C);
FMod_Envelope *env= (FMod_Envelope *)fcm_dv;
FCM_EnvelopeData *fedn;
FCM_EnvelopeData fed;
/* init template data */
fed.min= -1.0f;
fed.max= 1.0f;
fed.time= (float)scene->r.cfra; // XXX make this int for ease of use?
fed.f1= fed.f2= 0;
/* check that no data exists for the current frame... */
if (env->data) {
short exists = -1;
int i= binarysearch_fcm_envelopedata_index(env->data, (float)(scene->r.cfra), env->totvert, &exists);
/* binarysearch_...() will set exists by default to 0, so if it is non-zero, that means that the point exists already */
if (exists)
return;
/* add new */
fedn= MEM_callocN((env->totvert+1)*sizeof(FCM_EnvelopeData), "FCM_EnvelopeData");
/* add the points that should occur before the point to be pasted */
if (i > 0)
memcpy(fedn, env->data, i*sizeof(FCM_EnvelopeData));
/* add point to paste at index i */
*(fedn + i)= fed;
/* add the points that occur after the point to be pasted */
if (i < env->totvert)
memcpy(fedn+i+1, env->data+i, (env->totvert-i)*sizeof(FCM_EnvelopeData));
/* replace (+ free) old with new */
MEM_freeN(env->data);
env->data= fedn;
env->totvert++;
}
else {
env->data= MEM_callocN(sizeof(FCM_EnvelopeData), "FCM_EnvelopeData");
*(env->data)= fed;
env->totvert= 1;
}
}
/* callback to remove envelope data point */
// TODO: should we have a separate file for things like this?
static void fmod_envelope_deletepoint_cb (bContext *C, void *fcm_dv, void *ind_v)
{
FMod_Envelope *env= (FMod_Envelope *)fcm_dv;
FCM_EnvelopeData *fedn;
int index= GET_INT_FROM_POINTER(ind_v);
/* check that no data exists for the current frame... */
if (env->totvert > 1) {
/* allocate a new smaller array */
fedn= MEM_callocN(sizeof(FCM_EnvelopeData)*(env->totvert-1), "FCM_EnvelopeData");
memcpy(fedn, &env->data, sizeof(FCM_EnvelopeData)*(index));
memcpy(&fedn[index], &env->data[index+1], sizeof(FCM_EnvelopeData)*(env->totvert-index-1));
/* free old array, and set the new */
MEM_freeN(env->data);
env->data= fedn;
env->totvert--;
}
else {
/* just free array, since the only vert was deleted */
if (env->data)
MEM_freeN(env->data);
env->totvert= 0;
}
}
/* draw settings for envelope modifier */
static void draw_modifier__envelope(uiLayout *layout, ID *id, FModifier *fcm, short width)
{
FMod_Envelope *env= (FMod_Envelope *)fcm->data;
FCM_EnvelopeData *fed;
uiLayout *col, *row;
uiBlock *block;
uiBut *but;
PointerRNA ptr;
int i;
/* init the RNA-pointer */
RNA_pointer_create(id, &RNA_FModifierEnvelope, fcm, &ptr);
/* general settings */
col= uiLayoutColumn(layout, 1);
uiItemL(col, "Envelope:", 0);
uiItemR(col, NULL, 0, &ptr, "reference_value", 0, 0, 0);
row= uiLayoutRow(col, 1);
uiItemR(row, "Min", 0, &ptr, "default_minimum", 0, 0, 0);
uiItemR(row, "Max", 0, &ptr, "default_maximum", 0, 0, 0);
/* control points header */
// TODO: move this control-point control stuff to using the new special widgets for lists
// the current way is far too cramped
row= uiLayoutRow(layout, 0);
block= uiLayoutGetBlock(row);
uiDefBut(block, LABEL, 1, "Control Points:", 0, 0, 150, 20, NULL, 0.0, 0.0, 0, 0, "");
but= uiDefBut(block, BUT, B_FMODIFIER_REDRAW, "Add Point", 0,0,150,19, NULL, 0, 0, 0, 0, "Adds a new control-point to the envelope on the current frame");
uiButSetFunc(but, fmod_envelope_addpoint_cb, env, NULL);
/* control points list */
for (i=0, fed=env->data; i < env->totvert; i++, fed++) {
/* get a new row to operate on */
row= uiLayoutRow(layout, 1);
block= uiLayoutGetBlock(row);
uiBlockBeginAlign(block);
but=uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Fra:", 0, 0, 90, 20, &fed->time, -UI_FLT_MAX, UI_FLT_MAX, 10, 1, "Frame that envelope point occurs");
uiButSetFunc(but, validate_fmodifier_cb, fcm, NULL);
uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Min:", 0, 0, 100, 20, &fed->min, -UI_FLT_MAX, UI_FLT_MAX, 10, 2, "Minimum bound of envelope at this point");
uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Max:", 0, 0, 100, 20, &fed->max, -UI_FLT_MAX, UI_FLT_MAX, 10, 2, "Maximum bound of envelope at this point");
but= uiDefIconBut(block, BUT, B_FMODIFIER_REDRAW, ICON_X, 0, 0, 18, 20, NULL, 0.0, 0.0, 0.0, 0.0, "Delete envelope control point");
uiButSetFunc(but, fmod_envelope_deletepoint_cb, env, SET_INT_IN_POINTER(i));
uiBlockBeginAlign(block);
}
}
/* --------------- */
/* draw settings for limits modifier */
static void draw_modifier__limits(uiLayout *layout, ID *id, FModifier *fcm, short width)
{
uiLayout *split, *col, *row;
PointerRNA ptr;
/* init the RNA-pointer */
RNA_pointer_create(id, &RNA_FModifierLimits, fcm, &ptr);
/* row 1: minimum */
{
row= uiLayoutRow(layout, 0);
/* split into 2 columns */
split= uiLayoutSplit(layout, 0.5f);
/* x-minimum */
col= uiLayoutColumn(split, 1);
uiItemR(col, NULL, 0, &ptr, "use_minimum_x", 0, 0, 0);
uiItemR(col, NULL, 0, &ptr, "minimum_x", 0, 0, 0);
/* y-minimum*/
col= uiLayoutColumn(split, 1);
uiItemR(col, NULL, 0, &ptr, "use_minimum_y", 0, 0, 0);
uiItemR(col, NULL, 0, &ptr, "minimum_y", 0, 0, 0);
}
/* row 2: minimum */
{
row= uiLayoutRow(layout, 0);
/* split into 2 columns */
split= uiLayoutSplit(layout, 0.5f);
/* x-minimum */
col= uiLayoutColumn(split, 1);
uiItemR(col, NULL, 0, &ptr, "use_maximum_x", 0, 0, 0);
uiItemR(col, NULL, 0, &ptr, "maximum_x", 0, 0, 0);
/* y-minimum*/
col= uiLayoutColumn(split, 1);
uiItemR(col, NULL, 0, &ptr, "use_maximum_y", 0, 0, 0);
uiItemR(col, NULL, 0, &ptr, "maximum_y", 0, 0, 0);
}
}
/* --------------- */
void ANIM_uiTemplate_fmodifier_draw (uiLayout *layout, ID *id, ListBase *modifiers, FModifier *fcm)
{
FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
uiLayout *box, *row, *subrow;
uiBlock *block;
uiBut *but;
short width= 314;
/* draw header */
{
/* get layout-row + UI-block for this */
box= uiLayoutBox(layout);
row= uiLayoutRow(box, 0);
block= uiLayoutGetBlock(row); // err...
uiBlockSetEmboss(block, UI_EMBOSSN);
/* left-align -------------------------------------------- */
subrow= uiLayoutRow(row, 0);
uiLayoutSetAlignment(subrow, UI_LAYOUT_ALIGN_LEFT);
/* expand */
uiDefIconButBitS(block, ICONTOG, FMODIFIER_FLAG_EXPANDED, B_REDR, ICON_TRIA_RIGHT, 0, -1, UI_UNIT_X, UI_UNIT_Y, &fcm->flag, 0.0, 0.0, 0, 0, "Modifier is expanded.");
/* checkbox for 'active' status (for now) */
but= uiDefIconButBitS(block, ICONTOG, FMODIFIER_FLAG_ACTIVE, B_REDR, ICON_RADIOBUT_OFF, 0, -1, UI_UNIT_X, UI_UNIT_Y, &fcm->flag, 0.0, 0.0, 0, 0, "Modifier is active one.");
uiButSetFunc(but, activate_fmodifier_cb, modifiers, fcm);
/* name */
if (fmi)
uiDefBut(block, LABEL, 1, fmi->name, 0, 0, 150, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "F-Curve Modifier Type. Click to make modifier active one.");
else
uiDefBut(block, LABEL, 1, "<Unknown Modifier>", 0, 0, 150, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "F-Curve Modifier Type. Click to make modifier active one.");
/* right-align ------------------------------------------- */
subrow= uiLayoutRow(row, 0);
uiLayoutSetAlignment(subrow, UI_LAYOUT_ALIGN_RIGHT);
/* 'mute' button */
uiDefIconButBitS(block, ICONTOG, FMODIFIER_FLAG_MUTED, B_REDR, ICON_MUTE_IPO_OFF, 0, 0, UI_UNIT_X, UI_UNIT_Y, &fcm->flag, 0.0, 0.0, 0, 0, "Modifier is temporarily muted (not evaluated).");
/* delete button */
but= uiDefIconBut(block, BUT, B_REDR, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, "Delete F-Curve Modifier.");
uiButSetFunc(but, delete_fmodifier_cb, modifiers, fcm);
uiBlockSetEmboss(block, UI_EMBOSS);
}
/* when modifier is expanded, draw settings */
if (fcm->flag & FMODIFIER_FLAG_EXPANDED) {
/* set up the flexible-box layout which acts as the backdrop for the modifier settings */
box= uiLayoutBox(layout);
/* draw settings for individual modifiers */
switch (fcm->type) {
case FMODIFIER_TYPE_GENERATOR: /* Generator */
draw_modifier__generator(box, id, fcm, width);
break;
case FMODIFIER_TYPE_FN_GENERATOR: /* Built-In Function Generator */
draw_modifier__fn_generator(box, id, fcm, width);
break;
case FMODIFIER_TYPE_CYCLES: /* Cycles */
draw_modifier__cycles(box, id, fcm, width);
break;
case FMODIFIER_TYPE_ENVELOPE: /* Envelope */
draw_modifier__envelope(box, id, fcm, width);
break;
case FMODIFIER_TYPE_LIMITS: /* Limits */
draw_modifier__limits(box, id, fcm, width);
break;
case FMODIFIER_TYPE_NOISE: /* Noise */
draw_modifier__noise(box, id, fcm, width);
break;
default: /* unknown type */
break;
}
}
}
/* ********************************************** */

@ -51,7 +51,6 @@
#include "DNA_armature_types.h" #include "DNA_armature_types.h"
#include "DNA_camera_types.h" #include "DNA_camera_types.h"
#include "DNA_curve_types.h" #include "DNA_curve_types.h"
#include "DNA_ipo_types.h"
#include "DNA_object_types.h" #include "DNA_object_types.h"
#include "DNA_screen_types.h" #include "DNA_screen_types.h"
#include "DNA_scene_types.h" #include "DNA_scene_types.h"
@ -64,6 +63,7 @@
#include "DNA_gpencil_types.h" #include "DNA_gpencil_types.h"
#include "DNA_windowmanager_types.h" #include "DNA_windowmanager_types.h"
#include "DNA_world_types.h" #include "DNA_world_types.h"
#include "DNA_view2d_types.h"
#include "BKE_action.h" #include "BKE_action.h"
#include "BKE_depsgraph.h" #include "BKE_depsgraph.h"
@ -234,45 +234,87 @@ static ActKeyColumn *cfra_find_actkeycolumn (ListBase *keys, float cframe)
return NULL; return NULL;
} }
#if 0 // disabled, as some intel cards have problems with this /* coordinates for diamond shape */
/* Draw a simple diamond shape with a filled in center (in screen space) */ static const float _unit_diamond_shape[4][2] = {
static void draw_key_but(int x, int y, short w, short h, int sel) {0.0f, 1.0f}, /* top vert */
{1.0f, 0.0f}, /* mid-right */
{0.0f, -1.0f}, /* bottom vert */
{-1.0f, 0.0f} /* mid-left */
};
/* draw a simple diamond shape with OpenGL */
void draw_keyframe_shape (float x, float y, float xscale, float hsize, short sel, short mode)
{ {
int xmin= x, ymin= y; static GLuint displist1=0;
int xmax= x+w-1, ymax= y+h-1; static GLuint displist2=0;
int xc= (xmin+xmax)/2, yc= (ymin+ymax)/2;
/* interior - hardcoded colors (for selected and unselected only) */ /* initialise 2 display lists for diamond shape - one empty, one filled */
if (sel) glColor3ub(0xF1, 0xCA, 0x13); if (displist1 == 0) {
else glColor3ub(0xE9, 0xE9, 0xE9); displist1= glGenLists(1);
glNewList(displist1, GL_COMPILE);
glBegin(GL_QUADS); glBegin(GL_LINE_LOOP);
glVertex2i(xc, ymin); glVertex2fv(_unit_diamond_shape[0]);
glVertex2i(xmax, yc); glVertex2fv(_unit_diamond_shape[1]);
glVertex2i(xc, ymax); glVertex2fv(_unit_diamond_shape[2]);
glVertex2i(xmin, yc); glVertex2fv(_unit_diamond_shape[3]);
glEnd(); glEnd();
glEndList();
}
if (displist2 == 0) {
displist2= glGenLists(1);
glNewList(displist2, GL_COMPILE);
glBegin(GL_QUADS);
glVertex2fv(_unit_diamond_shape[0]);
glVertex2fv(_unit_diamond_shape[1]);
glVertex2fv(_unit_diamond_shape[2]);
glVertex2fv(_unit_diamond_shape[3]);
glEnd();
glEndList();
}
/* outline */ /* adjust view transform before starting */
glColor3ub(0, 0, 0); glTranslatef(x, y, 0.0f);
glScalef(1.0f/xscale*hsize, hsize, 1.0f);
glBegin(GL_LINE_LOOP); /* anti-aliased lines for more consistent appearance */
glVertex2i(xc, ymin); glEnable(GL_LINE_SMOOTH);
glVertex2i(xmax, yc);
glVertex2i(xc, ymax); /* draw! */
glVertex2i(xmin, yc); if ELEM(mode, KEYFRAME_SHAPE_INSIDE, KEYFRAME_SHAPE_BOTH) {
glEnd(); /* interior - hardcoded colors (for selected and unselected only) */
if (sel) UI_ThemeColorShade(TH_STRIP_SELECT, 50);
else glColor3ub(0xE9, 0xE9, 0xE9);
glCallList(displist2);
}
if ELEM(mode, KEYFRAME_SHAPE_FRAME, KEYFRAME_SHAPE_BOTH) {
/* exterior - black frame */
glColor3ub(0, 0, 0);
glCallList(displist1);
}
glDisable(GL_LINE_SMOOTH);
/* restore view transform */
glScalef(xscale/hsize, 1.0f/hsize, 1.0);
glTranslatef(-x, -y, 0.0f);
} }
#endif
static void draw_keylist(gla2DDrawInfo *di, ListBase *keys, ListBase *blocks, float ypos) static void draw_keylist(View2D *v2d, ListBase *keys, ListBase *blocks, float ypos)
{ {
ActKeyColumn *ak; ActKeyColumn *ak;
ActKeyBlock *ab; ActKeyBlock *ab;
float xscale;
glEnable(GL_BLEND); glEnable(GL_BLEND);
/* get View2D scaling factor */
UI_view2d_getscale(v2d, &xscale, NULL);
/* draw keyblocks */ /* draw keyblocks */
if (blocks) { if (blocks) {
for (ab= blocks->first; ab; ab= ab->next) { for (ab= blocks->first; ab; ab= ab->next) {
@ -292,18 +334,13 @@ static void draw_keylist(gla2DDrawInfo *di, ListBase *keys, ListBase *blocks, fl
totCurves = (startCurves>endCurves)? endCurves: startCurves; totCurves = (startCurves>endCurves)? endCurves: startCurves;
if (ab->totcurve >= totCurves) { if (ab->totcurve >= totCurves) {
int sc_xa, sc_xb, sc_ya, sc_yb;
/* get co-ordinates of block */
gla2DDrawTranslatePt(di, ab->start, ypos, &sc_xa, &sc_ya);
gla2DDrawTranslatePt(di, ab->end, ypos, &sc_xb, &sc_yb);
/* draw block */ /* draw block */
if (ab->sel) if (ab->sel)
UI_ThemeColor4(TH_STRIP_SELECT); UI_ThemeColor4(TH_STRIP_SELECT);
else else
UI_ThemeColor4(TH_STRIP); UI_ThemeColor4(TH_STRIP);
glRectf((float)sc_xa, (float)sc_ya-3, (float)sc_xb, (float)sc_yb+5);
glRectf(ab->start, ypos-5, ab->end, ypos+5);
} }
} }
} }
@ -311,18 +348,28 @@ static void draw_keylist(gla2DDrawInfo *di, ListBase *keys, ListBase *blocks, fl
/* draw keys */ /* draw keys */
if (keys) { if (keys) {
for (ak= keys->first; ak; ak= ak->next) { for (ak= keys->first; ak; ak= ak->next) {
int sc_x, sc_y; /* draw using OpenGL - uglier but faster */
// NOTE: a previous version of this didn't work nice for some intel cards
draw_keyframe_shape(ak->cfra, ypos, xscale, 5.0f, (ak->sel & SELECT), KEYFRAME_SHAPE_BOTH);
#if 0 // OLD CODE
//int sc_x, sc_y;
/* get co-ordinate to draw at */ /* get co-ordinate to draw at */
gla2DDrawTranslatePt(di, ak->cfra, ypos, &sc_x, &sc_y); //gla2DDrawTranslatePt(di, ak->cfra, ypos, &sc_x, &sc_y);
/* draw using icons - old way which is slower but more proven */ /* draw using icons - old way which is slower but more proven */
if (ak->sel & SELECT) UI_icon_draw_aspect((float)sc_x-7, (float)sc_y-6, ICON_SPACE2, 1.0f); //if (ak->sel & SELECT) UI_icon_draw_aspect((float)sc_x-7, (float)sc_y-6, ICON_SPACE2, 1.0f);
else UI_icon_draw_aspect((float)sc_x-7, (float)sc_y-6, ICON_SPACE3, 1.0f); //else UI_icon_draw_aspect((float)sc_x-7, (float)sc_y-6, ICON_SPACE3, 1.0f);
#endif // OLD CODE
#if 0 // NEW NON-WORKING CODE
/* draw icon */
// FIXME: this draws slightly wrong, as we need to apply some offset for icon, but that depends on scaling
// so for now disabled
//int icon = (ak->sel & SELECT) ? ICON_SPACE2 : ICON_SPACE3;
//UI_icon_draw_aspect(ak->cfra, ypos-6, icon, 1.0f);
#endif // NEW NON-WORKING CODE
/* draw using OpenGL - slightly uglier but faster */
// NOTE: disabled for now, as some intel cards seem to have problems with this
//draw_key_but(sc_x-5, sc_y-4, 11, 11, (ak->sel & SELECT));
} }
} }
@ -331,89 +378,86 @@ static void draw_keylist(gla2DDrawInfo *di, ListBase *keys, ListBase *blocks, fl
/* *************************** Channel Drawing Funcs *************************** */ /* *************************** Channel Drawing Funcs *************************** */
void draw_scene_channel(gla2DDrawInfo *di, ActKeysInc *aki, Scene *sce, float ypos) void draw_scene_channel(View2D *v2d, bDopeSheet *ads, Scene *sce, float ypos)
{ {
ListBase keys = {0, 0}; ListBase keys = {0, 0};
ListBase blocks = {0, 0}; ListBase blocks = {0, 0};
scene_to_keylist(sce, &keys, &blocks, aki); scene_to_keylist(ads, sce, &keys, &blocks);
draw_keylist(di, &keys, &blocks, ypos); draw_keylist(v2d, &keys, &blocks, ypos);
BLI_freelistN(&keys); BLI_freelistN(&keys);
BLI_freelistN(&blocks); BLI_freelistN(&blocks);
} }
void draw_object_channel(gla2DDrawInfo *di, ActKeysInc *aki, Object *ob, float ypos) void draw_object_channel(View2D *v2d, bDopeSheet *ads, Object *ob, float ypos)
{ {
ListBase keys = {0, 0}; ListBase keys = {0, 0};
ListBase blocks = {0, 0}; ListBase blocks = {0, 0};
ob_to_keylist(ob, &keys, &blocks, aki); ob_to_keylist(ads, ob, &keys, &blocks);
draw_keylist(di, &keys, &blocks, ypos); draw_keylist(v2d, &keys, &blocks, ypos);
BLI_freelistN(&keys); BLI_freelistN(&keys);
BLI_freelistN(&blocks); BLI_freelistN(&blocks);
} }
void draw_fcurve_channel(gla2DDrawInfo *di, ActKeysInc *aki, FCurve *fcu, float ypos) void draw_fcurve_channel(View2D *v2d, AnimData *adt, FCurve *fcu, float ypos)
{ {
ListBase keys = {0, 0}; ListBase keys = {0, 0};
ListBase blocks = {0, 0}; ListBase blocks = {0, 0};
fcurve_to_keylist(fcu, &keys, &blocks, aki); fcurve_to_keylist(adt, fcu, &keys, &blocks);
draw_keylist(di, &keys, &blocks, ypos); draw_keylist(v2d, &keys, &blocks, ypos);
BLI_freelistN(&keys); BLI_freelistN(&keys);
BLI_freelistN(&blocks); BLI_freelistN(&blocks);
} }
void draw_agroup_channel(gla2DDrawInfo *di, ActKeysInc *aki, bActionGroup *agrp, float ypos) void draw_agroup_channel(View2D *v2d, AnimData *adt, bActionGroup *agrp, float ypos)
{ {
ListBase keys = {0, 0}; ListBase keys = {0, 0};
ListBase blocks = {0, 0}; ListBase blocks = {0, 0};
agroup_to_keylist(agrp, &keys, &blocks, aki); agroup_to_keylist(adt, agrp, &keys, &blocks);
draw_keylist(di, &keys, &blocks, ypos); draw_keylist(v2d, &keys, &blocks, ypos);
BLI_freelistN(&keys); BLI_freelistN(&keys);
BLI_freelistN(&blocks); BLI_freelistN(&blocks);
} }
void draw_action_channel(gla2DDrawInfo *di, ActKeysInc *aki, bAction *act, float ypos) void draw_action_channel(View2D *v2d, AnimData *adt, bAction *act, float ypos)
{ {
ListBase keys = {0, 0}; ListBase keys = {0, 0};
ListBase blocks = {0, 0}; ListBase blocks = {0, 0};
action_to_keylist(act, &keys, &blocks, aki); action_to_keylist(adt, act, &keys, &blocks);
draw_keylist(di, &keys, &blocks, ypos); draw_keylist(v2d, &keys, &blocks, ypos);
BLI_freelistN(&keys); BLI_freelistN(&keys);
BLI_freelistN(&blocks); BLI_freelistN(&blocks);
} }
void draw_gpl_channel(gla2DDrawInfo *di, ActKeysInc *aki, bGPDlayer *gpl, float ypos) void draw_gpl_channel(View2D *v2d, bDopeSheet *ads, bGPDlayer *gpl, float ypos)
{ {
ListBase keys = {0, 0}; ListBase keys = {0, 0};
gpl_to_keylist(gpl, &keys, NULL, aki); gpl_to_keylist(ads, gpl, &keys, NULL);
draw_keylist(di, &keys, NULL, ypos); draw_keylist(v2d, &keys, NULL, ypos);
BLI_freelistN(&keys); BLI_freelistN(&keys);
} }
/* *************************** Keyframe List Conversions *************************** */ /* *************************** Keyframe List Conversions *************************** */
void scene_to_keylist(Scene *sce, ListBase *keys, ListBase *blocks, ActKeysInc *aki) void scene_to_keylist(bDopeSheet *ads, Scene *sce, ListBase *keys, ListBase *blocks)
{ {
if (sce) { if (sce) {
bDopeSheet *ads= (aki)? (aki->ads) : NULL;
AnimData *adt; AnimData *adt;
int filterflag; int filterflag;
/* get filterflag */ /* get filterflag */
if (ads) if (ads)
filterflag= ads->filterflag; filterflag= ads->filterflag;
else if ((aki) && (aki->actmode == -1)) /* only set like this by NLA */
filterflag= ADS_FILTER_NLADUMMY;
else else
filterflag= 0; filterflag= 0;
@ -423,7 +467,7 @@ void scene_to_keylist(Scene *sce, ListBase *keys, ListBase *blocks, ActKeysInc *
// TODO: when we adapt NLA system, this needs to be the NLA-scaled version // TODO: when we adapt NLA system, this needs to be the NLA-scaled version
if (adt->action) if (adt->action)
action_to_keylist(adt->action, keys, blocks, aki); action_to_keylist(adt, adt->action, keys, blocks);
} }
/* world animdata */ /* world animdata */
@ -432,17 +476,16 @@ void scene_to_keylist(Scene *sce, ListBase *keys, ListBase *blocks, ActKeysInc *
// TODO: when we adapt NLA system, this needs to be the NLA-scaled version // TODO: when we adapt NLA system, this needs to be the NLA-scaled version
if (adt->action) if (adt->action)
action_to_keylist(adt->action, keys, blocks, aki); action_to_keylist(adt, adt->action, keys, blocks);
} }
} }
} }
void ob_to_keylist(Object *ob, ListBase *keys, ListBase *blocks, ActKeysInc *aki) void ob_to_keylist(bDopeSheet *ads, Object *ob, ListBase *keys, ListBase *blocks)
{ {
Key *key= ob_get_key(ob); Key *key= ob_get_key(ob);
if (ob) { if (ob) {
bDopeSheet *ads= (aki)? (aki->ads) : NULL;
int filterflag; int filterflag;
/* get filterflag */ /* get filterflag */
@ -453,79 +496,18 @@ void ob_to_keylist(Object *ob, ListBase *keys, ListBase *blocks, ActKeysInc *aki
/* Add action keyframes */ /* Add action keyframes */
if (ob->adt && ob->adt->action) if (ob->adt && ob->adt->action)
action_nlascaled_to_keylist(ob, ob->adt->action, keys, blocks, aki); action_to_keylist(ob->adt, ob->adt->action, keys, blocks);
/* Add shapekey keyframes (only if dopesheet allows, if it is available) */ /* Add shapekey keyframes (only if dopesheet allows, if it is available) */
// TODO: when we adapt NLA system, this needs to be the NLA-scaled version
if ((key && key->adt && key->adt->action) && !(filterflag & ADS_FILTER_NOSHAPEKEYS)) if ((key && key->adt && key->adt->action) && !(filterflag & ADS_FILTER_NOSHAPEKEYS))
action_to_keylist(key->adt->action, keys, blocks, aki); action_to_keylist(key->adt, key->adt->action, keys, blocks);
#if 0 // XXX old animation system // TODO: restore materials, and object data, etc.
/* Add material keyframes (only if dopesheet allows, if it is available) */
if ((ob->totcol) && !(filterflag & ADS_FILTER_NOMAT)) {
short a;
for (a=0; a<ob->totcol; a++) {
Material *ma= give_current_material(ob, a);
if (ELEM(NULL, ma, ma->ipo) == 0)
ipo_to_keylist(ma->ipo, keys, blocks, aki);
}
}
/* Add object data keyframes */
switch (ob->type) {
case OB_CAMERA: /* ------- Camera ------------ */
{
Camera *ca= (Camera *)ob->data;
if ((ca->ipo) && !(filterflag & ADS_FILTER_NOCAM))
ipo_to_keylist(ca->ipo, keys, blocks, aki);
}
break;
case OB_LAMP: /* ---------- Lamp ----------- */
{
Lamp *la= (Lamp *)ob->data;
if ((la->ipo) && !(filterflag & ADS_FILTER_NOLAM))
ipo_to_keylist(la->ipo, keys, blocks, aki);
}
break;
case OB_CURVE: /* ------- Curve ---------- */
{
Curve *cu= (Curve *)ob->data;
if ((cu->ipo) && !(filterflag & ADS_FILTER_NOCUR))
ipo_to_keylist(cu->ipo, keys, blocks, aki);
}
break;
}
#endif // XXX old animation system
} }
} }
static short bezt_in_aki_range (ActKeysInc *aki, BezTriple *bezt)
{
/* when aki == NULL, we don't care about range */
if (aki == NULL)
return 1;
/* if start and end are both 0, then don't care about range */ void fcurve_to_keylist(AnimData *adt, FCurve *fcu, ListBase *keys, ListBase *blocks)
if (IS_EQ(aki->start, 0) && IS_EQ(aki->end, 0))
return 1;
/* if nla-scaling is in effect, apply appropriate scaling adjustments */
#if 0 // XXX this was from some buggy code... do not port for now
if (aki->ob) {
float frame= get_action_frame_inv(aki->ob, bezt->vec[1][0]);
return IN_RANGE(frame, aki->start, aki->end);
}
else {
/* check if in range */
return IN_RANGE(bezt->vec[1][0], aki->start, aki->end);
}
#endif // XXX this was from some buggy code... do not port for now
return 1;
}
void fcurve_to_keylist(FCurve *fcu, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
{ {
BezTriple *bezt; BezTriple *bezt;
ActKeyColumn *ak, *ak2; ActKeyColumn *ak, *ak2;
@ -533,15 +515,17 @@ void fcurve_to_keylist(FCurve *fcu, ListBase *keys, ListBase *blocks, ActKeysInc
int v; int v;
if (fcu && fcu->totvert && fcu->bezt) { if (fcu && fcu->totvert && fcu->bezt) {
/* apply NLA-mapping (if applicable) */
if (adt)
ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 1);
/* loop through beztriples, making ActKeys and ActKeyBlocks */ /* loop through beztriples, making ActKeys and ActKeyBlocks */
bezt= fcu->bezt; bezt= fcu->bezt;
for (v=0; v < fcu->totvert; v++, bezt++) { for (v=0; v < fcu->totvert; v++, bezt++) {
/* only if keyframe is in range (optimisation) */ /* only if keyframe is in range (optimisation) */
if (bezt_in_aki_range(aki, bezt)) { add_bezt_to_keycolumnslist(keys, bezt);
add_bezt_to_keycolumnslist(keys, bezt); if (blocks) add_bezt_to_keyblockslist(blocks, fcu, v);
if (blocks) add_bezt_to_keyblockslist(blocks, fcu, v);
}
} }
/* update the number of curves that elements have appeared in */ /* update the number of curves that elements have appeared in */
@ -577,65 +561,38 @@ void fcurve_to_keylist(FCurve *fcu, ListBase *keys, ListBase *blocks, ActKeysInc
} }
} }
} }
/* unapply NLA-mapping if applicable */
ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 1);
} }
} }
void agroup_to_keylist(bActionGroup *agrp, ListBase *keys, ListBase *blocks, ActKeysInc *aki) void agroup_to_keylist(AnimData *adt, bActionGroup *agrp, ListBase *keys, ListBase *blocks)
{ {
FCurve *fcu; FCurve *fcu;
if (agrp) { if (agrp) {
/* loop through F-Curves */ /* loop through F-Curves */
for (fcu= agrp->channels.first; fcu && fcu->grp==agrp; fcu= fcu->next) { for (fcu= agrp->channels.first; fcu && fcu->grp==agrp; fcu= fcu->next) {
fcurve_to_keylist(fcu, keys, blocks, aki); fcurve_to_keylist(adt, fcu, keys, blocks);
} }
} }
} }
void action_to_keylist(bAction *act, ListBase *keys, ListBase *blocks, ActKeysInc *aki) void action_to_keylist(AnimData *adt, bAction *act, ListBase *keys, ListBase *blocks)
{ {
FCurve *fcu; FCurve *fcu;
if (act) { if (act) {
/* loop through F-Curves */ /* loop through F-Curves */
for (fcu= act->curves.first; fcu; fcu= fcu->next) { for (fcu= act->curves.first; fcu; fcu= fcu->next) {
fcurve_to_keylist(fcu, keys, blocks, aki); fcurve_to_keylist(adt, fcu, keys, blocks);
} }
} }
} }
void action_nlascaled_to_keylist(Object *ob, bAction *act, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
{
FCurve *fcu;
Object *oldob= NULL;
/* although apply and clearing NLA-scaling pre-post creating keylist does impact on performance, void gpl_to_keylist(bDopeSheet *ads, bGPDlayer *gpl, ListBase *keys, ListBase *blocks)
* the effects should be fairly minimal, as we're already going through the keyframes multiple times
* already for blocks too...
*/
if (act) {
/* if 'aki' is provided, store it's current ob to restore later as it might not be the same */
if (aki) {
oldob= aki->ob;
aki->ob= ob;
}
/* loop through F-Curves
* - scaling correction only does times for center-points, so should be faster
*/
for (fcu= act->curves.first; fcu; fcu= fcu->next) {
ANIM_nla_mapping_apply_fcurve(ob, fcu, 0, 1);
fcurve_to_keylist(fcu, keys, blocks, aki);
ANIM_nla_mapping_apply_fcurve(ob, fcu, 1, 1);
}
/* if 'aki' is provided, restore ob */
if (aki)
aki->ob= oldob;
}
}
void gpl_to_keylist(bGPDlayer *gpl, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
{ {
bGPDframe *gpf; bGPDframe *gpf;
ActKeyColumn *ak; ActKeyColumn *ak;

@ -128,6 +128,10 @@ static short agrp_keys_bezier_loop(BeztEditData *bed, bActionGroup *agrp, BeztEd
{ {
FCurve *fcu; FCurve *fcu;
/* sanity check */
if (agrp == NULL)
return 0;
/* only iterate over the F-Curves that are in this group */ /* only iterate over the F-Curves that are in this group */
for (fcu= agrp->channels.first; fcu && fcu->grp==agrp; fcu= fcu->next) { for (fcu= agrp->channels.first; fcu && fcu->grp==agrp; fcu= fcu->next) {
if (ANIM_fcurve_keys_bezier_loop(bed, fcu, bezt_ok, bezt_cb, fcu_cb)) if (ANIM_fcurve_keys_bezier_loop(bed, fcu, bezt_ok, bezt_cb, fcu_cb))
@ -142,6 +146,10 @@ static short act_keys_bezier_loop(BeztEditData *bed, bAction *act, BeztEditFunc
{ {
FCurve *fcu; FCurve *fcu;
/* sanity check */
if (act == NULL)
return 0;
/* just loop through all F-Curves */ /* just loop through all F-Curves */
for (fcu= act->curves.first; fcu; fcu= fcu->next) { for (fcu= act->curves.first; fcu; fcu= fcu->next) {
if (ANIM_fcurve_keys_bezier_loop(bed, fcu, bezt_ok, bezt_cb, fcu_cb)) if (ANIM_fcurve_keys_bezier_loop(bed, fcu, bezt_ok, bezt_cb, fcu_cb))
@ -154,6 +162,10 @@ static short act_keys_bezier_loop(BeztEditData *bed, bAction *act, BeztEditFunc
/* This function is used to loop over the keyframe data of an AnimData block */ /* This function is used to loop over the keyframe data of an AnimData block */
static short adt_keys_bezier_loop(BeztEditData *bed, AnimData *adt, BeztEditFunc bezt_ok, BeztEditFunc bezt_cb, FcuEditFunc fcu_cb, int filterflag) static short adt_keys_bezier_loop(BeztEditData *bed, AnimData *adt, BeztEditFunc bezt_ok, BeztEditFunc bezt_cb, FcuEditFunc fcu_cb, int filterflag)
{ {
/* sanity check */
if (adt == NULL)
return 0;
/* drivers or actions? */ /* drivers or actions? */
if (filterflag & ADS_FILTER_ONLYDRIVERS) { if (filterflag & ADS_FILTER_ONLYDRIVERS) {
FCurve *fcu; FCurve *fcu;
@ -178,6 +190,10 @@ static short ob_keys_bezier_loop(BeztEditData *bed, Object *ob, BeztEditFunc bez
{ {
Key *key= ob_get_key(ob); Key *key= ob_get_key(ob);
/* sanity check */
if (ob == NULL)
return 0;
/* firstly, Object's own AnimData */ /* firstly, Object's own AnimData */
if (ob->adt) if (ob->adt)
adt_keys_bezier_loop(bed, ob->adt, bezt_ok, bezt_cb, fcu_cb, filterflag); adt_keys_bezier_loop(bed, ob->adt, bezt_ok, bezt_cb, fcu_cb, filterflag);
@ -194,7 +210,11 @@ static short ob_keys_bezier_loop(BeztEditData *bed, Object *ob, BeztEditFunc bez
/* This function is used to loop over the keyframe data in a Scene */ /* This function is used to loop over the keyframe data in a Scene */
static short scene_keys_bezier_loop(BeztEditData *bed, Scene *sce, BeztEditFunc bezt_ok, BeztEditFunc bezt_cb, FcuEditFunc fcu_cb, int filterflag) static short scene_keys_bezier_loop(BeztEditData *bed, Scene *sce, BeztEditFunc bezt_ok, BeztEditFunc bezt_cb, FcuEditFunc fcu_cb, int filterflag)
{ {
World *wo= sce->world; World *wo= (sce) ? sce->world : NULL;
/* sanity check */
if (sce == NULL)
return 0;
/* Scene's own animation */ /* Scene's own animation */
if (sce->adt) if (sce->adt)
@ -231,7 +251,7 @@ short ANIM_animchannel_keys_bezier_loop(BeztEditData *bed, bAnimListElem *ale, B
return act_keys_bezier_loop(bed, (bAction *)ale->data, bezt_ok, bezt_cb, fcu_cb); return act_keys_bezier_loop(bed, (bAction *)ale->data, bezt_ok, bezt_cb, fcu_cb);
case ALE_OB: /* object */ case ALE_OB: /* object */
return ob_keys_bezier_loop(bed, (Object *)ale->data, bezt_ok, bezt_cb, fcu_cb, filterflag); return ob_keys_bezier_loop(bed, (Object *)ale->key_data, bezt_ok, bezt_cb, fcu_cb, filterflag);
case ALE_SCE: /* scene */ case ALE_SCE: /* scene */
return scene_keys_bezier_loop(bed, (Scene *)ale->data, bezt_ok, bezt_cb, fcu_cb, filterflag); return scene_keys_bezier_loop(bed, (Scene *)ale->data, bezt_ok, bezt_cb, fcu_cb, filterflag);
} }

@ -52,6 +52,8 @@
#include "ED_keyframing.h" #include "ED_keyframing.h"
#include "ED_keyframes_edit.h" #include "ED_keyframes_edit.h"
#include "RNA_access.h"
/* This file contains code for various keyframe-editing tools which are 'destructive' /* This file contains code for various keyframe-editing tools which are 'destructive'
* (i.e. they will modify the order of the keyframes, and change the size of the array). * (i.e. they will modify the order of the keyframes, and change the size of the array).
* While some of these tools may eventually be moved out into blenkernel, for now, it is * While some of these tools may eventually be moved out into blenkernel, for now, it is

@ -1,5 +1,30 @@
/* Testing code for 2.5 animation system /**
* Copyright 2009, Joshua Leung * $Id$
*
* ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): Joshua Leung (full recode)
*
* ***** END GPL LICENSE BLOCK *****
*/ */
#include <stdio.h> #include <stdio.h>
@ -29,6 +54,7 @@
#include "BKE_action.h" #include "BKE_action.h"
#include "BKE_constraint.h" #include "BKE_constraint.h"
#include "BKE_fcurve.h" #include "BKE_fcurve.h"
#include "BKE_nla.h"
#include "BKE_global.h" #include "BKE_global.h"
#include "BKE_utildefines.h" #include "BKE_utildefines.h"
#include "BKE_context.h" #include "BKE_context.h"
@ -697,9 +723,119 @@ static float visualkey_get_value (PointerRNA *ptr, PropertyRNA *prop, int array_
/* ------------------------- Insert Key API ------------------------- */ /* ------------------------- Insert Key API ------------------------- */
/* Secondary Keyframing API call:
* Use this when validation of necessary animation data is not necessary, since an RNA-pointer to the necessary
* data being keyframed, and a pointer to the F-Curve to use have both been provided.
*
* The flag argument is used for special settings that alter the behaviour of
* the keyframe insertion. These include the 'visual' keyframing modes, quick refresh,
* and extra keyframe filtering.
*/
short insert_keyframe_direct (PointerRNA ptr, PropertyRNA *prop, FCurve *fcu, float cfra, short flag)
{
float curval= 0.0f;
/* no F-Curve to add keyframe to? */
if (fcu == NULL) {
printf("ERROR: no F-Curve to add keyframes to \n");
return 0;
}
/* if no property given yet, try to validate from F-Curve info */
if ((ptr.id.data == NULL) && (ptr.data==NULL)) {
printf("ERROR: no RNA-pointer available to retrieve values for keyframing from\n");
return 0;
}
if (prop == NULL) {
PointerRNA tmp_ptr;
/* try to get property we should be affecting */
if ((RNA_path_resolve(&ptr, fcu->rna_path, &tmp_ptr, &prop) == 0) || (prop == NULL)) {
/* property not found... */
char *idname= (ptr.id.data) ? ((ID *)ptr.id.data)->name : "<No ID-Pointer>";
printf("Insert Key: Could not insert keyframe, as RNA Path is invalid for the given ID (ID = %s, Path = %s)\n", idname, fcu->rna_path);
return 0;
}
else {
/* property found, so overwrite 'ptr' to make later code easier */
ptr= tmp_ptr;
}
}
/* set additional flags for the F-Curve (i.e. only integer values) */
fcu->flag &= ~(FCURVE_INT_VALUES|FCURVE_DISCRETE_VALUES);
switch (RNA_property_type(prop)) {
case PROP_FLOAT:
/* do nothing */
break;
case PROP_INT:
/* do integer (only 'whole' numbers) interpolation between all points */
fcu->flag |= FCURVE_INT_VALUES;
break;
default:
/* do 'discrete' (i.e. enum, boolean values which cannot take any intermediate
* values at all) interpolation between all points
* - however, we must also ensure that evaluated values are only integers still
*/
fcu->flag |= (FCURVE_DISCRETE_VALUES|FCURVE_INT_VALUES);
break;
}
/* obtain value to give keyframe */
if ( (flag & INSERTKEY_MATRIX) &&
(visualkey_can_use(&ptr, prop)) )
{
/* visual-keying is only available for object and pchan datablocks, as
* it works by keyframing using a value extracted from the final matrix
* instead of using the kt system to extract a value.
*/
curval= visualkey_get_value(&ptr, prop, fcu->array_index);
}
else {
/* read value from system */
curval= setting_get_rna_value(&ptr, prop, fcu->array_index);
}
/* only insert keyframes where they are needed */
if (flag & INSERTKEY_NEEDED) {
short insert_mode;
/* check whether this curve really needs a new keyframe */
insert_mode= new_key_needed(fcu, cfra, curval);
/* insert new keyframe at current frame */
if (insert_mode)
insert_vert_fcurve(fcu, cfra, curval, (flag & INSERTKEY_FAST));
/* delete keyframe immediately before/after newly added */
switch (insert_mode) {
case KEYNEEDED_DELPREV:
delete_fcurve_key(fcu, fcu->totvert-2, 1);
break;
case KEYNEEDED_DELNEXT:
delete_fcurve_key(fcu, 1, 1);
break;
}
/* only return success if keyframe added */
if (insert_mode)
return 1;
}
else {
/* just insert keyframe */
insert_vert_fcurve(fcu, cfra, curval, (flag & INSERTKEY_FAST));
/* return success */
return 1;
}
/* failed */
return 0;
}
/* Main Keyframing API call: /* Main Keyframing API call:
* Use this when validation of necessary animation data isn't necessary as it * Use this when validation of necessary animation data is necessary, since it may not exist yet.
* already exists. It will insert a keyframe using the current value being keyframed.
* *
* The flag argument is used for special settings that alter the behaviour of * The flag argument is used for special settings that alter the behaviour of
* the keyframe insertion. These include the 'visual' keyframing modes, quick refresh, * the keyframe insertion. These include the 'visual' keyframing modes, quick refresh,
@ -719,102 +855,31 @@ short insert_keyframe (ID *id, bAction *act, const char group[], const char rna_
} }
/* get F-Curve - if no action is provided, keyframe to the default one attached to this ID-block */ /* get F-Curve - if no action is provided, keyframe to the default one attached to this ID-block */
if (act == NULL) if (act == NULL) {
AnimData *adt= BKE_animdata_from_id(id);
/* get action to add F-Curve+keyframe to */
act= verify_adt_action(id, 1); act= verify_adt_action(id, 1);
/* apply NLA-mapping to frame to use (if applicable) */
cfra= BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
}
fcu= verify_fcurve(act, group, rna_path, array_index, 1); fcu= verify_fcurve(act, group, rna_path, array_index, 1);
/* only continue if we have an F-Curve to add keyframe to */ /* apply special time tweaking */
if (fcu) { // XXX check on this stuff...
float curval= 0.0f; if (GS(id->name) == ID_OB) {
//Object *ob= (Object *)id;
/* set additional flags for the F-Curve (i.e. only integer values) */ /* ancient time-offset cruft */
fcu->flag &= ~(FCURVE_INT_VALUES|FCURVE_DISCRETE_VALUES); //if ( (ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)) ) {
switch (RNA_property_type(prop)) { // /* actually frametofloat calc again! */
case PROP_FLOAT: // cfra-= give_timeoffset(ob)*scene->r.framelen;
/* do nothing */ //}
break;
case PROP_INT:
/* do integer (only 'whole' numbers) interpolation between all points */
fcu->flag |= FCURVE_INT_VALUES;
break;
default:
/* do 'discrete' (i.e. enum, boolean values which cannot take any intermediate
* values at all) interpolation between all points
* - however, we must also ensure that evaluated values are only integers still
*/
fcu->flag |= (FCURVE_DISCRETE_VALUES|FCURVE_INT_VALUES);
break;
}
/* apply special time tweaking */
// XXX check on this stuff...
if (GS(id->name) == ID_OB) {
//Object *ob= (Object *)id;
/* apply NLA-scaling (if applicable) */
//cfra= get_action_frame(ob, cfra);
/* ancient time-offset cruft */
//if ( (ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)) ) {
// /* actually frametofloat calc again! */
// cfra-= give_timeoffset(ob)*scene->r.framelen;
//}
}
/* obtain value to give keyframe */
if ( (flag & INSERTKEY_MATRIX) &&
(visualkey_can_use(&ptr, prop)) )
{
/* visual-keying is only available for object and pchan datablocks, as
* it works by keyframing using a value extracted from the final matrix
* instead of using the kt system to extract a value.
*/
curval= visualkey_get_value(&ptr, prop, array_index);
}
else {
/* read value from system */
curval= setting_get_rna_value(&ptr, prop, array_index);
}
/* only insert keyframes where they are needed */
if (flag & INSERTKEY_NEEDED) {
short insert_mode;
/* check whether this curve really needs a new keyframe */
insert_mode= new_key_needed(fcu, cfra, curval);
/* insert new keyframe at current frame */
if (insert_mode)
insert_vert_fcurve(fcu, cfra, curval, (flag & INSERTKEY_FAST));
/* delete keyframe immediately before/after newly added */
switch (insert_mode) {
case KEYNEEDED_DELPREV:
delete_fcurve_key(fcu, fcu->totvert-2, 1);
break;
case KEYNEEDED_DELNEXT:
delete_fcurve_key(fcu, 1, 1);
break;
}
/* only return success if keyframe added */
if (insert_mode)
return 1;
}
else {
/* just insert keyframe */
insert_vert_fcurve(fcu, cfra, curval, (flag & INSERTKEY_FAST));
/* return success */
return 1;
}
} }
/* no F-Curve to add keyframes to */ /* insert keyframe */
printf("ERROR: no F-Curve to add keyframes to \n"); return insert_keyframe_direct(ptr, prop, fcu, cfra, flag);
/* return failure */
return 0;
} }
/* ************************************************** */ /* ************************************************** */
@ -839,6 +904,9 @@ short delete_keyframe (ID *id, bAction *act, const char group[], const char rna_
/* if no action is provided, use the default one attached to this ID-block */ /* if no action is provided, use the default one attached to this ID-block */
AnimData *adt= BKE_animdata_from_id(id); AnimData *adt= BKE_animdata_from_id(id);
act= adt->action; act= adt->action;
/* apply NLA-mapping to frame to use (if applicable) */
cfra= BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
} }
/* we don't check the validity of the path here yet, but it should be ok... */ /* we don't check the validity of the path here yet, but it should be ok... */
fcu= verify_fcurve(act, group, rna_path, array_index, 0); fcu= verify_fcurve(act, group, rna_path, array_index, 0);
@ -852,9 +920,6 @@ short delete_keyframe (ID *id, bAction *act, const char group[], const char rna_
if (GS(id->name) == ID_OB) { if (GS(id->name) == ID_OB) {
//Object *ob= (Object *)id; //Object *ob= (Object *)id;
/* apply NLA-scaling (if applicable) */
// cfra= get_action_frame(ob, cfra);
/* ancient time-offset cruft */ /* ancient time-offset cruft */
//if ( (ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)) ) { //if ( (ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)) ) {
// /* actually frametofloat calc again! */ // /* actually frametofloat calc again! */
@ -1241,6 +1306,13 @@ static int insert_key_button_exec (bContext *C, wmOperator *op)
MEM_freeN(path); MEM_freeN(path);
} }
else if (ptr.type == &RNA_NlaStrip) {
/* handle special vars for NLA-strips */
NlaStrip *strip= (NlaStrip *)ptr.data;
FCurve *fcu= list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), 0);
success+= insert_keyframe_direct(ptr, prop, fcu, cfra, 0);
}
else { else {
if (G.f & G_DEBUG) if (G.f & G_DEBUG)
printf("Button Insert-Key: no path to property \n"); printf("Button Insert-Key: no path to property \n");
@ -1358,6 +1430,31 @@ void ANIM_OT_delete_keyframe_button (wmOperatorType *ot)
/* --------------- API/Per-Datablock Handling ------------------- */ /* --------------- API/Per-Datablock Handling ------------------- */
/* Checks if some F-Curve has a keyframe for a given frame */
short fcurve_frame_has_keyframe (FCurve *fcu, float frame, short filter)
{
/* quick sanity check */
if (fcu == NULL)
return 0;
/* we either include all regardless of muting, or only non-muted */
if ((filter & ANIMFILTER_KEYS_MUTED) || (fcu->flag & FCURVE_MUTED)==0) {
short replace = -1;
int i = binarysearch_bezt_index(fcu->bezt, frame, fcu->totvert, &replace);
/* binarysearch_bezt_index will set replace to be 0 or 1
* - obviously, 1 represents a match
*/
if (replace) {
/* sanity check: 'i' may in rare cases exceed arraylen */
if ((i >= 0) && (i < fcu->totvert))
return 1;
}
}
return 0;
}
/* Checks whether an Action has a keyframe for a given frame /* Checks whether an Action has a keyframe for a given frame
* Since we're only concerned whether a keyframe exists, we can simply loop until a match is found... * Since we're only concerned whether a keyframe exists, we can simply loop until a match is found...
*/ */
@ -1379,20 +1476,8 @@ short action_frame_has_keyframe (bAction *act, float frame, short filter)
for (fcu= act->curves.first; fcu; fcu= fcu->next) { for (fcu= act->curves.first; fcu; fcu= fcu->next) {
/* only check if there are keyframes (currently only of type BezTriple) */ /* only check if there are keyframes (currently only of type BezTriple) */
if (fcu->bezt && fcu->totvert) { if (fcu->bezt && fcu->totvert) {
/* we either include all regardless of muting, or only non-muted */ if (fcurve_frame_has_keyframe(fcu, frame, filter))
if ((filter & ANIMFILTER_KEYS_MUTED) || (fcu->flag & FCURVE_MUTED)==0) { return 1;
short replace = -1;
int i = binarysearch_bezt_index(fcu->bezt, frame, fcu->totvert, &replace);
/* binarysearch_bezt_index will set replace to be 0 or 1
* - obviously, 1 represents a match
*/
if (replace) {
/* sanity check: 'i' may in rare cases exceed arraylen */
if ((i >= 0) && (i < fcu->totvert))
return 1;
}
}
} }
} }

@ -1,5 +1,30 @@
/* Testing code for 2.5 animation system /**
* Copyright 2009, Joshua Leung * $Id$
*
* ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): Joshua Leung (full recode)
*
* ***** END GPL LICENSE BLOCK *****
*/ */
#include <stdio.h> #include <stdio.h>
@ -1060,6 +1085,9 @@ int modify_keyframes (bContext *C, ListBase *dsources, bAction *act, KeyingSet *
case ID_MA: /* Material Keyframes */ case ID_MA: /* Material Keyframes */
WM_event_add_notifier(C, NC_MATERIAL|ND_KEYS, ksp->id); WM_event_add_notifier(C, NC_MATERIAL|ND_KEYS, ksp->id);
break; break;
default: /* Any keyframes */
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
break;
} }
} }
} }
@ -1166,6 +1194,9 @@ int modify_keyframes (bContext *C, ListBase *dsources, bAction *act, KeyingSet *
case ID_MA: /* Material Keyframes */ case ID_MA: /* Material Keyframes */
WM_event_add_notifier(C, NC_MATERIAL|ND_KEYS, cks->id); WM_event_add_notifier(C, NC_MATERIAL|ND_KEYS, cks->id);
break; break;
default: /* Any keyframes */
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
break;
} }
} }
} }

@ -152,7 +152,7 @@ typedef struct RigControl {
} RigControl; } RigControl;
void BIF_retargetArc(struct bContext *C, ReebArc *earc, RigGraph *template_rigg); void BIF_retargetArc(struct bContext *C, ReebArc *earc, RigGraph *template_rigg);
RigGraph *RIG_graphFromArmature(struct bContext *C, struct Object *ob, struct bArmature *arm); RigGraph *RIG_graphFromArmature(const struct bContext *C, struct Object *ob, struct bArmature *arm);
int RIG_nbJoints(RigGraph *rg); int RIG_nbJoints(RigGraph *rg);
char *RIG_nameBone(RigGraph *rg, int arc_index, int bone_index); char *RIG_nameBone(RigGraph *rg, int arc_index, int bone_index);
void RIG_freeRigGraph(BGraph *rg); void RIG_freeRigGraph(BGraph *rg);

@ -42,7 +42,7 @@ void ARMATURE_OT_subdivide_multi(struct wmOperatorType *ot);
void ARMATURE_OT_parent_set(struct wmOperatorType *ot); void ARMATURE_OT_parent_set(struct wmOperatorType *ot);
void ARMATURE_OT_parent_clear(struct wmOperatorType *ot); void ARMATURE_OT_parent_clear(struct wmOperatorType *ot);
void ARMATURE_OT_select_all_toggle(struct wmOperatorType *ot); void ARMATURE_OT_select_all_toggle(struct wmOperatorType *ot);
void ARMATURE_OT_select_invert(struct wmOperatorType *ot); void ARMATURE_OT_select_inverse(struct wmOperatorType *ot);
void ARMATURE_OT_select_hierarchy(struct wmOperatorType *ot); void ARMATURE_OT_select_hierarchy(struct wmOperatorType *ot);
void ARMATURE_OT_select_linked(struct wmOperatorType *ot); void ARMATURE_OT_select_linked(struct wmOperatorType *ot);
void ARMATURE_OT_delete(struct wmOperatorType *ot); void ARMATURE_OT_delete(struct wmOperatorType *ot);
@ -56,10 +56,11 @@ void POSE_OT_rot_clear(struct wmOperatorType *ot);
void POSE_OT_loc_clear(struct wmOperatorType *ot); void POSE_OT_loc_clear(struct wmOperatorType *ot);
void POSE_OT_scale_clear(struct wmOperatorType *ot); void POSE_OT_scale_clear(struct wmOperatorType *ot);
void POSE_OT_select_all_toggle(struct wmOperatorType *ot); void POSE_OT_select_all_toggle(struct wmOperatorType *ot);
void POSE_OT_select_invert(struct wmOperatorType *ot); void POSE_OT_select_inverse(struct wmOperatorType *ot);
void POSE_OT_select_parent(struct wmOperatorType *ot); void POSE_OT_select_parent(struct wmOperatorType *ot);
void POSE_OT_select_hierarchy(struct wmOperatorType *ot); void POSE_OT_select_hierarchy(struct wmOperatorType *ot);
void POSE_OT_select_linked(struct wmOperatorType *ot); void POSE_OT_select_linked(struct wmOperatorType *ot);
void POSE_OT_select_constraint_target(struct wmOperatorType *ot);
void SKETCH_OT_gesture(struct wmOperatorType *ot); void SKETCH_OT_gesture(struct wmOperatorType *ot);
void SKETCH_OT_delete(struct wmOperatorType *ot); void SKETCH_OT_delete(struct wmOperatorType *ot);

@ -121,7 +121,7 @@ void ED_operatortypes_armature(void)
WM_operatortype_append(ARMATURE_OT_parent_clear); WM_operatortype_append(ARMATURE_OT_parent_clear);
WM_operatortype_append(ARMATURE_OT_select_all_toggle); WM_operatortype_append(ARMATURE_OT_select_all_toggle);
WM_operatortype_append(ARMATURE_OT_select_invert); WM_operatortype_append(ARMATURE_OT_select_inverse);
WM_operatortype_append(ARMATURE_OT_select_hierarchy); WM_operatortype_append(ARMATURE_OT_select_hierarchy);
WM_operatortype_append(ARMATURE_OT_select_linked); WM_operatortype_append(ARMATURE_OT_select_linked);
@ -148,11 +148,12 @@ void ED_operatortypes_armature(void)
WM_operatortype_append(POSE_OT_scale_clear); WM_operatortype_append(POSE_OT_scale_clear);
WM_operatortype_append(POSE_OT_select_all_toggle); WM_operatortype_append(POSE_OT_select_all_toggle);
WM_operatortype_append(POSE_OT_select_invert); WM_operatortype_append(POSE_OT_select_inverse);
WM_operatortype_append(POSE_OT_select_parent); WM_operatortype_append(POSE_OT_select_parent);
WM_operatortype_append(POSE_OT_select_hierarchy); WM_operatortype_append(POSE_OT_select_hierarchy);
WM_operatortype_append(POSE_OT_select_linked); WM_operatortype_append(POSE_OT_select_linked);
WM_operatortype_append(POSE_OT_select_constraint_target);
/* POSELIB */ /* POSELIB */
WM_operatortype_append(POSELIB_OT_browse_interactive); WM_operatortype_append(POSELIB_OT_browse_interactive);
@ -188,20 +189,18 @@ void ED_keymap_armature(wmWindowManager *wm)
WM_keymap_add_item(keymap, "ARMATURE_OT_parent_clear", PKEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "ARMATURE_OT_parent_clear", PKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "ARMATURE_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "ARMATURE_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "ARMATURE_OT_select_invert", IKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "ARMATURE_OT_select_inverse", IKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "ARMATURE_OT_test", TKEY, KM_PRESS, 0, 0); // XXX temp test for context iterators... to be removed WM_keymap_add_item(keymap, "ARMATURE_OT_test", TKEY, KM_PRESS, 0, 0); // XXX temp test for context iterators... to be removed
kmi= WM_keymap_add_item(keymap, "ARMATURE_OT_select_hierarchy", LEFTBRACKETKEY, KM_PRESS, 0, 0); kmi= WM_keymap_add_item(keymap, "ARMATURE_OT_select_hierarchy", LEFTBRACKETKEY, KM_PRESS, 0, 0);
RNA_enum_set(kmi->ptr, "direction", BONE_SELECT_PARENT); RNA_enum_set(kmi->ptr, "direction", BONE_SELECT_PARENT);
RNA_boolean_set(kmi->ptr, "extend", 0);
kmi= WM_keymap_add_item(keymap, "ARMATURE_OT_select_hierarchy", LEFTBRACKETKEY, KM_PRESS, KM_SHIFT, 0); kmi= WM_keymap_add_item(keymap, "ARMATURE_OT_select_hierarchy", LEFTBRACKETKEY, KM_PRESS, KM_SHIFT, 0);
RNA_enum_set(kmi->ptr, "direction", BONE_SELECT_PARENT); RNA_enum_set(kmi->ptr, "direction", BONE_SELECT_PARENT);
RNA_boolean_set(kmi->ptr, "extend", 1); RNA_boolean_set(kmi->ptr, "extend", 1);
kmi= WM_keymap_add_item(keymap, "ARMATURE_OT_select_hierarchy", RIGHTBRACKETKEY, KM_PRESS, 0, 0); kmi= WM_keymap_add_item(keymap, "ARMATURE_OT_select_hierarchy", RIGHTBRACKETKEY, KM_PRESS, 0, 0);
RNA_enum_set(kmi->ptr, "direction", BONE_SELECT_CHILD); RNA_enum_set(kmi->ptr, "direction", BONE_SELECT_CHILD);
RNA_boolean_set(kmi->ptr, "extend", 0);
kmi= WM_keymap_add_item(keymap, "ARMATURE_OT_select_hierarchy", RIGHTBRACKETKEY, KM_PRESS, KM_SHIFT, 0); kmi= WM_keymap_add_item(keymap, "ARMATURE_OT_select_hierarchy", RIGHTBRACKETKEY, KM_PRESS, KM_SHIFT, 0);
RNA_enum_set(kmi->ptr, "direction", BONE_SELECT_CHILD); RNA_enum_set(kmi->ptr, "direction", BONE_SELECT_CHILD);
RNA_boolean_set(kmi->ptr, "extend", 1); RNA_boolean_set(kmi->ptr, "extend", 1);
@ -234,20 +233,18 @@ void ED_keymap_armature(wmWindowManager *wm)
WM_keymap_add_item(keymap, "POSE_OT_scale_clear", SKEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "POSE_OT_scale_clear", SKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "POSE_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "POSE_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "POSE_OT_select_invert", IKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "POSE_OT_select_inverse", IKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "POSE_OT_select_parent", PKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "POSE_OT_select_parent", PKEY, KM_PRESS, KM_SHIFT, 0);
kmi= WM_keymap_add_item(keymap, "POSE_OT_select_hierarchy", LEFTBRACKETKEY, KM_PRESS, 0, 0); kmi= WM_keymap_add_item(keymap, "POSE_OT_select_hierarchy", LEFTBRACKETKEY, KM_PRESS, 0, 0);
RNA_enum_set(kmi->ptr, "direction", BONE_SELECT_PARENT); RNA_enum_set(kmi->ptr, "direction", BONE_SELECT_PARENT);
RNA_boolean_set(kmi->ptr, "extend", 0);
kmi= WM_keymap_add_item(keymap, "POSE_OT_select_hierarchy", LEFTBRACKETKEY, KM_PRESS, KM_SHIFT, 0); kmi= WM_keymap_add_item(keymap, "POSE_OT_select_hierarchy", LEFTBRACKETKEY, KM_PRESS, KM_SHIFT, 0);
RNA_enum_set(kmi->ptr, "direction", BONE_SELECT_PARENT); RNA_enum_set(kmi->ptr, "direction", BONE_SELECT_PARENT);
RNA_boolean_set(kmi->ptr, "extend", 1); RNA_boolean_set(kmi->ptr, "extend", 1);
kmi= WM_keymap_add_item(keymap, "POSE_OT_select_hierarchy", RIGHTBRACKETKEY, KM_PRESS, 0, 0); kmi= WM_keymap_add_item(keymap, "POSE_OT_select_hierarchy", RIGHTBRACKETKEY, KM_PRESS, 0, 0);
RNA_enum_set(kmi->ptr, "direction", BONE_SELECT_CHILD); RNA_enum_set(kmi->ptr, "direction", BONE_SELECT_CHILD);
RNA_boolean_set(kmi->ptr, "extend", 0);
kmi= WM_keymap_add_item(keymap, "POSE_OT_select_hierarchy", RIGHTBRACKETKEY, KM_PRESS, KM_SHIFT, 0); kmi= WM_keymap_add_item(keymap, "POSE_OT_select_hierarchy", RIGHTBRACKETKEY, KM_PRESS, KM_SHIFT, 0);
RNA_enum_set(kmi->ptr, "direction", BONE_SELECT_CHILD); RNA_enum_set(kmi->ptr, "direction", BONE_SELECT_CHILD);
RNA_boolean_set(kmi->ptr, "extend", 1); RNA_boolean_set(kmi->ptr, "extend", 1);

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