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:
authorAntonio Vazquez <blendergit@gmail.com>2020-07-23 18:54:11 +0300
committerAntonio Vazquez <blendergit@gmail.com>2020-07-23 18:54:11 +0300
commit5d96ed364f2704cfa32118ba256df306e8ceef92 (patch)
treee61a2406696923d08f421f8ff12636da2b3174a1 /source/blender/gpencil_modifiers/intern
parent416d28323bad4d453009e84a568946983d9fc28c (diff)
GPencil: Apply GSoC changes
Diffstat (limited to 'source/blender/gpencil_modifiers/intern')
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c997
1 files changed, 497 insertions, 500 deletions
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c
index 8e0e314f454..2e2fcb21251 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c
@@ -17,9 +17,9 @@
* This is a new part of Blender
*/
- /** \file
- * \ingroup modifiers
- */
+/** \file
+ * \ingroup modifiers
+ */
#include <stdio.h>
@@ -57,29 +57,29 @@
#include "MOD_gpencil_ui_common.h"
#include "MOD_gpencil_util.h"
-static void initData(GpencilModifierData* md)
+static void initData(GpencilModifierData *md)
{
- BuildGpencilModifierData* gpmd = (BuildGpencilModifierData*)md;
+ BuildGpencilModifierData *gpmd = (BuildGpencilModifierData *)md;
- /* We deliberately set this range to the half the default
- * frame-range to have an immediate effect to suggest use-cases
- */
- gpmd->start_frame = 1;
- gpmd->end_frame = 125;
+ /* We deliberately set this range to the half the default
+ * frame-range to have an immediate effect to suggest use-cases
+ */
+ gpmd->start_frame = 1;
+ gpmd->end_frame = 125;
- /* Init default length of each build effect - Nothing special */
- gpmd->start_delay = 0.0f;
- gpmd->length = 100.0f;
+ /* Init default length of each build effect - Nothing special */
+ gpmd->start_delay = 0.0f;
+ gpmd->length = 100.0f;
}
-static void copyData(const GpencilModifierData* md, GpencilModifierData* target)
+static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
{
- BKE_gpencil_modifier_copydata_generic(md, target);
+ BKE_gpencil_modifier_copydata_generic(md, target);
}
-static bool dependsOnTime(GpencilModifierData* UNUSED(md))
+static bool dependsOnTime(GpencilModifierData *UNUSED(md))
{
- return true;
+ return true;
}
/* ******************************************** */
@@ -98,560 +98,557 @@ static bool dependsOnTime(GpencilModifierData* UNUSED(md))
* - All strokes present are fully visible (i.e. we don't have to ignore any)
*/
- /* Remove a particular stroke */
-static void clear_stroke(bGPDframe* gpf, bGPDstroke* gps)
+/* Remove a particular stroke */
+static void clear_stroke(bGPDframe *gpf, bGPDstroke *gps)
{
- BLI_remlink(&gpf->strokes, gps);
- BKE_gpencil_free_stroke(gps);
+ BLI_remlink(&gpf->strokes, gps);
+ BKE_gpencil_free_stroke(gps);
}
/* Clear all strokes in frame */
-static void gpf_clear_all_strokes(bGPDframe* gpf)
+static void gpf_clear_all_strokes(bGPDframe *gpf)
{
- bGPDstroke* gps, * gps_next;
- for (gps = gpf->strokes.first; gps; gps = gps_next) {
- gps_next = gps->next;
- clear_stroke(gpf, gps);
- }
- BLI_listbase_clear(&gpf->strokes);
+ bGPDstroke *gps, *gps_next;
+ for (gps = gpf->strokes.first; gps; gps = gps_next) {
+ gps_next = gps->next;
+ clear_stroke(gpf, gps);
+ }
+ BLI_listbase_clear(&gpf->strokes);
}
/* Reduce the number of points in the stroke
*
* Note: This won't be called if all points are present/removed
*/
-static void reduce_stroke_points(bGPdata* gpd,
- bGPDstroke* gps,
- const int num_points,
- const eBuildGpencil_Transition transition)
+static void reduce_stroke_points(bGPdata *gpd,
+ bGPDstroke *gps,
+ const int num_points,
+ const eBuildGpencil_Transition transition)
{
- bGPDspoint* new_points = MEM_callocN(sizeof(bGPDspoint) * num_points, __func__);
- MDeformVert* new_dvert = NULL;
- if ((gps->dvert != NULL) && (num_points > 0)) {
- new_dvert = MEM_callocN(sizeof(MDeformVert) * num_points, __func__);
- }
-
- /* Which end should points be removed from */
- switch (transition) {
- case GP_BUILD_TRANSITION_GROW: /* Show in forward order =
- * Remove ungrown-points from end of stroke. */
- case GP_BUILD_TRANSITION_SHRINK: /* Hide in reverse order =
- * Remove dead-points from end of stroke. */
- {
- /* copy over point data */
- memcpy(new_points, gps->points, sizeof(bGPDspoint) * num_points);
- if ((gps->dvert != NULL) && (num_points > 0)) {
- memcpy(new_dvert, gps->dvert, sizeof(MDeformVert) * num_points);
-
- /* free unused point weights */
- for (int i = num_points; i < gps->totpoints; i++) {
- MDeformVert* dvert = &gps->dvert[i];
- BKE_gpencil_free_point_weights(dvert);
- }
- }
- break;
- }
-
- /* Hide in forward order = Remove points from start of stroke */
- case GP_BUILD_TRANSITION_FADE:
- {
- /* num_points is the number of points left after reducing.
- * We need to know how many to remove
- */
- const int offset = gps->totpoints - num_points;
-
- /* copy over point data */
- memcpy(new_points, gps->points + offset, sizeof(bGPDspoint) * num_points);
- if ((gps->dvert != NULL) && (num_points > 0)) {
- memcpy(new_dvert, gps->dvert + offset, sizeof(MDeformVert) * num_points);
-
- /* free unused weights */
- for (int i = 0; i < offset; i++) {
- MDeformVert* dvert = &gps->dvert[i];
- BKE_gpencil_free_point_weights(dvert);
- }
- }
- break;
- }
-
- default:
- printf("ERROR: Unknown transition %d in %s()\n", (int)transition, __func__);
- break;
- }
-
- /* replace stroke geometry */
- MEM_SAFE_FREE(gps->points);
- MEM_SAFE_FREE(gps->dvert);
- gps->points = new_points;
- gps->dvert = new_dvert;
- gps->totpoints = num_points;
-
- /* Calc geometry data. */
- BKE_gpencil_stroke_geometry_update(gpd, gps);
+ bGPDspoint *new_points = MEM_callocN(sizeof(bGPDspoint) * num_points, __func__);
+ MDeformVert *new_dvert = NULL;
+ if ((gps->dvert != NULL) && (num_points > 0)) {
+ new_dvert = MEM_callocN(sizeof(MDeformVert) * num_points, __func__);
+ }
+
+ /* Which end should points be removed from */
+ switch (transition) {
+ case GP_BUILD_TRANSITION_GROW: /* Show in forward order =
+ * Remove ungrown-points from end of stroke. */
+ case GP_BUILD_TRANSITION_SHRINK: /* Hide in reverse order =
+ * Remove dead-points from end of stroke. */
+ {
+ /* copy over point data */
+ memcpy(new_points, gps->points, sizeof(bGPDspoint) * num_points);
+ if ((gps->dvert != NULL) && (num_points > 0)) {
+ memcpy(new_dvert, gps->dvert, sizeof(MDeformVert) * num_points);
+
+ /* free unused point weights */
+ for (int i = num_points; i < gps->totpoints; i++) {
+ MDeformVert *dvert = &gps->dvert[i];
+ BKE_gpencil_free_point_weights(dvert);
+ }
+ }
+ break;
+ }
+
+ /* Hide in forward order = Remove points from start of stroke */
+ case GP_BUILD_TRANSITION_FADE: {
+ /* num_points is the number of points left after reducing.
+ * We need to know how many to remove
+ */
+ const int offset = gps->totpoints - num_points;
+
+ /* copy over point data */
+ memcpy(new_points, gps->points + offset, sizeof(bGPDspoint) * num_points);
+ if ((gps->dvert != NULL) && (num_points > 0)) {
+ memcpy(new_dvert, gps->dvert + offset, sizeof(MDeformVert) * num_points);
+
+ /* free unused weights */
+ for (int i = 0; i < offset; i++) {
+ MDeformVert *dvert = &gps->dvert[i];
+ BKE_gpencil_free_point_weights(dvert);
+ }
+ }
+ break;
+ }
+
+ default:
+ printf("ERROR: Unknown transition %d in %s()\n", (int)transition, __func__);
+ break;
+ }
+
+ /* replace stroke geometry */
+ MEM_SAFE_FREE(gps->points);
+ MEM_SAFE_FREE(gps->dvert);
+ gps->points = new_points;
+ gps->dvert = new_dvert;
+ gps->totpoints = num_points;
+
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gpd, gps);
}
/* --------------------------------------------- */
/* Stroke Data Table Entry - This represents one stroke being generated */
-typedef struct tStrokeBuildDetails
-{
- bGPDstroke* gps;
+typedef struct tStrokeBuildDetails {
+ bGPDstroke *gps;
- /* Indices - first/last indices for the stroke's points (overall) */
- size_t start_idx, end_idx;
+ /* Indices - first/last indices for the stroke's points (overall) */
+ size_t start_idx, end_idx;
- /* Number of points - Cache for more convenient access */
- int totpoints;
+ /* Number of points - Cache for more convenient access */
+ int totpoints;
} tStrokeBuildDetails;
/* Sequential - Show strokes one after the other */
-static void build_sequential(BuildGpencilModifierData* mmd,
- bGPdata* gpd,
- bGPDframe* gpf,
- float fac)
+static void build_sequential(BuildGpencilModifierData *mmd,
+ bGPdata *gpd,
+ bGPDframe *gpf,
+ float fac)
{
- const size_t tot_strokes = BLI_listbase_count(&gpf->strokes);
- bGPDstroke* gps;
- size_t i;
-
- /* 1) Compute proportion of time each stroke should occupy */
- /* NOTE: This assumes that the total number of points won't overflow! */
- tStrokeBuildDetails* table = MEM_callocN(sizeof(tStrokeBuildDetails) * tot_strokes, __func__);
- size_t totpoints = 0;
-
- /* 1.1) First pass - Tally up points */
- for (gps = gpf->strokes.first, i = 0; gps; gps = gps->next, i++) {
- tStrokeBuildDetails* cell = &table[i];
-
- cell->gps = gps;
- cell->totpoints = gps->totpoints;
-
- totpoints += cell->totpoints;
- }
-
- /* 1.2) Second pass - Compute the overall indices for points */
- for (i = 0; i < tot_strokes; i++) {
- tStrokeBuildDetails* cell = &table[i];
-
- if (i == 0) {
- cell->start_idx = 0;
- }
- else {
- cell->start_idx = (cell - 1)->end_idx;
- }
- cell->end_idx = cell->start_idx + cell->totpoints - 1;
- }
-
- /* 2) Determine the global indices for points that should be visible */
- size_t first_visible = 0;
- size_t last_visible = 0;
-
- switch (mmd->transition) {
- /* Show in forward order
- * - As fac increases, the number of visible points increases
- */
- case GP_BUILD_TRANSITION_GROW:
- first_visible = 0; /* always visible */
- last_visible = (size_t)roundf(totpoints * fac);
- break;
-
- /* Hide in reverse order
- * - As fac increases, the number of points visible at the end decreases
- */
- case GP_BUILD_TRANSITION_SHRINK:
- first_visible = 0; /* always visible (until last point removed) */
- last_visible = (size_t)(totpoints * (1.0f - fac));
- break;
-
- /* Hide in forward order
- * - As fac increases, the early points start getting hidden
- */
- case GP_BUILD_TRANSITION_FADE:
- first_visible = (size_t)(totpoints * fac);
- last_visible = totpoints; /* i.e. visible until the end, unless first overlaps this */
- break;
- }
-
- /* 3) Go through all strokes, deciding which to keep, and/or how much of each to keep */
- for (i = 0; i < tot_strokes; i++) {
- tStrokeBuildDetails* cell = &table[i];
-
- /* Determine what portion of the stroke is visible */
- if ((cell->end_idx < first_visible) || (cell->start_idx > last_visible)) {
- /* Not visible at all - Either ended before */
- clear_stroke(gpf, cell->gps);
- }
- else {
- /* Some proportion of stroke is visible */
- if ((first_visible <= cell->start_idx) && (last_visible >= cell->end_idx)) {
- /* Do nothing - whole stroke is visible */
- }
- else if (first_visible > cell->start_idx) {
- /* Starts partway through this stroke */
- int num_points = cell->end_idx - first_visible;
- reduce_stroke_points(gpd, cell->gps, num_points, mmd->transition);
- }
- else {
- /* Ends partway through this stroke */
- int num_points = last_visible - cell->start_idx;
- reduce_stroke_points(gpd, cell->gps, num_points, mmd->transition);
- }
- }
- }
-
- /* Free table */
- MEM_freeN(table);
+ const size_t tot_strokes = BLI_listbase_count(&gpf->strokes);
+ bGPDstroke *gps;
+ size_t i;
+
+ /* 1) Compute proportion of time each stroke should occupy */
+ /* NOTE: This assumes that the total number of points won't overflow! */
+ tStrokeBuildDetails *table = MEM_callocN(sizeof(tStrokeBuildDetails) * tot_strokes, __func__);
+ size_t totpoints = 0;
+
+ /* 1.1) First pass - Tally up points */
+ for (gps = gpf->strokes.first, i = 0; gps; gps = gps->next, i++) {
+ tStrokeBuildDetails *cell = &table[i];
+
+ cell->gps = gps;
+ cell->totpoints = gps->totpoints;
+
+ totpoints += cell->totpoints;
+ }
+
+ /* 1.2) Second pass - Compute the overall indices for points */
+ for (i = 0; i < tot_strokes; i++) {
+ tStrokeBuildDetails *cell = &table[i];
+
+ if (i == 0) {
+ cell->start_idx = 0;
+ }
+ else {
+ cell->start_idx = (cell - 1)->end_idx;
+ }
+ cell->end_idx = cell->start_idx + cell->totpoints - 1;
+ }
+
+ /* 2) Determine the global indices for points that should be visible */
+ size_t first_visible = 0;
+ size_t last_visible = 0;
+
+ switch (mmd->transition) {
+ /* Show in forward order
+ * - As fac increases, the number of visible points increases
+ */
+ case GP_BUILD_TRANSITION_GROW:
+ first_visible = 0; /* always visible */
+ last_visible = (size_t)roundf(totpoints * fac);
+ break;
+
+ /* Hide in reverse order
+ * - As fac increases, the number of points visible at the end decreases
+ */
+ case GP_BUILD_TRANSITION_SHRINK:
+ first_visible = 0; /* always visible (until last point removed) */
+ last_visible = (size_t)(totpoints * (1.0f - fac));
+ break;
+
+ /* Hide in forward order
+ * - As fac increases, the early points start getting hidden
+ */
+ case GP_BUILD_TRANSITION_FADE:
+ first_visible = (size_t)(totpoints * fac);
+ last_visible = totpoints; /* i.e. visible until the end, unless first overlaps this */
+ break;
+ }
+
+ /* 3) Go through all strokes, deciding which to keep, and/or how much of each to keep */
+ for (i = 0; i < tot_strokes; i++) {
+ tStrokeBuildDetails *cell = &table[i];
+
+ /* Determine what portion of the stroke is visible */
+ if ((cell->end_idx < first_visible) || (cell->start_idx > last_visible)) {
+ /* Not visible at all - Either ended before */
+ clear_stroke(gpf, cell->gps);
+ }
+ else {
+ /* Some proportion of stroke is visible */
+ if ((first_visible <= cell->start_idx) && (last_visible >= cell->end_idx)) {
+ /* Do nothing - whole stroke is visible */
+ }
+ else if (first_visible > cell->start_idx) {
+ /* Starts partway through this stroke */
+ int num_points = cell->end_idx - first_visible;
+ reduce_stroke_points(gpd, cell->gps, num_points, mmd->transition);
+ }
+ else {
+ /* Ends partway through this stroke */
+ int num_points = last_visible - cell->start_idx;
+ reduce_stroke_points(gpd, cell->gps, num_points, mmd->transition);
+ }
+ }
+ }
+
+ /* Free table */
+ MEM_freeN(table);
}
/* --------------------------------------------- */
/* Concurrent - Show multiple strokes at once */
-static void build_concurrent(BuildGpencilModifierData* mmd,
- bGPdata* gpd,
- bGPDframe* gpf,
- float fac)
+static void build_concurrent(BuildGpencilModifierData *mmd,
+ bGPdata *gpd,
+ bGPDframe *gpf,
+ float fac)
{
- bGPDstroke* gps, * gps_next;
- int max_points = 0;
-
- const bool reverse = (mmd->transition != GP_BUILD_TRANSITION_GROW);
-
- /* 1) Determine the longest stroke, to figure out when short strokes should start */
- /* FIXME: A *really* long stroke here could dwarf everything else, causing bad timings */
- for (gps = gpf->strokes.first; gps; gps = gps->next) {
- if (gps->totpoints > max_points) {
- max_points = gps->totpoints;
- }
- }
- if (max_points == 0) {
- printf("ERROR: Strokes are all empty (GP Build Modifier: %s)\n", __func__);
- return;
- }
-
- /* 2) For each stroke, determine how it should be handled */
- for (gps = gpf->strokes.first; gps; gps = gps_next) {
- gps_next = gps->next;
-
- /* Relative Length of Stroke - Relative to the longest stroke,
- * what proportion of the available time should this stroke use
- */
- const float relative_len = (float)gps->totpoints / (float)max_points;
-
- /* Determine how many points should be left in the stroke */
- int num_points = 0;
-
- switch (mmd->time_alignment) {
- case GP_BUILD_TIMEALIGN_START: /* all start on frame 1 */
- {
- /* Build effect occurs over when fac = 0, to fac = relative_len */
- if (fac <= relative_len) {
- /* Scale fac to fit relative_len */
- const float scaled_fac = fac / MAX2(relative_len, PSEUDOINVERSE_EPSILON);
-
- if (reverse) {
- num_points = (int)roundf((1.0f - scaled_fac) * gps->totpoints);
- }
- else {
- num_points = (int)roundf(scaled_fac * gps->totpoints);
- }
- }
- else {
- /* Build effect has ended */
- if (reverse) {
- num_points = 0;
- }
- else {
- num_points = gps->totpoints;
- }
- }
-
- break;
- }
- case GP_BUILD_TIMEALIGN_END: /* all end on same frame */
- {
- /* Build effect occurs over 1.0 - relative_len, to 1.0 (i.e. over the end of the range)
- */
- const float start_fac = 1.0f - relative_len;
-
- if (fac >= start_fac) {
- const float scaled_fac = (fac - start_fac) / MAX2(relative_len, PSEUDOINVERSE_EPSILON);
-
- if (reverse) {
- num_points = (int)roundf((1.0f - scaled_fac) * gps->totpoints);
- }
- else {
- num_points = (int)roundf(scaled_fac * gps->totpoints);
- }
- }
- else {
- /* Build effect hasn't started */
- if (reverse) {
- num_points = gps->totpoints;
- }
- else {
- num_points = 0;
- }
- }
-
- break;
- }
- }
-
- /* Modify the stroke geometry */
- if (num_points <= 0) {
- /* Nothing Left - Delete the stroke */
- clear_stroke(gpf, gps);
- }
- else if (num_points < gps->totpoints) {
- /* Remove some points */
- reduce_stroke_points(gpd, gps, num_points, mmd->transition);
- }
- }
+ bGPDstroke *gps, *gps_next;
+ int max_points = 0;
+
+ const bool reverse = (mmd->transition != GP_BUILD_TRANSITION_GROW);
+
+ /* 1) Determine the longest stroke, to figure out when short strokes should start */
+ /* FIXME: A *really* long stroke here could dwarf everything else, causing bad timings */
+ for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ if (gps->totpoints > max_points) {
+ max_points = gps->totpoints;
+ }
+ }
+ if (max_points == 0) {
+ printf("ERROR: Strokes are all empty (GP Build Modifier: %s)\n", __func__);
+ return;
+ }
+
+ /* 2) For each stroke, determine how it should be handled */
+ for (gps = gpf->strokes.first; gps; gps = gps_next) {
+ gps_next = gps->next;
+
+ /* Relative Length of Stroke - Relative to the longest stroke,
+ * what proportion of the available time should this stroke use
+ */
+ const float relative_len = (float)gps->totpoints / (float)max_points;
+
+ /* Determine how many points should be left in the stroke */
+ int num_points = 0;
+
+ switch (mmd->time_alignment) {
+ case GP_BUILD_TIMEALIGN_START: /* all start on frame 1 */
+ {
+ /* Build effect occurs over when fac = 0, to fac = relative_len */
+ if (fac <= relative_len) {
+ /* Scale fac to fit relative_len */
+ const float scaled_fac = fac / MAX2(relative_len, PSEUDOINVERSE_EPSILON);
+
+ if (reverse) {
+ num_points = (int)roundf((1.0f - scaled_fac) * gps->totpoints);
+ }
+ else {
+ num_points = (int)roundf(scaled_fac * gps->totpoints);
+ }
+ }
+ else {
+ /* Build effect has ended */
+ if (reverse) {
+ num_points = 0;
+ }
+ else {
+ num_points = gps->totpoints;
+ }
+ }
+
+ break;
+ }
+ case GP_BUILD_TIMEALIGN_END: /* all end on same frame */
+ {
+ /* Build effect occurs over 1.0 - relative_len, to 1.0 (i.e. over the end of the range)
+ */
+ const float start_fac = 1.0f - relative_len;
+
+ if (fac >= start_fac) {
+ const float scaled_fac = (fac - start_fac) / MAX2(relative_len, PSEUDOINVERSE_EPSILON);
+
+ if (reverse) {
+ num_points = (int)roundf((1.0f - scaled_fac) * gps->totpoints);
+ }
+ else {
+ num_points = (int)roundf(scaled_fac * gps->totpoints);
+ }
+ }
+ else {
+ /* Build effect hasn't started */
+ if (reverse) {
+ num_points = gps->totpoints;
+ }
+ else {
+ num_points = 0;
+ }
+ }
+
+ break;
+ }
+ }
+
+ /* Modify the stroke geometry */
+ if (num_points <= 0) {
+ /* Nothing Left - Delete the stroke */
+ clear_stroke(gpf, gps);
+ }
+ else if (num_points < gps->totpoints) {
+ /* Remove some points */
+ reduce_stroke_points(gpd, gps, num_points, mmd->transition);
+ }
+ }
}
/* --------------------------------------------- */
static void generate_geometry(
- GpencilModifierData* md, Depsgraph* depsgraph, bGPdata* gpd, bGPDlayer* gpl, bGPDframe* gpf)
+ GpencilModifierData *md, Depsgraph *depsgraph, bGPdata *gpd, bGPDlayer *gpl, bGPDframe *gpf)
{
- BuildGpencilModifierData* mmd = (BuildGpencilModifierData*)md;
- const bool reverse = (mmd->transition != GP_BUILD_TRANSITION_GROW);
- const bool is_percentage = (mmd->flag & GP_BUILD_PERCENTAGE);
-
- const float ctime = DEG_get_ctime(depsgraph);
-
- /* Early exit if it's an empty frame */
- if (gpf->strokes.first == NULL) {
- return;
- }
-
- /* Omit layer if filter by layer */
- if (mmd->layername[0] != '\0') {
- if ((mmd->flag & GP_BUILD_INVERT_LAYER) == 0) {
- if (!STREQ(mmd->layername, gpl->info)) {
- return;
- }
- }
- else {
- if (STREQ(mmd->layername, gpl->info)) {
- return;
- }
- }
- }
- /* verify layer pass */
- if (mmd->layer_pass > 0) {
- if ((mmd->flag & GP_BUILD_INVERT_LAYERPASS) == 0) {
- if (gpl->pass_index != mmd->layer_pass) {
- return;
- }
- }
- else {
- if (gpl->pass_index == mmd->layer_pass) {
- return;
- }
- }
- }
-
- /* Early exit if outside of the frame range for this modifier
- * (e.g. to have one forward, and one backwards modifier)
- */
- if (mmd->flag & GP_BUILD_RESTRICT_TIME) {
- if ((ctime < mmd->start_frame) || (ctime > mmd->end_frame)) {
- return;
- }
- }
-
- /* Compute start and end frames for the animation effect
- * By default, the upper bound is given by the "maximum length" setting
- */
- float start_frame = gpf->framenum + mmd->start_delay;
- float end_frame = start_frame + mmd->length;
-
- if (gpf->next) {
- /* Use the next frame or upper bound as end frame, whichever is lower/closer */
- end_frame = MIN2(end_frame, gpf->next->framenum);
- }
-
- /* Early exit if current frame is outside start/end bounds */
- /* NOTE: If we're beyond the next/previous frames (if existent),
- * then we wouldn't have this problem anyway... */
- if (ctime < start_frame) {
- /* Before Start - Animation hasn't started. Display initial state. */
- if (reverse) {
- /* 1) Reverse = Start with all, end with nothing.
- * ==> Do nothing (everything already present)
- */
- }
- else {
- /* 2) Forward Order = Start with nothing, end with the full frame.
- * ==> Free all strokes, and return an empty frame
- */
- gpf_clear_all_strokes(gpf);
- }
-
- /* Early exit */
- return;
- }
- else if (ctime >= end_frame) {
- /* Past End - Animation finished. Display final result. */
- if (reverse) {
- /* 1) Reverse = Start with all, end with nothing.
- * ==> Free all strokes, and return an empty frame
- */
- gpf_clear_all_strokes(gpf);
- }
- else {
- /* 2) Forward Order = Start with nothing, end with the full frame.
- * ==> Do Nothing (everything already present)
- */
- }
-
- /* Early exit */
- return;
- }
-
- /* Determine how far along we are between the keyframes */
- float fac = is_percentage ? mmd->percentage_fac :
- (ctime - start_frame) / (end_frame - start_frame);
-
- /* Time management mode */
- switch (mmd->mode) {
- case GP_BUILD_MODE_SEQUENTIAL:
- build_sequential(mmd, gpd, gpf, fac);
- break;
-
- case GP_BUILD_MODE_CONCURRENT:
- build_concurrent(mmd, gpd, gpf, fac);
- break;
-
- default:
- printf("Unsupported build mode (%d) for GP Build Modifier: '%s'\n",
- mmd->mode,
- mmd->modifier.name);
- break;
- }
+ BuildGpencilModifierData *mmd = (BuildGpencilModifierData *)md;
+ const bool reverse = (mmd->transition != GP_BUILD_TRANSITION_GROW);
+ const bool is_percentage = (mmd->flag & GP_BUILD_PERCENTAGE);
+
+ const float ctime = DEG_get_ctime(depsgraph);
+
+ /* Early exit if it's an empty frame */
+ if (gpf->strokes.first == NULL) {
+ return;
+ }
+
+ /* Omit layer if filter by layer */
+ if (mmd->layername[0] != '\0') {
+ if ((mmd->flag & GP_BUILD_INVERT_LAYER) == 0) {
+ if (!STREQ(mmd->layername, gpl->info)) {
+ return;
+ }
+ }
+ else {
+ if (STREQ(mmd->layername, gpl->info)) {
+ return;
+ }
+ }
+ }
+ /* verify layer pass */
+ if (mmd->layer_pass > 0) {
+ if ((mmd->flag & GP_BUILD_INVERT_LAYERPASS) == 0) {
+ if (gpl->pass_index != mmd->layer_pass) {
+ return;
+ }
+ }
+ else {
+ if (gpl->pass_index == mmd->layer_pass) {
+ return;
+ }
+ }
+ }
+
+ /* Early exit if outside of the frame range for this modifier
+ * (e.g. to have one forward, and one backwards modifier)
+ */
+ if (mmd->flag & GP_BUILD_RESTRICT_TIME) {
+ if ((ctime < mmd->start_frame) || (ctime > mmd->end_frame)) {
+ return;
+ }
+ }
+
+ /* Compute start and end frames for the animation effect
+ * By default, the upper bound is given by the "maximum length" setting
+ */
+ float start_frame = gpf->framenum + mmd->start_delay;
+ float end_frame = start_frame + mmd->length;
+
+ if (gpf->next) {
+ /* Use the next frame or upper bound as end frame, whichever is lower/closer */
+ end_frame = MIN2(end_frame, gpf->next->framenum);
+ }
+
+ /* Early exit if current frame is outside start/end bounds */
+ /* NOTE: If we're beyond the next/previous frames (if existent),
+ * then we wouldn't have this problem anyway... */
+ if (ctime < start_frame) {
+ /* Before Start - Animation hasn't started. Display initial state. */
+ if (reverse) {
+ /* 1) Reverse = Start with all, end with nothing.
+ * ==> Do nothing (everything already present)
+ */
+ }
+ else {
+ /* 2) Forward Order = Start with nothing, end with the full frame.
+ * ==> Free all strokes, and return an empty frame
+ */
+ gpf_clear_all_strokes(gpf);
+ }
+
+ /* Early exit */
+ return;
+ }
+ else if (ctime >= end_frame) {
+ /* Past End - Animation finished. Display final result. */
+ if (reverse) {
+ /* 1) Reverse = Start with all, end with nothing.
+ * ==> Free all strokes, and return an empty frame
+ */
+ gpf_clear_all_strokes(gpf);
+ }
+ else {
+ /* 2) Forward Order = Start with nothing, end with the full frame.
+ * ==> Do Nothing (everything already present)
+ */
+ }
+
+ /* Early exit */
+ return;
+ }
+
+ /* Determine how far along we are between the keyframes */
+ float fac = is_percentage ? mmd->percentage_fac :
+ (ctime - start_frame) / (end_frame - start_frame);
+
+ /* Time management mode */
+ switch (mmd->mode) {
+ case GP_BUILD_MODE_SEQUENTIAL:
+ build_sequential(mmd, gpd, gpf, fac);
+ break;
+
+ case GP_BUILD_MODE_CONCURRENT:
+ build_concurrent(mmd, gpd, gpf, fac);
+ break;
+
+ default:
+ printf("Unsupported build mode (%d) for GP Build Modifier: '%s'\n",
+ mmd->mode,
+ mmd->modifier.name);
+ break;
+ }
}
/* Entry-point for Build Modifier */
-static void generateStrokes(GpencilModifierData* md, Depsgraph* depsgraph, Object* ob)
+static void generateStrokes(GpencilModifierData *md, Depsgraph *depsgraph, Object *ob)
{
- Scene* scene = DEG_get_evaluated_scene(depsgraph);
- bGPdata* gpd = (bGPdata*)ob->data;
-
- LISTBASE_FOREACH(bGPDlayer*, gpl, &gpd->layers)
- {
- bGPDframe* gpf = BKE_gpencil_frame_retime_get(depsgraph, scene, ob, gpl);
- if (gpf == NULL) {
- continue;
- }
- generate_geometry(md, depsgraph, gpd, gpl, gpf);
- }
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
+ bGPdata *gpd = (bGPdata *)ob->data;
+
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ bGPDframe *gpf = BKE_gpencil_frame_retime_get(depsgraph, scene, ob, gpl);
+ if (gpf == NULL) {
+ continue;
+ }
+ generate_geometry(md, depsgraph, gpd, gpl, gpf);
+ }
}
-static void panel_draw(const bContext* C, Panel* panel)
+static void panel_draw(const bContext *C, Panel *panel)
{
- uiLayout* row, * sub;
- uiLayout* layout = panel->layout;
+ uiLayout *row, *sub;
+ uiLayout *layout = panel->layout;
- PointerRNA ptr;
- PointerRNA ob_ptr;
- gpencil_modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
+ PointerRNA ptr;
+ PointerRNA ob_ptr;
+ gpencil_modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
- int mode = RNA_enum_get(&ptr, "mode");
+ int mode = RNA_enum_get(&ptr, "mode");
- uiLayoutSetPropSep(layout, true);
+ uiLayoutSetPropSep(layout, true);
- uiItemR(layout, &ptr, "mode", 0, NULL, ICON_NONE);
- if (mode == GP_BUILD_MODE_CONCURRENT) {
- uiItemR(layout, &ptr, "concurrent_time_alignment", 0, NULL, ICON_NONE);
- }
+ uiItemR(layout, &ptr, "mode", 0, NULL, ICON_NONE);
+ if (mode == GP_BUILD_MODE_CONCURRENT) {
+ uiItemR(layout, &ptr, "concurrent_time_alignment", 0, NULL, ICON_NONE);
+ }
- uiItemS(layout);
+ uiItemS(layout);
- uiItemR(layout, &ptr, "transition", 0, NULL, ICON_NONE);
- uiItemR(layout, &ptr, "start_delay", 0, NULL, ICON_NONE);
- uiItemR(layout, &ptr, "length", 0, IFACE_("Frames"), ICON_NONE);
+ uiItemR(layout, &ptr, "transition", 0, NULL, ICON_NONE);
+ uiItemR(layout, &ptr, "start_delay", 0, NULL, ICON_NONE);
+ uiItemR(layout, &ptr, "length", 0, IFACE_("Frames"), ICON_NONE);
- uiItemS(layout);
+ uiItemS(layout);
- row = uiLayoutRowWithHeading(layout, true, IFACE_("Use Factor"));
- uiItemR(row, &ptr, "use_percentage", 0, "", ICON_NONE);
- sub = uiLayoutRow(row, true);
- uiLayoutSetActive(sub, RNA_boolean_get(&ptr, "use_percentage"));
- uiItemR(sub, &ptr, "percentage_factor", 0, "", ICON_NONE);
+ row = uiLayoutRowWithHeading(layout, true, IFACE_("Use Factor"));
+ uiItemR(row, &ptr, "use_percentage", 0, "", ICON_NONE);
+ sub = uiLayoutRow(row, true);
+ uiLayoutSetActive(sub, RNA_boolean_get(&ptr, "use_percentage"));
+ uiItemR(sub, &ptr, "percentage_factor", 0, "", ICON_NONE);
- /* Check for incompatible time modifier. */
- Object* ob = ob_ptr.data;
- GpencilModifierData* md = ptr.data;
- if (BKE_gpencil_modifiers_findby_type(ob, eGpencilModifierType_Time) != NULL) {
- BKE_gpencil_modifier_set_error(md, "Build and Time Offset modifiers are incompatible");
- }
+ /* Check for incompatible time modifier. */
+ Object *ob = ob_ptr.data;
+ GpencilModifierData *md = ptr.data;
+ if (BKE_gpencil_modifiers_findby_type(ob, eGpencilModifierType_Time) != NULL) {
+ BKE_gpencil_modifier_set_error(md, "Build and Time Offset modifiers are incompatible");
+ }
- gpencil_modifier_panel_end(layout, &ptr);
+ gpencil_modifier_panel_end(layout, &ptr);
}
-static void frame_range_header_draw(const bContext* C, Panel* panel)
+static void frame_range_header_draw(const bContext *C, Panel *panel)
{
- uiLayout* layout = panel->layout;
+ uiLayout *layout = panel->layout;
- PointerRNA ptr;
- gpencil_modifier_panel_get_property_pointers(C, panel, NULL, &ptr);
+ PointerRNA ptr;
+ gpencil_modifier_panel_get_property_pointers(C, panel, NULL, &ptr);
- uiItemR(layout, &ptr, "use_restrict_frame_range", 0, IFACE_("Custom Range"), ICON_NONE);
+ uiItemR(layout, &ptr, "use_restrict_frame_range", 0, IFACE_("Custom Range"), ICON_NONE);
}
-static void frame_range_panel_draw(const bContext* C, Panel* panel)
+static void frame_range_panel_draw(const bContext *C, Panel *panel)
{
- uiLayout* col;
- uiLayout* layout = panel->layout;
+ uiLayout *col;
+ uiLayout *layout = panel->layout;
- PointerRNA ptr;
- gpencil_modifier_panel_get_property_pointers(C, panel, NULL, &ptr);
+ PointerRNA ptr;
+ gpencil_modifier_panel_get_property_pointers(C, panel, NULL, &ptr);
- uiLayoutSetPropSep(layout, true);
+ uiLayoutSetPropSep(layout, true);
- col = uiLayoutColumn(layout, false);
- uiItemR(col, &ptr, "frame_start", 0, IFACE_("Start"), ICON_NONE);
- uiItemR(col, &ptr, "frame_end", 0, IFACE_("End"), ICON_NONE);
+ col = uiLayoutColumn(layout, false);
+ uiItemR(col, &ptr, "frame_start", 0, IFACE_("Start"), ICON_NONE);
+ uiItemR(col, &ptr, "frame_end", 0, IFACE_("End"), ICON_NONE);
}
-static void mask_panel_draw(const bContext* C, Panel* panel)
+static void mask_panel_draw(const bContext *C, Panel *panel)
{
- gpencil_modifier_masking_panel_draw(C, panel, false, false);
+ gpencil_modifier_masking_panel_draw(C, panel, false, false);
}
-static void panelRegister(ARegionType* region_type)
+static void panelRegister(ARegionType *region_type)
{
- PanelType* panel_type = gpencil_modifier_panel_register(
- region_type, eGpencilModifierType_Build, panel_draw);
- gpencil_modifier_subpanel_register(
- region_type, "frame_range", "", frame_range_header_draw, frame_range_panel_draw, panel_type);
- gpencil_modifier_subpanel_register(
- region_type, "_mask", "Influence", NULL, mask_panel_draw, panel_type);
+ PanelType *panel_type = gpencil_modifier_panel_register(
+ region_type, eGpencilModifierType_Build, panel_draw);
+ gpencil_modifier_subpanel_register(
+ region_type, "frame_range", "", frame_range_header_draw, frame_range_panel_draw, panel_type);
+ gpencil_modifier_subpanel_register(
+ region_type, "_mask", "Influence", NULL, mask_panel_draw, panel_type);
}
/* ******************************************** */
GpencilModifierTypeInfo modifierType_Gpencil_Build = {
- /* name */ "Build",
- /* structName */ "BuildGpencilModifierData",
- /* structSize */ sizeof(BuildGpencilModifierData),
- /* type */ eGpencilModifierTypeType_Gpencil,
- /* flags */ eGpencilModifierTypeFlag_NoApply,
-
- /* copyData */ copyData,
-
- /* deformStroke */ NULL,
- /* generateStrokes */ generateStrokes,
- /* bakeModifier */ NULL,
- /* remapTime */ NULL,
-
- /* initData */ initData,
- /* freeData */ NULL,
- /* isDisabled */ NULL,
- /* updateDepsgraph */ NULL,
- /* dependsOnTime */ dependsOnTime,
- /* foreachObjectLink */ NULL,
- /* foreachIDLink */ NULL,
- /* foreachTexLink */ NULL,
- /* panelRegister */ panelRegister,
+ /* name */ "Build",
+ /* structName */ "BuildGpencilModifierData",
+ /* structSize */ sizeof(BuildGpencilModifierData),
+ /* type */ eGpencilModifierTypeType_Gpencil,
+ /* flags */ eGpencilModifierTypeFlag_NoApply,
+
+ /* copyData */ copyData,
+
+ /* deformStroke */ NULL,
+ /* generateStrokes */ generateStrokes,
+ /* bakeModifier */ NULL,
+ /* remapTime */ NULL,
+
+ /* initData */ initData,
+ /* freeData */ NULL,
+ /* isDisabled */ NULL,
+ /* updateDepsgraph */ NULL,
+ /* dependsOnTime */ dependsOnTime,
+ /* foreachObjectLink */ NULL,
+ /* foreachIDLink */ NULL,
+ /* foreachTexLink */ NULL,
+ /* panelRegister */ panelRegister,
};