Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/editors/animation/anim_draw.c78
-rw-r--r--source/blender/editors/animation/anim_filter.c88
-rw-r--r--source/blender/editors/animation/anim_keyframes_draw.c701
-rw-r--r--source/blender/editors/include/ED_anim_api.h76
-rw-r--r--source/blender/editors/include/ED_keyframes_draw.h99
-rw-r--r--source/blender/editors/include/UI_resources.h7
-rw-r--r--source/blender/editors/interface/resources.c9
-rw-r--r--source/blender/editors/space_action/action_draw.c1321
-rw-r--r--source/blender/editors/space_action/action_intern.h9
-rw-r--r--source/blender/editors/space_action/space_action.c20
-rw-r--r--source/blender/editors/space_view3d/drawarmature.c26
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h5
12 files changed, 2361 insertions, 78 deletions
diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c
index 5485ed9e61e..aea4b0bbf1d 100644
--- a/source/blender/editors/animation/anim_draw.c
+++ b/source/blender/editors/animation/anim_draw.c
@@ -42,8 +42,10 @@
#include "BLI_blenlib.h"
+#include "BKE_action.h"
#include "BKE_context.h"
#include "BKE_global.h"
+#include "BKE_ipo.h"
#include "BKE_object.h"
#include "BKE_screen.h"
#include "BKE_utildefines.h"
@@ -177,3 +179,79 @@ void ANIM_draw_previewrange (const bContext *C, View2D *v2d)
}
/* *************************************************** */
+/* KEYFRAME DRAWING UTILITIES */
+
+/* Obtain the Object providing NLA-scaling for the given channel (if applicable) */
+Object *ANIM_nla_mapping_get(bAnimContext *ac, bAnimListElem *ale)
+{
+ /* sanity checks */
+ if (ac == NULL)
+ return NULL;
+
+ /* handling depends on the type of animation-context we've got */
+ if (ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_IPO)) {
+ /* Action Editor (action mode) or Ipo Editor (ipo mode):
+ * Only use if editor is not pinned, and active object has action
+ */
+ if (ac->obact && ac->obact->action) {
+ /* Action Editor */
+ if (ac->datatype == ANIMCONT_ACTION) {
+ SpaceAction *saction= (SpaceAction *)ac->sa->spacedata.first;
+
+ if (saction->pin == 0)
+ return ac->obact;
+ }
+ /* IPO Editor */
+ else if (ac->datatype == ANIMCONT_IPO) {
+ SpaceIpo *sipo= (SpaceIpo *)ac->sa->spacedata.first;
+
+ if (sipo->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;
+ }
+ }
+
+ /* no appropriate object found */
+ return NULL;
+}
+
+/* Set/clear temporary mapping of coordinates from 'local-action' time to 'global-nla-scaled' time
+ * - the old mapping is stored in a static var, but that shouldn't be too bad as UI drawing
+ * (where this is called) is single-threaded anyway
+ */
+// XXX was called: map_active_strip()
+void ANIM_nla_mapping_draw(gla2DDrawInfo *di, Object *ob, short restore)
+{
+ static rctf stored;
+
+ if (restore) {
+ /* restore un-mapped coordinates */
+ gla2DSetMap(di, &stored);
+ }
+ else {
+ /* set mapped coordinates */
+ rctf map;
+
+ gla2DGetMap(di, &stored);
+ map= stored;
+
+ map.xmin= get_action_frame(ob, map.xmin);
+ map.xmax= get_action_frame(ob, map.xmax);
+
+ if (map.xmin == map.xmax) map.xmax += 1.0f;
+ gla2DSetMap(di, &map);
+ }
+}
+
+/* *************************************************** */
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index 19dafc439dc..d4b9f9fff93 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -140,86 +140,110 @@ Key *actedit_get_shapekeys (const bContext *C, SpaceAction *saction)
}
/* Get data being edited in Action Editor (depending on current 'mode') */
-static void *actedit_get_context (const bContext *C, SpaceAction *saction, short *datatype)
+static short actedit_get_context (const bContext *C, bAnimContext *ac, SpaceAction *saction)
{
- Scene *scene= CTX_data_scene(C);
-
/* sync settings with current view status, then return appropriate data */
switch (saction->mode) {
case SACTCONT_ACTION: /* 'Action Editor' */
/* if not pinned, sync with active object */
if (saction->pin == 0) {
- if (OBACT)
- saction->action = OBACT->action;
+ if (ac->obact)
+ saction->action = ac->obact->action;
else
saction->action= NULL;
}
-
- *datatype= ANIMCONT_ACTION;
- return saction->action;
+
+ ac->datatype= ANIMCONT_ACTION;
+ ac->data= saction->action;
+
+ ac->mode= saction->mode;
+ return 1;
case SACTCONT_SHAPEKEY: /* 'ShapeKey Editor' */
- *datatype= ANIMCONT_SHAPEKEY;
- return actedit_get_shapekeys(C, saction);
+ ac->datatype= ANIMCONT_SHAPEKEY;
+ ac->data= actedit_get_shapekeys(C, saction);
+
+ ac->mode= saction->mode;
+ return 1;
case SACTCONT_GPENCIL: /* Grease Pencil */ // XXX review how this mode is handled...
- *datatype=ANIMCONT_GPENCIL;
- return CTX_wm_screen(C); // FIXME: add that dopesheet type thing here!
- break;
+ ac->datatype=ANIMCONT_GPENCIL;
+ ac->data= CTX_wm_screen(C); // FIXME: add that dopesheet type thing here!
+
+ ac->mode= saction->mode;
+ return 1;
case SACTCONT_DOPESHEET: /* DopeSheet */
/* update scene-pointer (no need to check for pinning yet, as not implemented) */
- saction->ads.source= (ID *)scene;
+ saction->ads.source= (ID *)ac->scene;
- *datatype= ANIMCONT_DOPESHEET;
- return &saction->ads;
+ ac->datatype= ANIMCONT_DOPESHEET;
+ ac->data= &saction->ads;
+
+ ac->mode= saction->mode;
+ return 1;
default: /* unhandled yet */
- *datatype= ANIMCONT_NONE;
- return NULL;
+ ac->datatype= ANIMCONT_NONE;
+ ac->data= NULL;
+
+ ac->mode= -1;
+ return 0;
}
}
/* ----------- Private Stuff - IPO Editor ------------- */
/* Get data being edited in IPO Editor (depending on current 'mode') */
-static void *ipoedit_get_context (const bContext *C, SpaceIpo *sipo, short *datatype)
+static short ipoedit_get_context (const bContext *C, bAnimContext *ac, SpaceIpo *sipo)
{
// XXX FIXME...
- return NULL;
+ return 0;
}
/* ----------- Public API --------------- */
-/* Obtain current anim-data context from Blender Context info */
-void *ANIM_animdata_get_context (const bContext *C, short *datatype)
+/* Obtain current anim-data context from Blender Context info
+ * - AnimContext to write to is provided as pointer to var on stack so that we don't have
+ * allocation/freeing costs (which are not that avoidable with channels).
+ * -
+ */
+short ANIM_animdata_get_context (const bContext *C, bAnimContext *ac)
{
- ScrArea *sa= CTX_wm_area(C);
+ ScrArea *sa= CTX_wm_area(C); // XXX it is assumed that this will always be valid
+ ARegion *ar= CTX_wm_region(C);
+ Scene *scene= CTX_data_scene(C);
+
+ /* clear old context info */
+ if (ac == NULL) return 0;
+ memset(ac, 0, sizeof(bAnimContext));
- /* set datatype to 'None' for convenience */
- if (datatype == NULL) return NULL;
- *datatype= ANIMCONT_NONE;
- if (sa == NULL) return NULL; /* highly unlikely to happen, but still! */
+ /* set default context settings */
+ ac->scene= scene;
+ ac->obact= (scene && scene->basact)? scene->basact->object : NULL;
+ ac->sa= sa;
+ ac->spacetype= sa->spacetype;
+ ac->regiontype= ar->regiontype;
/* context depends on editor we are currently in */
switch (sa->spacetype) {
case SPACE_ACTION:
{
SpaceAction *saction= (SpaceAction *)CTX_wm_space_data(C);
- return actedit_get_context(C, saction, datatype);
+ return actedit_get_context(C, ac, saction);
}
break;
case SPACE_IPO:
{
SpaceIpo *sipo= (SpaceIpo *)CTX_wm_space_data(C);
- return ipoedit_get_context(C, sipo, datatype);
+ return ipoedit_get_context(C, ac, sipo);
}
break;
}
/* nothing appropriate */
- return NULL;
+ return 0;
}
/* ************************************************************ */
@@ -1208,6 +1232,10 @@ void ANIM_animdata_filter (ListBase *anim_data, int filter_mode, void *data, sho
case ANIMCONT_DOPESHEET:
animdata_filter_dopesheet(anim_data, data, filter_mode);
break;
+
+ case ANIMCONT_IPO:
+ // FIXME: this will be used for showing a single IPO-block (not too useful from animator perspective though!)
+ break;
}
/* remove any weedy entries */
diff --git a/source/blender/editors/animation/anim_keyframes_draw.c b/source/blender/editors/animation/anim_keyframes_draw.c
new file mode 100644
index 00000000000..2f8d1be784e
--- /dev/null
+++ b/source/blender/editors/animation/anim_keyframes_draw.c
@@ -0,0 +1,701 @@
+/**
+ * $Id: drawaction.c 17746 2008-12-08 11:19:44Z 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) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/* System includes ----------------------------------------------------- */
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <float.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+/* Types --------------------------------------------------------------- */
+
+#include "DNA_listBase.h"
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_space_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_key_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_material_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BKE_action.h"
+#include "BKE_depsgraph.h"
+#include "BKE_ipo.h"
+#include "BKE_key.h"
+#include "BKE_material.h"
+#include "BKE_object.h"
+#include "BKE_global.h" // XXX remove me!
+#include "BKE_context.h"
+#include "BKE_utildefines.h"
+
+/* Everything from source (BIF, BDR, BSE) ------------------------------ */
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "UI_interface.h"
+#include "UI_interface_icons.h"
+#include "UI_resources.h"
+#include "UI_text.h"
+#include "UI_view2d.h"
+
+#include "ED_anim_api.h"
+#include "ED_keyframing.h"
+#include "ED_keyframes_draw.h"
+#include "ED_screen.h"
+#include "ED_space_api.h"
+
+
+#if 0 // XXX old includes for reference only
+ #include "BIF_editaction.h"
+ #include "BIF_editkey.h"
+ #include "BIF_editnla.h"
+ #include "BIF_drawgpencil.h"
+ #include "BIF_keyframing.h"
+ #include "BIF_language.h"
+ #include "BIF_space.h"
+
+ #include "BDR_editcurve.h"
+ #include "BDR_gpencil.h"
+
+ #include "BSE_drawnla.h"
+ #include "BSE_drawipo.h"
+ #include "BSE_drawview.h"
+ #include "BSE_editaction_types.h"
+ #include "BSE_editipo.h"
+ #include "BSE_headerbuttons.h"
+ #include "BSE_time.h"
+ #include "BSE_view.h"
+#endif // XXX old defines for reference only
+
+/* *************************** Keyframe Drawing *************************** */
+
+static void add_bezt_to_keycolumnslist(ListBase *keys, BezTriple *bezt)
+{
+ /* The equivilant of add_to_cfra_elem except this version
+ * makes ActKeyColumns - one of the two datatypes required
+ * for action editor drawing.
+ */
+ ActKeyColumn *ak, *akn;
+
+ if (ELEM(NULL, keys, bezt)) return;
+
+ /* try to any existing key to replace, or where to insert after */
+ for (ak= keys->last; ak; ak= ak->prev) {
+ /* do because of double keys */
+ if (ak->cfra == bezt->vec[1][0]) {
+ /* set selection status and 'touched' status */
+ if (BEZSELECTED(bezt)) ak->sel = SELECT;
+ ak->modified += 1;
+
+ return;
+ }
+ else if (ak->cfra < bezt->vec[1][0]) break;
+ }
+
+ /* add new block */
+ akn= MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumn");
+ if (ak) BLI_insertlinkafter(keys, ak, akn);
+ else BLI_addtail(keys, akn);
+
+ akn->cfra= bezt->vec[1][0];
+ akn->modified += 1;
+
+ // TODO: handle type = bezt->h1 or bezt->h2
+ akn->handle_type= 0;
+
+ if (BEZSELECTED(bezt))
+ akn->sel = SELECT;
+ else
+ akn->sel = 0;
+}
+
+static void add_bezt_to_keyblockslist(ListBase *blocks, IpoCurve *icu, int index)
+{
+ /* The equivilant of add_to_cfra_elem except this version
+ * makes ActKeyBlocks - one of the two datatypes required
+ * for action editor drawing.
+ */
+ ActKeyBlock *ab, *abn;
+ BezTriple *beztn=NULL, *prev=NULL;
+ BezTriple *bezt;
+ int v;
+
+ /* get beztriples */
+ beztn= (icu->bezt + index);
+
+ /* we need to go through all beztriples, as they may not be in order (i.e. during transform) */
+ for (v=0, bezt=icu->bezt; v<icu->totvert; v++, bezt++) {
+ /* skip if beztriple is current */
+ if (v != index) {
+ /* check if beztriple is immediately before */
+ if (beztn->vec[1][0] > bezt->vec[1][0]) {
+ /* check if closer than previous was */
+ if (prev) {
+ if (prev->vec[1][0] < bezt->vec[1][0])
+ prev= bezt;
+ }
+ else {
+ prev= bezt;
+ }
+ }
+ }
+ }
+
+ /* check if block needed - same value(s)?
+ * -> firstly, handles must have same central value as each other
+ * -> secondly, handles which control that section of the curve must be constant
+ */
+ if ((!prev) || (!beztn)) return;
+ if (IS_EQ(beztn->vec[1][1], prev->vec[1][1])==0) return;
+ if (IS_EQ(beztn->vec[1][1], beztn->vec[0][1])==0) return;
+ if (IS_EQ(prev->vec[1][1], prev->vec[2][1])==0) return;
+
+ /* try to find a keyblock that starts on the previous beztriple
+ * Note: we can't search from end to try to optimise this as it causes errors there's
+ * an A ___ B |---| B situation
+ */
+ // FIXME: here there is a bug where we are trying to get the summary for the following channels
+ // A|--------------|A ______________ B|--------------|B
+ // A|------------------------------------------------|A
+ // A|----|A|---|A|-----------------------------------|A
+ for (ab= blocks->first; ab; ab= ab->next) {
+ /* check if alter existing block or add new block */
+ if (ab->start == prev->vec[1][0]) {
+ /* set selection status and 'touched' status */
+ if (BEZSELECTED(beztn)) ab->sel = SELECT;
+ ab->modified += 1;
+
+ return;
+ }
+ else if (ab->start < prev->vec[1][0]) break;
+ }
+
+ /* add new block */
+ abn= MEM_callocN(sizeof(ActKeyBlock), "ActKeyBlock");
+ if (ab) BLI_insertlinkbefore(blocks, ab, abn);
+ else BLI_addtail(blocks, abn);
+
+ abn->start= prev->vec[1][0];
+ abn->end= beztn->vec[1][0];
+ abn->val= beztn->vec[1][1];
+
+ if (BEZSELECTED(prev) || BEZSELECTED(beztn))
+ abn->sel = SELECT;
+ else
+ abn->sel = 0;
+ abn->modified = 1;
+}
+
+/* helper function - find actkeycolumn that occurs on cframe */
+static ActKeyColumn *cfra_find_actkeycolumn (ListBase *keys, float cframe)
+{
+ ActKeyColumn *ak, *ak2;
+
+ if (keys==NULL)
+ return NULL;
+
+ /* search from both ends at the same time, and stop if we find match or if both ends meet */
+ for (ak=keys->first, ak2=keys->last; ak && ak2; ak=ak->next, ak2=ak2->prev) {
+ /* return whichever end encounters the frame */
+ if (ak->cfra == cframe)
+ return ak;
+ if (ak2->cfra == cframe)
+ return ak2;
+
+ /* no matches on either end, so return NULL */
+ if (ak == ak2)
+ return NULL;
+ }
+
+ return NULL;
+}
+
+#if 0 // disabled, as some intel cards have problems with this
+/* Draw a simple diamond shape with a filled in center (in screen space) */
+static void draw_key_but(int x, int y, short w, short h, int sel)
+{
+ int xmin= x, ymin= y;
+ int xmax= x+w-1, ymax= y+h-1;
+ int xc= (xmin+xmax)/2, yc= (ymin+ymax)/2;
+
+ /* interior - hardcoded colors (for selected and unselected only) */
+ if (sel) glColor3ub(0xF1, 0xCA, 0x13);
+ else glColor3ub(0xE9, 0xE9, 0xE9);
+
+ glBegin(GL_QUADS);
+ glVertex2i(xc, ymin);
+ glVertex2i(xmax, yc);
+ glVertex2i(xc, ymax);
+ glVertex2i(xmin, yc);
+ glEnd();
+
+
+ /* outline */
+ glColor3ub(0, 0, 0);
+
+ glBegin(GL_LINE_LOOP);
+ glVertex2i(xc, ymin);
+ glVertex2i(xmax, yc);
+ glVertex2i(xc, ymax);
+ glVertex2i(xmin, yc);
+ glEnd();
+}
+#endif
+
+static void draw_keylist(gla2DDrawInfo *di, ListBase *keys, ListBase *blocks, float ypos)
+{
+ ActKeyColumn *ak;
+ ActKeyBlock *ab;
+
+ glEnable(GL_BLEND);
+
+ /* draw keyblocks */
+ if (blocks) {
+ for (ab= blocks->first; ab; ab= ab->next) {
+ short startCurves, endCurves, totCurves;
+
+ /* find out how many curves occur at each keyframe */
+ ak= cfra_find_actkeycolumn(keys, ab->start);
+ startCurves = (ak)? ak->totcurve: 0;
+
+ ak= cfra_find_actkeycolumn(keys, ab->end);
+ endCurves = (ak)? ak->totcurve: 0;
+
+ /* only draw keyblock if it appears in at all of the keyframes at lowest end */
+ if (!startCurves && !endCurves)
+ continue;
+ else
+ totCurves = (startCurves>endCurves)? endCurves: startCurves;
+
+ if (ab->totcurve >= totCurves) {
+ int sc_xa, sc_xb, sc_y;
+
+ /* get co-ordinates of block */
+ // XXX only use x-coordinates... y are dummy ones!
+ gla2DDrawTranslatePt(di, ab->start, ypos, &sc_xa, &sc_y);
+ gla2DDrawTranslatePt(di, ab->end, ypos, &sc_xb, &sc_y);
+
+ /* draw block */
+ if (ab->sel)
+ UI_ThemeColor4(TH_STRIP_SELECT);
+ else
+ UI_ThemeColor4(TH_STRIP);
+ glRectf((float)sc_xa, (float)ypos-3, (float)sc_xb, (float)ypos+5);
+ }
+ }
+ }
+
+ /* draw keys */
+ if (keys) {
+ for (ak= keys->first; ak; ak= ak->next) {
+ int sc_x, sc_y;
+
+ /* get co-ordinate to draw at */
+ // XXX only use x-coordinates... y are dummy ones!
+ gla2DDrawTranslatePt(di, ak->cfra, ypos, &sc_x, &sc_y);
+
+ /* draw using icons - old way which is slower but more proven */
+ if (ak->sel & SELECT)UI_icon_draw_aspect((float)sc_x-7, (float)ypos-6, ICON_SPACE2, 1.0f);
+ else UI_icon_draw_aspect((float)sc_x-7, (float)ypos-6, ICON_SPACE3, 1.0f);
+
+ /* 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));
+ }
+ }
+
+ glDisable(GL_BLEND);
+}
+
+void draw_object_channel(gla2DDrawInfo *di, ActKeysInc *aki, Object *ob, float ypos)
+{
+ ListBase keys = {0, 0};
+ ListBase blocks = {0, 0};
+
+ ob_to_keylist(ob, &keys, &blocks, aki);
+ draw_keylist(di, &keys, &blocks, ypos);
+
+ BLI_freelistN(&keys);
+ BLI_freelistN(&blocks);
+}
+
+void draw_ipo_channel(gla2DDrawInfo *di, ActKeysInc *aki, Ipo *ipo, float ypos)
+{
+ ListBase keys = {0, 0};
+ ListBase blocks = {0, 0};
+
+ ipo_to_keylist(ipo, &keys, &blocks, aki);
+ draw_keylist(di, &keys, &blocks, ypos);
+
+ BLI_freelistN(&keys);
+ BLI_freelistN(&blocks);
+}
+
+void draw_icu_channel(gla2DDrawInfo *di, ActKeysInc *aki, IpoCurve *icu, float ypos)
+{
+ ListBase keys = {0, 0};
+ ListBase blocks = {0, 0};
+
+ icu_to_keylist(icu, &keys, &blocks, aki);
+ draw_keylist(di, &keys, &blocks, ypos);
+
+ BLI_freelistN(&keys);
+ BLI_freelistN(&blocks);
+}
+
+void draw_agroup_channel(gla2DDrawInfo *di, ActKeysInc *aki, bActionGroup *agrp, float ypos)
+{
+ ListBase keys = {0, 0};
+ ListBase blocks = {0, 0};
+
+ agroup_to_keylist(agrp, &keys, &blocks, aki);
+ draw_keylist(di, &keys, &blocks, ypos);
+
+ BLI_freelistN(&keys);
+ BLI_freelistN(&blocks);
+}
+
+void draw_action_channel(gla2DDrawInfo *di, ActKeysInc *aki, bAction *act, float ypos)
+{
+ ListBase keys = {0, 0};
+ ListBase blocks = {0, 0};
+
+ action_to_keylist(act, &keys, &blocks, aki);
+ draw_keylist(di, &keys, &blocks, ypos);
+
+ BLI_freelistN(&keys);
+ BLI_freelistN(&blocks);
+}
+
+void draw_gpl_channel(gla2DDrawInfo *di, ActKeysInc *aki, bGPDlayer *gpl, float ypos)
+{
+ ListBase keys = {0, 0};
+
+ gpl_to_keylist(gpl, &keys, NULL, aki);
+ draw_keylist(di, &keys, NULL, ypos);
+ BLI_freelistN(&keys);
+}
+
+/* --------------- Conversion: data -> keyframe list ------------------ */
+
+void ob_to_keylist(Object *ob, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
+{
+ bConstraintChannel *conchan;
+ Key *key= ob_get_key(ob);
+
+ if (ob) {
+ bDopeSheet *ads= (aki)? (aki->ads) : NULL;
+ int filterflag;
+
+ /* get filterflag */
+ if (ads)
+ filterflag= ads->filterflag;
+ else if ((aki) && (aki->actmode == -1)) /* only set like this by NLA */
+ filterflag= ADS_FILTER_NLADUMMY;
+ else
+ filterflag= 0;
+
+ /* Add object keyframes */
+ if ((ob->ipo) && !(filterflag & ADS_FILTER_NOIPOS))
+ ipo_to_keylist(ob->ipo, keys, blocks, aki);
+
+ /* Add action keyframes */
+ if ((ob->action) && !(filterflag & ADS_FILTER_NOACTS))
+ action_nlascaled_to_keylist(ob, ob->action, keys, blocks, aki);
+
+ /* Add shapekey keyframes (only if dopesheet allows, if it is available) */
+ if ((key && key->ipo) && !(filterflag & ADS_FILTER_NOSHAPEKEYS))
+ ipo_to_keylist(key->ipo, keys, blocks, aki);
+
+ /* 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) && !(ads->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) && !(ads->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) && !(ads->filterflag & ADS_FILTER_NOCUR))
+ ipo_to_keylist(cu->ipo, keys, blocks, aki);
+ }
+ break;
+ }
+
+ /* Add constraint keyframes */
+ if (!(filterflag & ADS_FILTER_NOCONSTRAINTS)) {
+ for (conchan=ob->constraintChannels.first; conchan; conchan=conchan->next) {
+ if (conchan->ipo)
+ ipo_to_keylist(conchan->ipo, keys, blocks, aki);
+ }
+ }
+ }
+}
+
+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 */
+ if (IS_EQ(aki->start, 0) && IS_EQ(aki->end, 0))
+ return 1;
+
+ /* if nla-scaling is in effect, apply appropriate scaling adjustments */
+ 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);
+ }
+}
+
+void icu_to_keylist(IpoCurve *icu, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
+{
+ BezTriple *bezt;
+ ActKeyColumn *ak, *ak2;
+ ActKeyBlock *ab, *ab2;
+ int v;
+
+ if (icu && icu->totvert) {
+ /* loop through beztriples, making ActKeys and ActKeyBlocks */
+ bezt= icu->bezt;
+
+ for (v=0; v<icu->totvert; v++, bezt++) {
+ /* only if keyframe is in range (optimisation) */
+ if (bezt_in_aki_range(aki, bezt)) {
+ add_bezt_to_keycolumnslist(keys, bezt);
+ if (blocks) add_bezt_to_keyblockslist(blocks, icu, v);
+ }
+ }
+
+ /* update the number of curves that elements have appeared in */
+ if (keys) {
+ for (ak=keys->first, ak2=keys->last; ak && ak2; ak=ak->next, ak2=ak2->prev) {
+ if (ak->modified) {
+ ak->modified = 0;
+ ak->totcurve += 1;
+ }
+
+ if (ak == ak2)
+ break;
+
+ if (ak2->modified) {
+ ak2->modified = 0;
+ ak2->totcurve += 1;
+ }
+ }
+ }
+ if (blocks) {
+ for (ab=blocks->first, ab2=blocks->last; ab && ab2; ab=ab->next, ab2=ab2->prev) {
+ if (ab->modified) {
+ ab->modified = 0;
+ ab->totcurve += 1;
+ }
+
+ if (ab == ab2)
+ break;
+
+ if (ab2->modified) {
+ ab2->modified = 0;
+ ab2->totcurve += 1;
+ }
+ }
+ }
+ }
+}
+
+void ipo_to_keylist(Ipo *ipo, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
+{
+ IpoCurve *icu;
+
+ if (ipo) {
+ for (icu= ipo->curve.first; icu; icu= icu->next)
+ icu_to_keylist(icu, keys, blocks, aki);
+ }
+}
+
+void agroup_to_keylist(bActionGroup *agrp, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
+{
+ bActionChannel *achan;
+ bConstraintChannel *conchan;
+
+ if (agrp) {
+ /* loop through action channels */
+ for (achan= agrp->channels.first; achan && achan->grp==agrp; achan= achan->next) {
+ if (VISIBLE_ACHAN(achan)) {
+ /* firstly, add keys from action channel's ipo block */
+ if (achan->ipo)
+ ipo_to_keylist(achan->ipo, keys, blocks, aki);
+
+ /* then, add keys from constraint channels */
+ for (conchan= achan->constraintChannels.first; conchan; conchan= conchan->next) {
+ if (conchan->ipo)
+ ipo_to_keylist(conchan->ipo, keys, blocks, aki);
+ }
+ }
+ }
+ }
+}
+
+void action_to_keylist(bAction *act, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
+{
+ bActionChannel *achan;
+ bConstraintChannel *conchan;
+
+ if (act) {
+ /* loop through action channels */
+ for (achan= act->chanbase.first; achan; achan= achan->next) {
+ /* firstly, add keys from action channel's ipo block */
+ if (achan->ipo)
+ ipo_to_keylist(achan->ipo, keys, blocks, aki);
+
+ /* then, add keys from constraint channels */
+ for (conchan= achan->constraintChannels.first; conchan; conchan= conchan->next) {
+ if (conchan->ipo)
+ ipo_to_keylist(conchan->ipo, keys, blocks, aki);
+ }
+ }
+ }
+}
+
+void action_nlascaled_to_keylist(Object *ob, bAction *act, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
+{
+ bActionChannel *achan;
+ bConstraintChannel *conchan;
+ Object *oldob= NULL;
+
+ /* although apply and clearing NLA-scaling pre-post creating keylist does impact on performance,
+ * 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 action channels */
+ for (achan= act->chanbase.first; achan; achan= achan->next) {
+ /* firstly, add keys from action channel's ipo block
+ * - scaling correction only does times for center-points, so should be faster
+ */
+ if (achan->ipo) {
+ //actstrip_map_ipo_keys(ob, achan->ipo, 0, 1); // XXX
+ ipo_to_keylist(achan->ipo, keys, blocks, aki);
+ //actstrip_map_ipo_keys(ob, achan->ipo, 1, 1); // XXX
+ }
+
+ /* then, add keys from constraint channels
+ * - scaling correction only does times for center-points, so should be faster
+ */
+ for (conchan= achan->constraintChannels.first; conchan; conchan= conchan->next) {
+ if (conchan->ipo) {
+ //actstrip_map_ipo_keys(ob, conchan->ipo, 0, 1); // XXX
+ ipo_to_keylist(conchan->ipo, keys, blocks, aki);
+ //actstrip_map_ipo_keys(ob, conchan->ipo, 1, 1); // XXX
+ }
+ }
+ }
+
+ /* 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;
+ ActKeyColumn *ak;
+
+ if (gpl && keys) {
+ /* loop over frames, converting directly to 'keyframes' (should be in order too) */
+ for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
+ ak= MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumn");
+ BLI_addtail(keys, ak);
+
+ ak->cfra= (float)gpf->framenum;
+ ak->modified = 1;
+ ak->handle_type= 0;
+
+ if (gpf->flag & GP_FRAME_SELECT)
+ ak->sel = SELECT;
+ else
+ ak->sel = 0;
+ }
+ }
+}
+
diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h
index 61065cd970d..f6996bbb07e 100644
--- a/source/blender/editors/include/ED_anim_api.h
+++ b/source/blender/editors/include/ED_anim_api.h
@@ -33,12 +33,43 @@ struct ID;
struct ListBase;
struct bContext;
struct View2D;
+struct gla2DDrawInfo;
+struct Object;
struct bActionGroup;
/* ************************************************ */
/* ANIMATION CHANNEL FILTERING */
-/* --------------- Data Types -------------------- */
+/* --------------- Context --------------------- */
+
+/* This struct defines a structure used for animation-specific
+ * 'context' information
+ */
+typedef struct bAnimContext {
+ void *data; /* data to be filtered for use in animation editor */
+ short datatype; /* type of data eAnimCont_Types */
+
+ short mode; /* editor->mode */
+ short spacetype; /* sa->spacetype */
+ short regiontype; /* active region -> type (channels or main) */
+ struct ScrArea *sa; /* editor */
+
+ struct Scene *scene; /* active scene */
+ struct Object *obact; /* active object */
+} bAnimContext;
+
+/* Main Data container types */
+// XXX was ACTCONT_*
+typedef enum eAnimCont_Types {
+ ANIMCONT_NONE = 0, /* invalid or no data */
+ ANIMCONT_ACTION, /* action (bAction) */
+ ANIMCONT_SHAPEKEY, /* shapekey (Key) */
+ ANIMCONT_GPENCIL, /* grease pencil (screen) */
+ ANIMCONT_DOPESHEET, /* dopesheet (bDopesheet) */
+ ANIMCONT_IPO, /* single IPO (Ipo) */
+} eAnimCont_Types;
+
+/* --------------- Channels -------------------- */
/* This struct defines a structure used for quick and uniform access for
* channels of animation data
@@ -109,15 +140,7 @@ typedef enum eAnim_KeyType {
ALE_GROUP, /* Action Group summary */
} eAnim_KeyType;
-/* Main Data container types */
-// XXX was ACTCONT_*
-typedef enum eAnimCont_Types {
- ANIMCONT_NONE = 0, /* invalid or no data */
- ANIMCONT_ACTION, /* action (bAction) */
- ANIMCONT_SHAPEKEY, /* shapekey (Key) */
- ANIMCONT_GPENCIL, /* grease pencil (screen) */
- ANIMCONT_DOPESHEET, /* dopesheet (bDopesheet) */
-} eAnimCont_Types;
+/* ----------------- Filtering -------------------- */
/* filtering flags - under what circumstances should a channel be added */
// XXX was ACTFILTER_*
@@ -179,13 +202,28 @@ typedef enum eAnimFilter_Flags {
#define EDITABLE_GPL(gpl) ((gpl->flag & GP_LAYER_LOCKED)==0)
#define SEL_GPL(gpl) ((gpl->flag & GP_LAYER_ACTIVE) || (gpl->flag & GP_LAYER_SELECT))
+/* -------------- Channel Defines -------------- */
+
+/* channel heights */
+#define ACHANNEL_HEIGHT 16
+#define ACHANNEL_HEIGHT_HALF 8
+#define ACHANNEL_SKIP 2
+#define ACHANNEL_STEP (ACHANNEL_HEIGHT + ACHANNEL_SKIP)
+ // FIXME: needs to be renamed...
+#define NAMEWIDTH 190
+
/* ---------------- API -------------------- */
/* Obtain list of filtered Animation channels to operate on */
void ANIM_animdata_filter(struct ListBase *anim_data, int filter_mode, void *data, short datatype);
/* Obtain current anim-data context from Blender Context info */
-void *ANIM_animdata_get_context(const struct bContext *C, short *datatype);
+/** Example usage (example to be removed...):
+ // get editor data
+ if ((ANIM_animdata_get_context(C, &ac) == 0) || (ac.data == NULL))
+ return;
+ */
+short ANIM_animdata_get_context(const struct bContext *C, bAnimContext *ac);
/* ************************************************ */
/* DRAWING API */
@@ -210,12 +248,24 @@ void ANIM_draw_cfra(const bContext *C, struct View2D *v2d, short flag);
/* ------------- Preview Range Drawing -------------- */
-// XXX should preview range get its own file?
-
/* main call to draw preview range curtains */
void ANIM_draw_previewrange(const bContext *C, struct View2D *v2d);
/* ************************************************* */
+/* ASSORTED TOOLS */
+
+/* ------------- NLA-Mapping ----------------------- */
+
+/* Obtain the Object providing NLA-scaling for the given channel if applicable */
+struct Object *ANIM_nla_mapping_get(bAnimContext *ac, bAnimListElem *ale);
+
+/* set/clear temporary mapping of coordinates from 'local-action' time to 'global-nla-scaled' time */
+void ANIM_nla_mapping_draw(struct gla2DDrawInfo *di, struct Object *ob, short restore);
+
+/* ------------- xxx macros ----------------------- */
+#define BEZSELECTED(bezt) ((bezt->f2 & SELECT) || (bezt->f1 & SELECT) || (bezt->f3 & SELECT))
+
+/* ************************************************* */
/* OPERATORS */
void ED_operatortypes_anim(void);
diff --git a/source/blender/editors/include/ED_keyframes_draw.h b/source/blender/editors/include/ED_keyframes_draw.h
new file mode 100644
index 00000000000..a1ddd6b6bed
--- /dev/null
+++ b/source/blender/editors/include/ED_keyframes_draw.h
@@ -0,0 +1,99 @@
+/**
+ * $Id: BDR_drawaction.h 17579 2008-11-26 11:01: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) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef BDR_DRAWACTION_H
+#define BDR_DRAWACTION_H
+
+struct BezTriple;
+struct Ipo;
+struct IpoCurve;
+struct gla2DDrawInfo;
+struct bAction;
+struct bActionGroup;
+struct bActListElem;
+struct Object;
+struct ListBase;
+struct bGPDlayer;
+
+/* ****************************** Base Structs ****************************** */
+
+/* Keyframe Column Struct */
+typedef struct ActKeyColumn {
+ struct ActKeyColumn *next, *prev;
+ short sel, handle_type;
+ float cfra;
+
+ /* only while drawing - used to determine if long-keyframe needs to be drawn */
+ short modified;
+ short totcurve;
+} ActKeyColumn;
+
+/* 'Long Keyframe' Struct */
+typedef struct ActKeyBlock {
+ struct ActKeyBlock *next, *prev;
+ short sel, handle_type;
+ float val;
+ float start, end;
+
+ /* only while drawing - used to determine if block needs to be drawn */
+ short modified;
+ short totcurve;
+} ActKeyBlock;
+
+
+/* Inclusion-Range Limiting Struct (optional) */
+typedef struct ActKeysInc {
+ struct bDopeSheet *ads; /* dopesheet data (for dopesheet mode) */
+ struct Object *ob; /* owner object for NLA-scaling info (if Object channels, is just Object) */
+ short actmode; /* mode of the Action Editor (-1 is for NLA) */
+
+ float start, end; /* frames (global-time) to only consider keys between */ // XXX not used anymore!
+} ActKeysInc;
+
+/* ******************************* Methods ****************************** */
+
+/* Channel Drawing */
+void draw_icu_channel(struct gla2DDrawInfo *di, ActKeysInc *aki, struct IpoCurve *icu, float ypos);
+void draw_ipo_channel(struct gla2DDrawInfo *di, ActKeysInc *aki, struct Ipo *ipo, float ypos);
+void draw_agroup_channel(struct gla2DDrawInfo *di, ActKeysInc *aki, struct bActionGroup *agrp, float ypos);
+void draw_action_channel(struct gla2DDrawInfo *di, ActKeysInc *aki, struct bAction *act, float ypos);
+void draw_object_channel(struct gla2DDrawInfo *di, ActKeysInc *aki, struct Object *ob, float ypos);
+void draw_gpl_channel(struct gla2DDrawInfo *di, ActKeysInc *aki, struct bGPDlayer *gpl, float ypos);
+
+/* Keydata Generation */
+void icu_to_keylist(struct IpoCurve *icu, ListBase *keys, ListBase *blocks, ActKeysInc *aki);
+void ipo_to_keylist(struct Ipo *ipo, ListBase *keys, ListBase *blocks, ActKeysInc *aki);
+void agroup_to_keylist(struct bActionGroup *agrp, ListBase *keys, ListBase *blocks, ActKeysInc *aki);
+void action_to_keylist(struct bAction *act, ListBase *keys, ListBase *blocks, ActKeysInc *aki);
+void action_nlascaled_to_keylist(struct Object *ob, struct bAction *act, ListBase *keys, ListBase *blocks, ActKeysInc *aki);
+void ob_to_keylist(struct Object *ob, ListBase *keys, ListBase *blocks, ActKeysInc *aki);
+void gpl_to_keylist(struct bGPDlayer *gpl, ListBase *keys, ListBase *blocks, ActKeysInc *aki);
+
+#endif /* BDR_DRAWACTION_H */
+
diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h
index 461150ef045..a7a4c2814c3 100644
--- a/source/blender/editors/include/UI_resources.h
+++ b/source/blender/editors/include/UI_resources.h
@@ -527,6 +527,13 @@ enum {
TH_EDGE_SHARP,
TH_EDITMESH_ACTIVE,
+
+ TH_HANDLE_VERTEX,
+ TH_HANDLE_VERTEX_SELECT,
+ TH_HANDLE_VERTEX_SIZE,
+
+ TH_DOPESHEET_CHANNELOB,
+ TH_DOPESHEET_CHANNELSUBOB,
};
/* XXX WARNING: previous is saved in file, so do not change order! */
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index 6e498a5fc29..4022fefa33b 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -430,6 +430,10 @@ void ui_theme_init_userdef(void)
SETCOL(btheme->tipo.hilite, 0x60, 0xc0, 0x40, 255);
btheme->tipo.vertex_size= 3;
+ SETCOL(btheme->tipo.handle_vertex, 0xff, 0x70, 0xff, 255);
+ SETCOL(btheme->tipo.handle_vertex_select, 0xff, 0xff, 0x70, 255);
+ btheme->tipo.handle_vertex_size= 3;
+
/* space file */
/* to have something initialized */
btheme->tfile= btheme->tv3d;
@@ -453,6 +457,11 @@ void ui_theme_init_userdef(void)
SETCOL(btheme->tact.hilite, 17, 27, 60, 100); // bar
SETCOL(btheme->tact.strip_select, 0xff, 0xff, 0xaa, 255);
SETCOL(btheme->tact.strip, 0xe4, 0x9c, 0xc6, 255);
+ SETCOL(btheme->tact.group, 0x39, 0x7d, 0x1b, 255);
+ SETCOL(btheme->tact.group_active, 0x7d, 0xe9, 0x60, 255);
+ SETCOL(btheme->tact.ds_channel, 0x36, 0x13, 0xca, 255);
+ SETCOL(btheme->tact.ds_subchannel, 0x60, 0x43, 0xd2, 255);
+
/* space nla */
btheme->tnla= btheme->tv3d;
diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c
new file mode 100644
index 00000000000..c9c309a7f79
--- /dev/null
+++ b/source/blender/editors/space_action/action_draw.c
@@ -0,0 +1,1321 @@
+/**
+ * $Id: drawaction.c 17746 2008-12-08 11:19:44Z 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) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/* System includes ----------------------------------------------------- */
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <float.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+/* Types --------------------------------------------------------------- */
+
+#include "DNA_listBase.h"
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_space_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_key_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_material_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BKE_action.h"
+#include "BKE_depsgraph.h"
+#include "BKE_ipo.h"
+#include "BKE_key.h"
+#include "BKE_material.h"
+#include "BKE_object.h"
+#include "BKE_global.h" // XXX remove me!
+#include "BKE_context.h"
+#include "BKE_utildefines.h"
+
+/* Everything from source (BIF, BDR, BSE) ------------------------------ */
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "UI_interface.h"
+#include "UI_interface_icons.h"
+#include "UI_resources.h"
+#include "UI_text.h"
+#include "UI_view2d.h"
+
+#include "ED_anim_api.h"
+#include "ED_keyframing.h"
+#include "ED_keyframes_draw.h"
+#include "ED_screen.h"
+#include "ED_space_api.h"
+
+#if 0 // XXX old includes for reference only
+ #include "BIF_editaction.h"
+ #include "BIF_editkey.h"
+ #include "BIF_editnla.h"
+ #include "BIF_drawgpencil.h"
+ #include "BIF_keyframing.h"
+ #include "BIF_language.h"
+ #include "BIF_space.h"
+
+ #include "BDR_editcurve.h"
+ #include "BDR_gpencil.h"
+
+ #include "BSE_drawnla.h"
+ #include "BSE_drawipo.h"
+ #include "BSE_drawview.h"
+ #include "BSE_editaction_types.h"
+ #include "BSE_editipo.h"
+ #include "BSE_headerbuttons.h"
+ #include "BSE_time.h"
+ #include "BSE_view.h"
+#endif // XXX old defines for reference only
+
+/********************************** Slider Stuff **************************** */
+
+#if 0 // XXX all of this slider stuff will need a rethink!
+/* sliders for shapekeys */
+static void meshactionbuts(SpaceAction *saction, Object *ob, Key *key)
+{
+ int i;
+ char str[64];
+ float x, y;
+ uiBlock *block;
+ uiBut *but;
+
+ /* lets make the shapekey sliders */
+
+ /* reset the damn myortho2 or the sliders won't draw/redraw
+ * correctly *grumble*
+ */
+ mywinset(curarea->win);
+ myortho2(-0.375f, curarea->winx-0.375f, G.v2d->cur.ymin, G.v2d->cur.ymax);
+
+ sprintf(str, "actionbuttonswin %d", curarea->win);
+ block= uiNewBlock (&curarea->uiblocks, str, UI_EMBOSS, UI_HELV, curarea->win);
+
+ x = NAMEWIDTH + 1;
+ y = 0.0f;
+
+ uiBlockSetEmboss(block, UI_EMBOSSN);
+
+ if (!(G.saction->flag & SACTION_SLIDERS)) {
+ ACTWIDTH = NAMEWIDTH;
+ but=uiDefIconButBitS(block, TOG, SACTION_SLIDERS, B_REDR,
+ ICON_DISCLOSURE_TRI_RIGHT,
+ NAMEWIDTH - XIC - 5, (short)y + CHANNELHEIGHT,
+ XIC,YIC-2,
+ &(G.saction->flag), 0, 0, 0, 0,
+ "Show action window sliders");
+ /* no hilite, the winmatrix is not correct later on... */
+ uiButSetFlag(but, UI_NO_HILITE);
+ }
+ else {
+ but= uiDefIconButBitS(block, TOG, SACTION_SLIDERS, B_REDR,
+ ICON_DISCLOSURE_TRI_DOWN,
+ NAMEWIDTH - XIC - 5, (short)y + CHANNELHEIGHT,
+ XIC,YIC-2,
+ &(G.saction->flag), 0, 0, 0, 0,
+ "Hide action window sliders");
+ /* no hilite, the winmatrix is not correct later on... */
+ uiButSetFlag(but, UI_NO_HILITE);
+
+ ACTWIDTH = NAMEWIDTH + SLIDERWIDTH;
+
+ /* sliders are open so draw them */
+ BIF_ThemeColor(TH_FACE);
+
+ glRects(NAMEWIDTH, 0, NAMEWIDTH+SLIDERWIDTH, curarea->winy);
+ uiBlockSetEmboss(block, UI_EMBOSS);
+ for (i=1; i < key->totkey; i++) {
+ make_rvk_slider(block, ob, i,
+ (int)x, (int)y, SLIDERWIDTH-2, CHANNELHEIGHT-1, "Slider to control Shape Keys");
+
+ y-=CHANNELHEIGHT+CHANNELSKIP;
+
+ /* see sliderval array in editkey.c */
+ if (i >= 255) break;
+ }
+ }
+ uiDrawBlock(block);
+}
+
+static void icu_slider_func(void *voidicu, void *voidignore)
+{
+ /* the callback for the icu sliders ... copies the
+ * value from the icu->curval into a bezier at the
+ * right frame on the right ipo curve (creating both the
+ * ipo curve and the bezier if needed).
+ */
+ IpoCurve *icu= voidicu;
+ BezTriple *bezt=NULL;
+ float cfra, icuval;
+
+ cfra = frame_to_float(CFRA);
+ if (G.saction->pin==0 && OBACT)
+ cfra= get_action_frame(OBACT, cfra);
+
+ /* if the ipocurve exists, try to get a bezier
+ * for this frame
+ */
+ bezt = get_bezt_icu_time(icu, &cfra, &icuval);
+
+ /* create the bezier triple if one doesn't exist,
+ * otherwise modify it's value
+ */
+ if (bezt == NULL) {
+ insert_vert_icu(icu, cfra, icu->curval, 0);
+ }
+ else {
+ bezt->vec[1][1] = icu->curval;
+ }
+
+ /* make sure the Ipo's are properly processed and
+ * redraw as necessary
+ */
+ sort_time_ipocurve(icu);
+ testhandles_ipocurve(icu);
+
+ /* nla-update (in case this affects anything) */
+ synchronize_action_strips();
+
+ /* do redraw pushes, and also the depsgraph flushes */
+ if (OBACT->pose || ob_get_key(OBACT))
+ DAG_object_flush_update(G.scene, OBACT, OB_RECALC);
+ else
+ DAG_object_flush_update(G.scene, OBACT, OB_RECALC_OB);
+
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWACTION, 0);
+ allqueue(REDRAWNLA, 0);
+ allqueue(REDRAWIPO, 0);
+ allspace(REMAKEIPO, 0);
+ allqueue(REDRAWBUTSALL, 0);
+}
+
+static void make_icu_slider(uiBlock *block, IpoCurve *icu,
+ int x, int y, int w, int h, char *tip)
+{
+ /* create a slider for the ipo-curve*/
+ uiBut *but;
+
+ if(icu == NULL) return;
+
+ if (IS_EQ(icu->slide_max, icu->slide_min)) {
+ if (IS_EQ(icu->ymax, icu->ymin)) {
+ if (ELEM(icu->blocktype, ID_CO, ID_KE)) {
+ /* hack for constraints and shapekeys (and maybe a few others) */
+ icu->slide_min= 0.0;
+ icu->slide_max= 1.0;
+ }
+ else {
+ icu->slide_min= -100;
+ icu->slide_max= 100;
+ }
+ }
+ else {
+ icu->slide_min= icu->ymin;
+ icu->slide_max= icu->ymax;
+ }
+ }
+ if (icu->slide_min >= icu->slide_max) {
+ SWAP(float, icu->slide_min, icu->slide_max);
+ }
+
+ but=uiDefButF(block, NUMSLI, REDRAWVIEW3D, "",
+ x, y , w, h,
+ &(icu->curval), icu->slide_min, icu->slide_max,
+ 10, 2, tip);
+
+ uiButSetFunc(but, icu_slider_func, icu, NULL);
+
+ // no hilite, the winmatrix is not correct later on...
+ uiButSetFlag(but, UI_NO_HILITE);
+}
+
+/* sliders for ipo-curves of active action-channel */
+static void action_icu_buts(SpaceAction *saction)
+{
+ ListBase act_data = {NULL, NULL};
+ bActListElem *ale;
+ int filter;
+ void *data;
+ short datatype;
+
+ char str[64];
+ float x, y;
+ uiBlock *block;
+
+ /* lets make the action sliders */
+
+ /* reset the damn myortho2 or the sliders won't draw/redraw
+ * correctly *grumble*
+ */
+ mywinset(curarea->win);
+ myortho2(-0.375f, curarea->winx-0.375f, G.v2d->cur.ymin, G.v2d->cur.ymax);
+
+ sprintf(str, "actionbuttonswin %d", curarea->win);
+ block= uiNewBlock (&curarea->uiblocks, str,
+ UI_EMBOSS, UI_HELV, curarea->win);
+
+ x = (float)NAMEWIDTH + 1;
+ y = 0.0f;
+
+ uiBlockSetEmboss(block, UI_EMBOSSN);
+
+ if (G.saction->flag & SACTION_SLIDERS) {
+ /* sliders are open so draw them */
+
+ /* get editor data */
+ data= get_action_context(&datatype);
+ if (data == NULL) return;
+
+ /* build list of channels to draw */
+ filter= (ACTFILTER_FORDRAWING|ACTFILTER_VISIBLE|ACTFILTER_CHANNELS);
+ actdata_filter(&act_data, filter, data, datatype);
+
+ /* draw backdrop first */
+ BIF_ThemeColor(TH_FACE); // change this color... it's ugly
+ glRects(NAMEWIDTH, (short)G.v2d->cur.ymin, NAMEWIDTH+SLIDERWIDTH, (short)G.v2d->cur.ymax);
+
+ uiBlockSetEmboss(block, UI_EMBOSS);
+ for (ale= act_data.first; ale; ale= ale->next) {
+ const float yminc= y-CHANNELHEIGHT/2;
+ const float ymaxc= y+CHANNELHEIGHT/2;
+
+ /* check if visible */
+ if ( IN_RANGE(yminc, G.v2d->cur.ymin, G.v2d->cur.ymax) ||
+ IN_RANGE(ymaxc, G.v2d->cur.ymin, G.v2d->cur.ymax) )
+ {
+ /* determine what needs to be drawn */
+ switch (ale->type) {
+ case ACTTYPE_CONCHAN: /* constraint channel */
+ {
+ bActionChannel *achan = (bActionChannel *)ale->owner;
+ IpoCurve *icu = (IpoCurve *)ale->key_data;
+
+ /* only show if owner is selected */
+ if ((ale->ownertype == ACTTYPE_OBJECT) || SEL_ACHAN(achan)) {
+ make_icu_slider(block, icu,
+ (int)x, (int)y, SLIDERWIDTH-2, CHANNELHEIGHT-2,
+ "Slider to control current value of Constraint Influence");
+ }
+ }
+ break;
+ case ACTTYPE_ICU: /* ipo-curve channel */
+ {
+ bActionChannel *achan = (bActionChannel *)ale->owner;
+ IpoCurve *icu = (IpoCurve *)ale->key_data;
+
+ /* only show if owner is selected */
+ if ((ale->ownertype == ACTTYPE_OBJECT) || SEL_ACHAN(achan)) {
+ make_icu_slider(block, icu,
+ (int)x, (int)y, SLIDERWIDTH-2, CHANNELHEIGHT-2,
+ "Slider to control current value of IPO-Curve");
+ }
+ }
+ break;
+ case ACTTYPE_SHAPEKEY: /* shapekey channel */
+ {
+ Object *ob= (Object *)ale->id;
+ IpoCurve *icu= (IpoCurve *)ale->key_data;
+
+ // TODO: only show if object is active
+ if (icu) {
+ make_icu_slider(block, icu,
+ (int)x, (int)y, SLIDERWIDTH-2, CHANNELHEIGHT-2,
+ "Slider to control ShapeKey");
+ }
+ else if (ob && ale->index) {
+ make_rvk_slider(block, ob, ale->index,
+ (int)x, (int)y, SLIDERWIDTH-2, CHANNELHEIGHT-1, "Slider to control Shape Keys");
+ }
+ }
+ break;
+ }
+ }
+
+ /* adjust y-position for next one */
+ y-=CHANNELHEIGHT+CHANNELSKIP;
+ }
+
+ /* free tempolary channels */
+ BLI_freelistN(&act_data);
+ }
+ uiDrawBlock(block);
+}
+
+#endif // XXX all of this slider stuff will need a rethink
+
+
+/********************************** Left-Hand Panel + Generics **************************** */
+
+// XXX
+extern void gl_round_box(short, float, float, float, float, short);
+
+/* left hand part */
+void draw_channel_names(const bContext *C, SpaceAction *saction, ARegion *ar)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimContext ac;
+ bAnimListElem *ale;
+ int filter;
+ View2D *v2d= &ar->v2d;
+ float x= 0.0f, y= (float)(-ACHANNEL_HEIGHT_HALF);
+
+ /* determine what type of data we are operating on */
+ if ((ANIM_animdata_get_context(C, &ac) == 0) || (ac.data == NULL))
+ return;
+
+ /* set default color back to black */
+ //glColor3ub(0x00, 0x00, 0x00);
+
+ /* build list of channels to draw */
+ filter= (ANIMFILTER_FORDRAWING|ANIMFILTER_VISIBLE|ANIMFILTER_CHANNELS);
+ ANIM_animdata_filter(&anim_data, filter, ac.data, ac.datatype);
+
+ /* loop through channels, and set up drawing depending on their type */
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ const float yminc= (float)(y - ACHANNEL_HEIGHT_HALF);
+ const float ymaxc= (float)(y + ACHANNEL_HEIGHT_HALF);
+
+ /* check if visible */
+ if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
+ IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
+ {
+ bActionGroup *grp = NULL;
+ short indent= 0, offset= 0, sel= 0, group= 0;
+ int expand= -1, protect = -1, special= -1, mute = -1;
+ char name[64];
+
+ /* determine what needs to be drawn */
+ switch (ale->type) {
+ case ANIMTYPE_OBJECT: /* object */
+ {
+ Base *base= (Base *)ale->data;
+ Object *ob= base->object;
+
+ group= 4;
+ indent= 0;
+
+ /* icon depends on object-type */
+ if (ob->type == OB_ARMATURE)
+ special= ICON_ARMATURE;
+ else
+ special= ICON_OBJECT;
+
+ /* only show expand if there are any channels */
+ if (EXPANDED_OBJC(ob))
+ expand= ICON_TRIA_DOWN;
+ else
+ expand= ICON_TRIA_RIGHT;
+
+ sel = SEL_OBJC(base);
+ sprintf(name, ob->id.name+2);
+ }
+ break;
+ case ANIMTYPE_FILLACTD: /* action widget */
+ {
+ bAction *act= (bAction *)ale->data;
+
+ group = 4;
+ indent= 1;
+ special= ICON_ACTION;
+
+ if (EXPANDED_ACTC(act))
+ expand= ICON_TRIA_DOWN;
+ else
+ expand= ICON_TRIA_RIGHT;
+
+ sel = SEL_ACTC(act);
+ sprintf(name, "Action");
+ }
+ break;
+ case ANIMTYPE_FILLIPOD: /* ipo (dopesheet) expand widget */
+ {
+ Object *ob = (Object *)ale->data;
+
+ group = 4;
+ indent = 1;
+ special = ICON_IPO;
+
+ if (FILTER_IPO_OBJC(ob))
+ expand = ICON_TRIA_DOWN;
+ else
+ expand = ICON_TRIA_RIGHT;
+
+ //sel = SEL_OBJC(base);
+ sprintf(name, "IPO Curves");
+ }
+ break;
+ case ANIMTYPE_FILLCOND: /* constraint channels (dopesheet) expand widget */
+ {
+ Object *ob = (Object *)ale->data;
+
+ group = 4;
+ indent = 1;
+ special = ICON_CONSTRAINT;
+
+ if (FILTER_CON_OBJC(ob))
+ expand = ICON_TRIA_DOWN;
+ else
+ expand = ICON_TRIA_RIGHT;
+
+ //sel = SEL_OBJC(base);
+ sprintf(name, "Constraints");
+ }
+ break;
+ case ANIMTYPE_FILLMATD: /* object materials (dopesheet) expand widget */
+ {
+ Object *ob = (Object *)ale->data;
+
+ group = 4;
+ indent = 1;
+ special = ICON_MATERIAL;
+
+ if (FILTER_MAT_OBJC(ob))
+ expand = ICON_TRIA_DOWN;
+ else
+ expand = ICON_TRIA_RIGHT;
+
+ sprintf(name, "Materials");
+ }
+ break;
+
+
+ case ANIMTYPE_DSMAT: /* single material (dopesheet) expand widget */
+ {
+ Material *ma = (Material *)ale->data;
+
+ group = 0;
+ indent = 0;
+ special = ICON_MATERIAL;
+ offset = 21;
+
+ if (FILTER_MAT_OBJD(ma))
+ expand = ICON_TRIA_DOWN;
+ else
+ expand = ICON_TRIA_RIGHT;
+
+ sprintf(name, ma->id.name+2);
+ }
+ break;
+ case ANIMTYPE_DSLAM: /* lamp (dopesheet) expand widget */
+ {
+ Lamp *la = (Lamp *)ale->data;
+
+ group = 4;
+ indent = 1;
+ special = ICON_LAMP;
+
+ if (FILTER_LAM_OBJD(la))
+ expand = ICON_TRIA_DOWN;
+ else
+ expand = ICON_TRIA_RIGHT;
+
+ sprintf(name, la->id.name+2);
+ }
+ break;
+ case ANIMTYPE_DSCAM: /* camera (dopesheet) expand widget */
+ {
+ Camera *ca = (Camera *)ale->data;
+
+ group = 4;
+ indent = 1;
+ special = ICON_CAMERA;
+
+ if (FILTER_CAM_OBJD(ca))
+ expand = ICON_TRIA_DOWN;
+ else
+ expand = ICON_TRIA_RIGHT;
+
+ sprintf(name, ca->id.name+2);
+ }
+ break;
+ case ANIMTYPE_DSCUR: /* curve (dopesheet) expand widget */
+ {
+ Curve *cu = (Curve *)ale->data;
+
+ group = 4;
+ indent = 1;
+ special = ICON_CURVE;
+
+ if (FILTER_CUR_OBJD(cu))
+ expand = ICON_TRIA_DOWN;
+ else
+ expand = ICON_TRIA_RIGHT;
+
+ sprintf(name, cu->id.name+2);
+ }
+ break;
+ case ANIMTYPE_DSSKEY: /* shapekeys (dopesheet) expand widget */
+ {
+ Key *key= (Key *)ale->data;
+
+ group = 4;
+ indent = 1;
+ special = ICON_EDIT;
+
+ if (FILTER_SKE_OBJD(key))
+ expand = ICON_TRIA_DOWN;
+ else
+ expand = ICON_TRIA_RIGHT;
+
+ //sel = SEL_OBJC(base);
+ sprintf(name, "Shape Keys");
+ }
+ break;
+
+
+ case ANIMTYPE_GROUP: /* action group */
+ {
+ bActionGroup *agrp= (bActionGroup *)ale->data;
+
+ group= 2;
+ indent= 0;
+ special= -1;
+
+ offset= (ale->id) ? 21 : 0;
+
+ /* only show expand if there are any channels */
+ if (agrp->channels.first) {
+ if (EXPANDED_AGRP(agrp))
+ expand = ICON_TRIA_DOWN;
+ else
+ expand = ICON_TRIA_RIGHT;
+ }
+
+ if (EDITABLE_AGRP(agrp))
+ protect = ICON_UNLOCKED;
+ else
+ protect = ICON_LOCKED;
+
+ sel = SEL_AGRP(agrp);
+ sprintf(name, agrp->name);
+ }
+ break;
+ case ANIMTYPE_ACHAN: /* action channel */
+ {
+ bActionChannel *achan= (bActionChannel *)ale->data;
+
+ group= (ale->grp) ? 1 : 0;
+ grp= ale->grp;
+
+ indent = 0;
+ special = -1;
+
+ offset= (ale->id) ? 21 : 0;
+
+ if (EXPANDED_ACHAN(achan))
+ expand = ICON_TRIA_DOWN;
+ else
+ expand = ICON_TRIA_RIGHT;
+
+ if (EDITABLE_ACHAN(achan))
+ protect = ICON_UNLOCKED;
+ else
+ protect = ICON_LOCKED;
+
+ if (achan->ipo) {
+ if (achan->ipo->muteipo)
+ mute = ICON_MUTE_IPO_ON;
+ else
+ mute = ICON_MUTE_IPO_OFF;
+ }
+
+ sel = SEL_ACHAN(achan);
+ sprintf(name, achan->name);
+ }
+ break;
+ case ANIMTYPE_CONCHAN: /* constraint channel */
+ {
+ bConstraintChannel *conchan = (bConstraintChannel *)ale->data;
+
+ group= (ale->grp) ? 1 : 0;
+ grp= ale->grp;
+
+ if (ale->id) {
+ if (ale->ownertype == ANIMTYPE_ACHAN) {
+ /* for constraint channels under Action in Dopesheet */
+ indent= 2;
+ offset= 21;
+ }
+ else {
+ /* for constraint channels under Object in Dopesheet */
+ indent= 2;
+ offset = 0;
+ }
+ }
+ else {
+ /* for normal constraint channels in Action Editor */
+ indent= 2;
+ offset= 0;
+ }
+
+ if (EDITABLE_CONCHAN(conchan))
+ protect = ICON_UNLOCKED;
+ else
+ protect = ICON_LOCKED;
+
+ if (conchan->ipo) {
+ if (conchan->ipo->muteipo)
+ mute = ICON_MUTE_IPO_ON;
+ else
+ mute = ICON_MUTE_IPO_OFF;
+ }
+
+ sel = SEL_CONCHAN(conchan);
+ sprintf(name, conchan->name);
+ }
+ break;
+ case ANIMTYPE_ICU: /* ipo-curve channel */
+ {
+ IpoCurve *icu = (IpoCurve *)ale->data;
+
+ indent = 2;
+ protect = -1; // for now, until this can be supported by others
+
+ group= (ale->grp) ? 1 : 0;
+ grp= ale->grp;
+
+ if (ale->id) {
+ if ((GS(ale->id->name)==ID_MA) || (ale->ownertype == ANIMTYPE_ACHAN))
+ offset= 21;
+ else
+ offset= 0;
+ }
+ else
+ offset= 0;
+
+ if (icu->flag & IPO_MUTE)
+ mute = ICON_MUTE_IPO_ON;
+ else
+ mute = ICON_MUTE_IPO_OFF;
+
+ sel = SEL_ICU(icu);
+ //if (saction->pin)
+ // sprintf(name, getname_ipocurve(icu, NULL)); // xxx func to eventually eliminate
+ //else
+ // sprintf(name, getname_ipocurve(icu, ac.obact)); // xxx func to eventually eliminate
+ sprintf(name, "[IPO Curve]"); // FIXME xxx
+ }
+ break;
+ case ANIMTYPE_FILLIPO: /* ipo expand widget */
+ {
+ bActionChannel *achan = (bActionChannel *)ale->data;
+
+ indent = 1;
+ //special = geticon_ipo_blocktype(achan->ipo->blocktype); // xxx func to eventually eliminate
+
+ group= (ale->grp) ? 1 : 0;
+ grp= ale->grp;
+
+ offset= (ale->id) ? 21 : 0;
+
+ if (FILTER_IPO_ACHAN(achan))
+ expand = ICON_TRIA_DOWN;
+ else
+ expand = ICON_TRIA_RIGHT;
+
+ sel = SEL_ACHAN(achan);
+ sprintf(name, "IPO Curves");
+ }
+ break;
+ case ANIMTYPE_FILLCON: /* constraint expand widget */
+ {
+ bActionChannel *achan = (bActionChannel *)ale->data;
+
+ indent = 1;
+ special = ICON_CONSTRAINT;
+
+ group= (ale->grp) ? 1 : 0;
+ grp= ale->grp;
+
+ offset= (ale->id) ? 21 : 0;
+
+ if (FILTER_CON_ACHAN(achan))
+ expand = ICON_TRIA_DOWN;
+ else
+ expand = ICON_TRIA_RIGHT;
+
+ sel = SEL_ACHAN(achan);
+ sprintf(name, "Constraint");
+ }
+ break;
+
+
+ case ANIMTYPE_SHAPEKEY: /* shapekey channel */
+ {
+ KeyBlock *kb = (KeyBlock *)ale->data;
+
+ indent = 0;
+ special = -1;
+
+ offset= (ale->id) ? 21 : 0;
+
+ if (kb->name[0] == '\0')
+ sprintf(name, "Key %d", ale->index);
+ else
+ sprintf(name, kb->name);
+ }
+ break;
+
+ case ANIMTYPE_GPDATABLOCK: /* gpencil datablock */
+ {
+ bGPdata *gpd = (bGPdata *)ale->data;
+ ScrArea *sa = (ScrArea *)ale->owner;
+
+ indent = 0;
+ group= 3;
+
+ /* only show expand if there are any channels */
+ if (gpd->layers.first) {
+ if (gpd->flag & GP_DATA_EXPAND)
+ expand = ICON_TRIA_DOWN;
+ else
+ expand = ICON_TRIA_RIGHT;
+ }
+
+ switch (sa->spacetype) {
+ case SPACE_VIEW3D:
+ {
+ /* this shouldn't cause any overflow... */
+ //sprintf(name, "3DView[%02d]:%s", sa->win, view3d_get_name(sa->spacedata.first)); // XXX missing func..
+ special= ICON_VIEW3D;
+ }
+ break;
+ case SPACE_NODE:
+ {
+ SpaceNode *snode= sa->spacedata.first;
+ char treetype[12];
+
+ if (snode->treetype == 1)
+ sprintf(treetype, "Composite");
+ else
+ sprintf(treetype, "Material");
+ sprintf(name, "Nodes:%s", treetype);
+
+ special= ICON_NODE;
+ }
+ break;
+ case SPACE_SEQ:
+ {
+ SpaceSeq *sseq= sa->spacedata.first;
+ char imgpreview[10];
+
+ switch (sseq->mainb) {
+ case 1: sprintf(imgpreview, "Image..."); break;
+ case 2: sprintf(imgpreview, "Luma..."); break;
+ case 3: sprintf(imgpreview, "Chroma..."); break;
+ case 4: sprintf(imgpreview, "Histogram"); break;
+
+ default: sprintf(imgpreview, "Sequence"); break;
+ }
+ sprintf(name, "Sequencer:%s", imgpreview);
+
+ special= ICON_SEQUENCE;
+ }
+ break;
+ case SPACE_IMAGE:
+ {
+ SpaceImage *sima= sa->spacedata.first;
+
+ if (sima->image)
+ sprintf(name, "Image:%s", sima->image->id.name+2);
+ else
+ sprintf(name, "Image:<None>");
+
+ special= ICON_IMAGE_COL;
+ }
+ break;
+
+ default:
+ {
+ sprintf(name, "<Unknown GP-Data Source>");
+ special= -1;
+ }
+ break;
+ }
+ }
+ break;
+ case ANIMTYPE_GPLAYER: /* gpencil layer */
+ {
+ bGPDlayer *gpl = (bGPDlayer *)ale->data;
+
+ indent = 0;
+ special = -1;
+ expand = -1;
+ group = 1;
+
+ if (EDITABLE_GPL(gpl))
+ protect = ICON_UNLOCKED;
+ else
+ protect = ICON_LOCKED;
+
+ if (gpl->flag & GP_LAYER_HIDE)
+ mute = ICON_MUTE_IPO_ON;
+ else
+ mute = ICON_MUTE_IPO_OFF;
+
+ sel = SEL_GPL(gpl);
+ BLI_snprintf(name, 32, gpl->info);
+ }
+ break;
+ }
+
+ /* now, start drawing based on this information */
+ /* draw backing strip behind channel name */
+ if (group == 4) {
+ /* only used in dopesheet... */
+ if (ale->type == ANIMTYPE_OBJECT) {
+ /* object channel - darker */
+ UI_ThemeColor(TH_DOPESHEET_CHANNELOB);
+ uiSetRoundBox((expand == ICON_TRIA_DOWN)? (1):(1|8));
+ gl_round_box(GL_POLYGON, x+offset, yminc, (float)NAMEWIDTH, ymaxc, 8);
+ }
+ else {
+ /* sub-object folders - lighter */
+ UI_ThemeColor(TH_DOPESHEET_CHANNELSUBOB);
+
+ offset += 7 * indent;
+ glBegin(GL_QUADS);
+ glVertex2f(x+offset, yminc);
+ glVertex2f(x+offset, ymaxc);
+ glVertex2f((float)NAMEWIDTH, ymaxc);
+ glVertex2f((float)NAMEWIDTH, yminc);
+ glEnd();
+
+ /* clear group value, otherwise we cause errors... */
+ group = 0;
+ }
+ }
+ else if (group == 3) {
+ /* only for gp-data channels */
+ UI_ThemeColorShade(TH_GROUP, 20);
+ uiSetRoundBox((expand == ICON_TRIA_DOWN)? (1):(1|8));
+ gl_round_box(GL_POLYGON, x+offset, yminc, (float)NAMEWIDTH, ymaxc, 8);
+ }
+ else if (group == 2) {
+ /* only for action group channels */
+ if (ale->flag & AGRP_ACTIVE)
+ UI_ThemeColorShade(TH_GROUP_ACTIVE, 10);
+ else
+ UI_ThemeColorShade(TH_GROUP, 20);
+ uiSetRoundBox((expand == ICON_TRIA_DOWN)? (1):(1|8));
+ gl_round_box(GL_POLYGON, x+offset, yminc, (float)NAMEWIDTH, ymaxc, 8);
+ }
+ else {
+ /* for normal channels
+ * - use 3 shades of color group/standard color for 3 indention level
+ * - only use group colors if allowed to, and if actually feasible
+ */
+ if ( !(saction->flag & SACTION_NODRAWGCOLORS) &&
+ (grp) && (grp->customCol) )
+ {
+ char cp[3];
+
+ if (indent == 2) {
+ VECCOPY(cp, grp->cs.solid);
+ }
+ else if (indent == 1) {
+ VECCOPY(cp, grp->cs.select);
+ }
+ else {
+ VECCOPY(cp, grp->cs.active);
+ }
+
+ glColor3ub(cp[0], cp[1], cp[2]);
+ }
+ else
+ UI_ThemeColorShade(TH_HEADER, ((indent==0)?20: (indent==1)?-20: -40));
+
+ indent += group;
+ offset += 7 * indent;
+ glBegin(GL_QUADS);
+ glVertex2f(x+offset, yminc);
+ glVertex2f(x+offset, ymaxc);
+ glVertex2f((float)NAMEWIDTH, ymaxc);
+ glVertex2f((float)NAMEWIDTH, yminc);
+ glEnd();
+ }
+
+ /* draw expand/collapse triangle */
+ if (expand > 0) {
+ UI_icon_draw(x+offset, yminc, expand);
+ offset += 17;
+ }
+
+ /* draw special icon indicating certain data-types */
+ if (special > -1) {
+ if (ELEM(group, 3, 4)) {
+ /* for gpdatablock channels */
+ UI_icon_draw(x+offset, yminc, special);
+ offset += 17;
+ }
+ else {
+ /* for ipo/constraint channels */
+ UI_icon_draw(x+offset, yminc, special);
+ offset += 17;
+ }
+ }
+
+ /* draw name */
+ if (sel)
+ UI_ThemeColor(TH_TEXT_HI);
+ else
+ UI_ThemeColor(TH_TEXT);
+ offset += 3;
+ glRasterPos2f(x+offset, y-4);
+ UI_DrawString(G.font, name, 0);
+
+ /* reset offset - for RHS of panel */
+ offset = 0;
+
+ /* draw protect 'lock' */
+ if (protect > -1) {
+ offset = 16;
+ UI_icon_draw((float)NAMEWIDTH-offset, yminc, protect);
+ }
+
+ /* draw mute 'eye' */
+ if (mute > -1) {
+ offset += 16;
+ UI_icon_draw((float)(NAMEWIDTH-offset), yminc, mute);
+ }
+ }
+
+ /* adjust y-position for next one */
+ y -= ACHANNEL_STEP;
+ }
+
+ /* free tempolary channels */
+ BLI_freelistN(&anim_data);
+}
+
+static ActKeysInc *init_aki_data(bAnimContext *ac, bAnimListElem *ale)
+{
+ static ActKeysInc aki;
+
+ /* no need to set settings if wrong context */
+ if ((ac->data == NULL) || ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET)==0)
+ return NULL;
+
+ /* if strip is mapped, store settings */
+ aki.ob= ANIM_nla_mapping_get(ac, ale);
+
+ if (ac->datatype == ANIMCONT_DOPESHEET)
+ aki.ads= (bDopeSheet *)ac->data;
+ else
+ aki.ads= NULL;
+ aki.actmode= ac->datatype;
+
+ /* always return pointer... */
+ return &aki;
+}
+
+
+void draw_channel_strips(const bContext *C, SpaceAction *saction, ARegion *ar)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimContext ac;
+ bAnimListElem *ale;
+ int filter;
+
+ View2D *v2d= &ar->v2d;
+ Object *nob= NULL;
+ gla2DDrawInfo *di;
+ rcti scr_rct;
+
+ int act_start, act_end, dummy;
+ float y, sta, end;
+
+ char col1[3], col2[3];
+ char col1a[3], col2a[3];
+ char col1b[3], col2b[3];
+
+
+ /* get theme colors */
+ UI_GetThemeColor3ubv(TH_SHADE2, col2);
+ UI_GetThemeColor3ubv(TH_HILITE, col1);
+ UI_GetThemeColor3ubv(TH_GROUP, col2a);
+ UI_GetThemeColor3ubv(TH_GROUP_ACTIVE, col1a);
+
+ UI_GetThemeColor3ubv(TH_DOPESHEET_CHANNELOB, col1b);
+ UI_GetThemeColor3ubv(TH_DOPESHEET_CHANNELSUBOB, col2b);
+
+ /* get editor data */
+ if ((ANIM_animdata_get_context(C, &ac) == 0) || (ac.data == NULL))
+ return;
+
+ /* set view-mapping rect (only used for x-axis), for NLA-scaling mapping with less calculation */
+ scr_rct.xmin= ar->winrct.xmin + ar->v2d.mask.xmin;
+ scr_rct.ymin= ar->winrct.ymin + ar->v2d.mask.ymin;
+ scr_rct.xmax= ar->winrct.xmin + ar->v2d.hor.xmax;
+ scr_rct.ymax= ar->winrct.ymin + ar->v2d.mask.ymax;
+ di= glaBegin2DDraw(&scr_rct, &v2d->cur);
+
+ /* if in NLA there's a strip active, map the view */
+ if (ac.datatype == ANIMCONT_ACTION) {
+ nob= ANIM_nla_mapping_get(&ac, NULL);
+
+ if (nob)
+ ANIM_nla_mapping_draw(di, nob, 0);
+
+ /* start and end of action itself */
+ calc_action_range(ac.data, &sta, &end, 0);
+ gla2DDrawTranslatePt(di, sta, 0.0f, &act_start, &dummy);
+ gla2DDrawTranslatePt(di, end, 0.0f, &act_end, &dummy);
+
+ if (nob)
+ ANIM_nla_mapping_draw(di, nob, 1);
+ }
+
+ /* build list of channels to draw */
+ filter= (ANIMFILTER_FORDRAWING|ANIMFILTER_VISIBLE|ANIMFILTER_CHANNELS);
+ ANIM_animdata_filter(&anim_data, filter, ac.data, ac.datatype);
+
+ /* first backdrop strips */
+ y= (float)(-ACHANNEL_HEIGHT_HALF);
+ glEnable(GL_BLEND);
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ const float yminc= (float)(y - ACHANNEL_HEIGHT_HALF);
+ const float ymaxc= (float)(y + ACHANNEL_HEIGHT_HALF);
+
+ /* check if visible */
+ if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
+ IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
+ {
+ int frame1_x, channel_y, sel=0;
+
+ /* determine if any need to draw channel */
+ if (ale->datatype != ALE_NONE) {
+ /* determine if channel is selected */
+ switch (ale->type) {
+ case ANIMTYPE_OBJECT:
+ {
+ Base *base= (Base *)ale->data;
+ sel = SEL_OBJC(base);
+ }
+ break;
+ case ANIMTYPE_GROUP:
+ {
+ bActionGroup *agrp = (bActionGroup *)ale->data;
+ sel = SEL_AGRP(agrp);
+ }
+ break;
+ case ANIMTYPE_ACHAN:
+ {
+ bActionChannel *achan = (bActionChannel *)ale->data;
+ sel = SEL_ACHAN(achan);
+ }
+ break;
+ case ANIMTYPE_CONCHAN:
+ {
+ bConstraintChannel *conchan = (bConstraintChannel *)ale->data;
+ sel = SEL_CONCHAN(conchan);
+ }
+ break;
+ case ANIMTYPE_ICU:
+ {
+ IpoCurve *icu = (IpoCurve *)ale->data;
+ sel = SEL_ICU(icu);
+ }
+ break;
+ case ANIMTYPE_GPLAYER:
+ {
+ bGPDlayer *gpl = (bGPDlayer *)ale->data;
+ sel = SEL_GPL(gpl);
+ }
+ break;
+ }
+
+ if (ELEM(ac.datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET)) {
+ gla2DDrawTranslatePt(di, v2d->cur.xmin, y, &frame1_x, &channel_y);
+
+ switch (ale->type) {
+ case ANIMTYPE_OBJECT:
+ {
+ if (sel) glColor4ub(col1b[0], col1b[1], col1b[2], 0x45);
+ else glColor4ub(col1b[0], col1b[1], col1b[2], 0x22);
+ }
+ break;
+
+ case ANIMTYPE_FILLIPOD:
+ case ANIMTYPE_FILLACTD:
+ case ANIMTYPE_FILLCOND:
+ case ANIMTYPE_DSSKEY:
+ {
+ if (sel) glColor4ub(col2b[0], col2b[1], col2b[2], 0x45);
+ else glColor4ub(col2b[0], col2b[1], col2b[2], 0x22);
+ }
+ break;
+
+ case ANIMTYPE_GROUP:
+ {
+ if (sel) glColor4ub(col1a[0], col1a[1], col1a[2], 0x22);
+ else glColor4ub(col2a[0], col2a[1], col2a[2], 0x22);
+ }
+ break;
+
+ default:
+ {
+ if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22);
+ else glColor4ub(col2[0], col2[1], col2[2], 0x22);
+ }
+ break;
+ }
+
+ /* draw region twice: firstly backdrop, then the current range */
+ glRectf((float)frame1_x, (float)channel_y-ACHANNEL_HEIGHT_HALF, (float)v2d->hor.xmax, (float)channel_y+ACHANNEL_HEIGHT_HALF);
+
+ if (ac.datatype == ANIMCONT_ACTION)
+ glRectf((float)act_start, (float)channel_y-ACHANNEL_HEIGHT_HALF, (float)act_end, (float)channel_y+ACHANNEL_HEIGHT_HALF);
+ }
+ else if (ac.datatype == ANIMCONT_SHAPEKEY) {
+ gla2DDrawTranslatePt(di, 1, y, &frame1_x, &channel_y);
+
+ /* all frames that have a frame number less than one
+ * get a desaturated orange background
+ */
+ glColor4ub(col2[0], col2[1], col2[2], 0x22);
+ glRectf(0.0f, (float)channel_y-ACHANNEL_HEIGHT_HALF, (float)frame1_x, (float)channel_y+ACHANNEL_HEIGHT_HALF);
+
+ /* frames one and higher get a saturated orange background */
+ glColor4ub(col2[0], col2[1], col2[2], 0x44);
+ glRectf((float)frame1_x, (float)channel_y-ACHANNEL_HEIGHT_HALF, (float)v2d->hor.xmax, (float)channel_y+ACHANNEL_HEIGHT_HALF);
+ }
+ else if (ac.datatype == ANIMCONT_GPENCIL) {
+ gla2DDrawTranslatePt(di, v2d->cur.xmin, y, &frame1_x, &channel_y);
+
+ /* frames less than one get less saturated background */
+ if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22);
+ else glColor4ub(col2[0], col2[1], col2[2], 0x22);
+ glRectf(0.0f, (float)channel_y-ACHANNEL_HEIGHT_HALF, (float)frame1_x, (float)channel_y+ACHANNEL_HEIGHT_HALF);
+
+ /* frames one and higher get a saturated background */
+ if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x44);
+ else glColor4ub(col2[0], col2[1], col2[2], 0x44);
+ glRectf((float)frame1_x, (float)channel_y-ACHANNEL_HEIGHT_HALF, (float)v2d->hor.xmax, (float)channel_y+ACHANNEL_HEIGHT_HALF);
+ }
+ }
+ }
+
+ /* Increment the step */
+ y -= ACHANNEL_STEP;
+ }
+ glDisable(GL_BLEND);
+
+ /* Draw keyframes
+ * 1) Only channels that are visible in the Action Editor get drawn/evaluated.
+ * This is to try to optimise this for heavier data sets
+ * 2) Keyframes which are out of view horizontally are disregarded
+ */
+ y= (float)(-ACHANNEL_HEIGHT_HALF);
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ const float yminc= (float)(y - ACHANNEL_HEIGHT_HALF);
+ const float ymaxc= (float)(y + ACHANNEL_HEIGHT_HALF);
+
+ /* check if visible */
+ if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
+ IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
+ {
+ /* check if anything to show for this channel */
+ if (ale->datatype != ALE_NONE) {
+ ActKeysInc *aki= init_aki_data(&ac, ale);
+ nob= ANIM_nla_mapping_get(&ac, ale);
+
+ if (nob)
+ ANIM_nla_mapping_draw(di, nob, 0);
+
+ /* draw 'keyframes' for each specific datatype */
+ switch (ale->datatype) {
+ case ALE_OB:
+ draw_object_channel(di, aki, ale->key_data, y);
+ break;
+ case ALE_ACT:
+ draw_action_channel(di, aki, ale->key_data, y);
+ break;
+ case ALE_GROUP:
+ draw_agroup_channel(di, aki, ale->data, y);
+ break;
+ case ALE_IPO:
+ draw_ipo_channel(di, aki, ale->key_data, y);
+ break;
+ case ALE_ICU:
+ draw_icu_channel(di, aki, ale->key_data, y);
+ break;
+ case ALE_GPFRAME:
+ draw_gpl_channel(di, aki, ale->data, y);
+ break;
+ }
+
+ if (nob)
+ ANIM_nla_mapping_draw(di, nob, 1);
+ }
+ }
+
+ y-= ACHANNEL_STEP;
+ }
+
+ /* free tempolary channels used for drawing */
+ BLI_freelistN(&anim_data);
+
+ /* black line marking 'current frame' for Time-Slide transform mode */
+ if (saction->flag & SACTION_MOVING) {
+ int frame1_x;
+
+ gla2DDrawTranslatePt(di, saction->timeslide, 0, &frame1_x, &dummy);
+ cpack(0x0);
+
+ glBegin(GL_LINES);
+ glVertex2f((float)frame1_x, (float)v2d->mask.ymin - 100);
+ glVertex2f((float)frame1_x, (float)v2d->mask.ymax);
+ glEnd();
+ }
+
+ glaEnd2DDraw(di);
+}
diff --git a/source/blender/editors/space_action/action_intern.h b/source/blender/editors/space_action/action_intern.h
index cd4886f50c4..82ff4926082 100644
--- a/source/blender/editors/space_action/action_intern.h
+++ b/source/blender/editors/space_action/action_intern.h
@@ -28,11 +28,18 @@
#ifndef ED_ACTION_INTERN_H
#define ED_ACTION_INTERN_H
+struct bContext;
+struct SpaceAction;
+struct ARegion;
+
/* internal exports only */
+/* action_draw.c */
+void draw_channel_names(const struct bContext *C, struct SpaceAction *saction, struct ARegion *ar);
+void draw_channel_strips(const struct bContext *C, struct SpaceAction *saction, struct ARegion *ar);
/* action_header.c */
-void action_header_buttons(const bContext *C, ARegion *ar);
+void action_header_buttons(const struct bContext *C, struct ARegion *ar);
#endif /* ED_ACTION_INTERN_H */
diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c
index af43f65af82..e3ccc313909 100644
--- a/source/blender/editors/space_action/space_action.c
+++ b/source/blender/editors/space_action/space_action.c
@@ -29,6 +29,7 @@
#include <string.h>
#include <stdio.h>
+#include "DNA_listBase.h"
#include "DNA_action_types.h"
#include "DNA_object_types.h"
#include "DNA_space_types.h"
@@ -58,6 +59,7 @@
#include "UI_view2d.h"
#include "ED_anim_api.h"
+#include "ED_keyframes_draw.h"
#include "ED_markers.h"
#include "action_intern.h" // own include
@@ -177,15 +179,16 @@ static void action_main_area_draw(const bContext *C, ARegion *ar)
glClear(GL_COLOR_BUFFER_BIT);
UI_view2d_view_ortho(C, v2d);
-
+
/* time grid */
unit= (saction->flag & SACTION_DRAWTIME)? V2D_UNIT_SECONDS : V2D_UNIT_FRAMES;
grid= UI_view2d_grid_calc(C, v2d, unit, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY, ar->winx, ar->winy);
UI_view2d_grid_draw(C, v2d, grid, V2D_GRIDLINES_ALL);
UI_view2d_grid_free(grid);
- /* data? */
-
+ /* data */
+ draw_channel_strips(C, saction, ar);
+
/* current frame */
if (saction->flag & SACTION_DRAWTIME) flag |= DRAWCFRA_UNIT_SECONDS;
if ((saction->flag & SACTION_NODRAWCFRANUM)==0) flag |= DRAWCFRA_SHOW_NUMBOX;
@@ -233,7 +236,7 @@ static void action_channel_area_init(wmWindowManager *wm, ARegion *ar)
static void action_channel_area_draw(const bContext *C, ARegion *ar)
{
/* draw entirely, view changes should be handled here */
- //SpaceAction *saction= C->area->spacedata.first;
+ SpaceAction *saction= (SpaceAction*)CTX_wm_space_data(C);
View2D *v2d= &ar->v2d;
View2DScrollers *scrollers;
float col[3];
@@ -245,12 +248,9 @@ static void action_channel_area_draw(const bContext *C, ARegion *ar)
UI_view2d_view_ortho(C, v2d);
- /* data... */
- // temp... line for testing
- glColor3f(0, 0, 0);
- glLineWidth(2.0f);
- sdrawline(10, 0, 190, 0);
- glLineWidth(1.0f);
+ /* data */
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ draw_channel_names(C, saction, ar);
/* reset view matrix */
UI_view2d_view_restore(C);
diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c
index c10ceb78282..1eb0b8c2b86 100644
--- a/source/blender/editors/space_view3d/drawarmature.c
+++ b/source/blender/editors/space_view3d/drawarmature.c
@@ -70,6 +70,8 @@
#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "ED_keyframes_draw.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -79,26 +81,6 @@
/* XXX ***************** */
int pose_channel_in_IK_chain() {return 0;}
-void ipo_to_keylist() {}
-void *ob_get_action() {return NULL;}
-void action_to_keylist() {}
-
-typedef struct ActKeyColumn {
- struct ActKeyColumn *next, *prev;
- short sel, handle_type;
- float cfra;
-
- /* only while drawing - used to determine if long-keyframe needs to be drawn */
- short modified;
- short totcurve;
-} ActKeyColumn;
-typedef struct ActKeysInc {
- struct Object *ob; /* if present, used to find action-scaled time */
- float start, end; /* frames (global-time) to only consider keys between */
-} ActKeysInc;
-
-/* ******************** */
-
/* *************** Armature Drawing - Coloring API ***************************** */
@@ -2192,7 +2174,7 @@ static void draw_pose_paths(View3D *v3d, Object *ob)
if (arm->pathflag & ARM_PATH_KFRAS) {
/* build list of all keyframes in active action for pchan */
keys.first = keys.last = NULL;
- act= ob_get_action(ob);
+ act= ob->action;
if (act) {
achan= get_action_channel(act, pchan->name);
if (achan)
@@ -2338,7 +2320,7 @@ static void draw_ghost_poses_range(Scene *scene, View3D *v3d, Base *base)
static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, Base *base)
{
Object *ob= base->object;
- bAction *act= ob_get_action(ob);
+ bAction *act= ob->action;
bArmature *arm= ob->data;
bPose *posen, *poseo;
ListBase keys= {NULL, NULL};
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index a8cd905f81c..975403c3a5f 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -90,7 +90,8 @@ typedef struct ThemeSpace {
char normal[4];
char bone_solid[4], bone_pose[4];
char strip[4], strip_select[4];
- char cframe[4], pad[4];
+ char cframe[4];
+ char ds_channel[4], ds_subchannel[4]; // dopesheet
char vertex_size, facedot_size;
char bpad[2];
@@ -105,7 +106,7 @@ typedef struct ThemeSpace {
char handle_vertex[4];
char handle_vertex_select[4];
char handle_vertex_size;
- char hpad[7];
+ char hpad[3];
} ThemeSpace;