Exemplo n.º 1
0
/* callback to verify modifier data */
static void validate_fmodifier_cb(bContext *UNUSED(C), void *fcm_v, void *UNUSED(arg))
{
	FModifier *fcm = (FModifier *)fcm_v;
	FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm);
	
	/* call the verify callback on the modifier if applicable */
	if (fmi && fmi->verify_data)
		fmi->verify_data(fcm);
}
Exemplo n.º 2
0
/* evaluate time modifications imposed by some F-Curve Modifiers
 * - this step acts as an optimization to prevent the F-Curve stack being evaluated
 *   several times by modifiers requesting the time be modified, as the final result
 *   would have required using the modified time
 * - modifiers only ever receive the unmodified time, as subsequent modifiers should be
 *   working on the 'global' result of the modified curve, not some localised segment,
 *   so nevaltime gets set to whatever the last time-modifying modifier likes...
 * - we start from the end of the stack, as only the last one matters for now
 *
 * Note: *fcu might be NULL
 */
float evaluate_time_fmodifiers(FModifiersStackStorage *storage,
                               ListBase *modifiers,
                               FCurve *fcu,
                               float cvalue,
                               float evaltime)
{
  /* sanity checks */
  if (ELEM(NULL, modifiers, modifiers->last)) {
    return evaltime;
  }

  if (fcu && fcu->flag & FCURVE_MOD_OFF) {
    return evaltime;
  }

  /* Starting from the end of the stack, calculate the time effects of various stacked modifiers
   * on the time the F-Curve should be evaluated at.
   *
   * This is done in reverse order to standard evaluation, as when this is done in standard
   * order, each modifier would cause jumps to other points in the curve, forcing all
   * previous ones to be evaluated again for them to be correct. However, if we did in the
   * reverse order as we have here, we can consider them a macro to micro type of waterfall
   * effect, which should get us the desired effects when using layered time manipulations
   * (such as multiple 'stepped' modifiers in sequence, causing different stepping rates)
   */
  uint fcm_index = storage->modifier_count - 1;
  for (FModifier *fcm = modifiers->last; fcm; fcm = fcm->prev, fcm_index--) {
    const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm);

    if (fmi == NULL) {
      continue;
    }

    /* If modifier cannot be applied on this frame
     * (whatever scale it is on, it won't affect the results)
     * hence we shouldn't bother seeing what it would do given the chance. */
    if ((fcm->flag & FMODIFIER_FLAG_RANGERESTRICT) == 0 ||
        ((fcm->sfra <= evaltime) && (fcm->efra >= evaltime))) {
      /* only evaluate if there's a callback for this */
      if (fmi->evaluate_modifier_time) {
        if ((fcm->flag & (FMODIFIER_FLAG_DISABLED | FMODIFIER_FLAG_MUTED)) == 0) {
          void *storage_ptr = POINTER_OFFSET(storage->buffer,
                                             fcm_index * storage->size_per_modifier);

          float nval = fmi->evaluate_modifier_time(fcu, fcm, cvalue, evaltime, storage_ptr);

          float influence = eval_fmodifier_influence(fcm, evaltime);
          evaltime = interpf(nval, evaltime, influence);
        }
      }
    }
  }

  /* return the modified evaltime */
  return evaltime;
}
Exemplo n.º 3
0
/* Evaluates the given set of F-Curve Modifiers using the given data
 * Should only be called after evaluate_time_fmodifiers() has been called...
 */
void evaluate_value_fmodifiers(FModifiersStackStorage *storage,
                               ListBase *modifiers,
                               FCurve *fcu,
                               float *cvalue,
                               float evaltime)
{
  FModifier *fcm;

  /* sanity checks */
  if (ELEM(NULL, modifiers, modifiers->first)) {
    return;
  }

  if (fcu->flag & FCURVE_MOD_OFF) {
    return;
  }

  /* evaluate modifiers */
  uint fcm_index = 0;
  for (fcm = modifiers->first; fcm; fcm = fcm->next, fcm_index++) {
    const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm);

    if (fmi == NULL) {
      continue;
    }

    /* Only evaluate if there's a callback for this,
     * and if F-Modifier can be evaluated on this frame. */
    if ((fcm->flag & FMODIFIER_FLAG_RANGERESTRICT) == 0 ||
        ((fcm->sfra <= evaltime) && (fcm->efra >= evaltime))) {
      if (fmi->evaluate_modifier) {
        if ((fcm->flag & (FMODIFIER_FLAG_DISABLED | FMODIFIER_FLAG_MUTED)) == 0) {
          void *storage_ptr = POINTER_OFFSET(storage->buffer,
                                             fcm_index * storage->size_per_modifier);

          float nval = *cvalue;
          fmi->evaluate_modifier(fcu, fcm, &nval, evaltime, storage_ptr);

          float influence = eval_fmodifier_influence(fcm, evaltime);
          *cvalue = interpf(nval, *cvalue, influence);
        }
      }
    }
  }
}
Exemplo n.º 4
0
/* Duplicate all of the F-Modifiers in the Modifier stacks */
void copy_fmodifiers(ListBase *dst, ListBase *src)
{
	FModifier *fcm, *srcfcm;
	
	if (ELEM(NULL, dst, src))
		return;
	
	dst->first = dst->last = NULL;
	BLI_duplicatelist(dst, src);
	
	for (fcm = dst->first, srcfcm = src->first; fcm && srcfcm; srcfcm = srcfcm->next, fcm = fcm->next) {
		FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm);
		
		/* make a new copy of the F-Modifier's data */
		fcm->data = MEM_dupallocN(fcm->data);
		
		/* only do specific constraints if required */
		if (fmi && fmi->copy_data)
			fmi->copy_data(fcm, srcfcm);
	}
}
Exemplo n.º 5
0
uint evaluate_fmodifiers_storage_size_per_modifier(ListBase *modifiers)
{
  /* Sanity checks. */
  if (ELEM(NULL, modifiers, modifiers->first)) {
    return 0;
  }

  uint max_size = 0;

  for (FModifier *fcm = modifiers->first; fcm; fcm = fcm->next) {
    const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm);

    if (fmi == NULL) {
      continue;
    }

    max_size = MAX2(max_size, fmi->storage_size);
  }

  return max_size;
}
Exemplo n.º 6
0
/* Remove and free the given F-Modifier from the given stack  */
bool remove_fmodifier(ListBase *modifiers, FModifier *fcm)
{
  const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm);

  /* sanity check */
  if (fcm == NULL) {
    return false;
  }

  /* removing the cycles modifier requires a handle update */
  FCurve *update_fcu = (fcm->type == FMODIFIER_TYPE_CYCLES) ? fcm->curve : NULL;

  /* free modifier's special data (stored inside fcm->data) */
  if (fcm->data) {
    if (fmi && fmi->free_data) {
      fmi->free_data(fcm);
    }

    /* free modifier's data (fcm->data) */
    MEM_freeN(fcm->data);
  }

  /* remove modifier from stack */
  if (modifiers) {
    BLI_freelinkN(modifiers, fcm);

    /* update the fcurve if the Cycles modifier is removed */
    if (update_fcu) {
      calchandles_fcurve(update_fcu);
    }

    return true;
  }
  else {
    /* XXX this case can probably be removed some day, as it shouldn't happen... */
    CLOG_STR_ERROR(&LOG, "no modifier stack given");
    MEM_freeN(fcm);
    return false;
  }
}
Exemplo n.º 7
0
/* Evaluates the given set of F-Curve Modifiers using the given data
 * Should only be called after evaluate_time_fmodifiers() has been called...
 */
void evaluate_value_fmodifiers(FModifierStackStorage *storage, ListBase *modifiers,
                               FCurve *fcu, float *cvalue, float evaltime)
{
	FModifier *fcm;
	
	/* sanity checks */
	if (ELEM(NULL, modifiers, modifiers->first))
		return;
	
	/* evaluate modifiers */
	for (fcm = modifiers->first; fcm; fcm = fcm->next) {
		FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm);
		
		if (fmi == NULL) 
			continue;
		
		/* only evaluate if there's a callback for this, and if F-Modifier can be evaluated on this frame */
		if ((fcm->flag & FMODIFIER_FLAG_RANGERESTRICT) == 0 ||
		    ((fcm->sfra <= evaltime) && (fcm->efra >= evaltime)) )
		{
			if (fmi->evaluate_modifier || fmi->evaluate_modifier_storage) {
				if ((fcm->flag & (FMODIFIER_FLAG_DISABLED | FMODIFIER_FLAG_MUTED)) == 0) {
					float influence = eval_fmodifier_influence(fcm, evaltime);
					float nval = *cvalue;

					if ((fmi->requires & FMI_REQUIRES_STORAGE) == 0) {
						fmi->evaluate_modifier(fcu, fcm, &nval, evaltime);
					}
					else {
						fmi->evaluate_modifier_storage(storage, fcu, fcm, &nval, evaltime);
					}

					*cvalue = interpf(nval, *cvalue, influence);
				}
			}
		}
	}
} 
Exemplo n.º 8
0
/* Make a copy of the specified F-Modifier */
FModifier *copy_fmodifier(FModifier *src)
{
	FModifierTypeInfo *fmi = fmodifier_get_typeinfo(src);
	FModifier *dst;
	
	/* sanity check */
	if (src == NULL)
		return NULL;
		
	/* copy the base data, clearing the links */
	dst = MEM_dupallocN(src);
	dst->next = dst->prev = NULL;
	
	/* make a new copy of the F-Modifier's data */
	dst->data = MEM_dupallocN(src->data);
	
	/* only do specific constraints if required */
	if (fmi && fmi->copy_data)
		fmi->copy_data(dst, src);
		
	/* return the new modifier */
	return dst;
}
Exemplo n.º 9
0
/* Do we have any modifiers which match certain criteria
 * - mtype - type of modifier (if 0, doesn't matter)
 * - acttype - type of action to perform (if -1, doesn't matter)
 */
bool list_has_suitable_fmodifier(ListBase *modifiers, int mtype, short acttype)
{
  FModifier *fcm;

  /* if there are no specific filtering criteria, just skip */
  if ((mtype == 0) && (acttype == 0)) {
    return (modifiers && modifiers->first);
  }

  /* sanity checks */
  if (ELEM(NULL, modifiers, modifiers->first)) {
    return false;
  }

  /* find the first mdifier fitting these criteria */
  for (fcm = modifiers->first; fcm; fcm = fcm->next) {
    const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm);
    short mOk = 1, aOk = 1; /* by default 1, so that when only one test, won't fail */

    /* check if applicable ones are fulfilled */
    if (mtype) {
      mOk = (fcm->type == mtype);
    }
    if (acttype > -1) {
      aOk = (fmi->acttype == acttype);
    }

    /* if both are ok, we've found a hit */
    if (mOk && aOk) {
      return true;
    }
  }

  /* no matches */
  return false;
}
Exemplo n.º 10
0
void ANIM_uiTemplate_fmodifier_draw(uiLayout *layout, ID *id, ListBase *modifiers, FModifier *fcm)
{
	FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm);
	uiLayout *box, *row, *sub, *col;
	uiBlock *block;
	uiBut *but;
	short width = 314;
	PointerRNA ptr;
	
	/* init the RNA-pointer */
	RNA_pointer_create(id, &RNA_FModifier, fcm, &ptr);
	
	/* draw header */
	{
		/* get layout-row + UI-block for this */
		box = uiLayoutBox(layout);
		
		row = uiLayoutRow(box, FALSE);
		block = uiLayoutGetBlock(row); // err...
		
		/* left-align -------------------------------------------- */
		sub = uiLayoutRow(row, TRUE);
		uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
		
		uiBlockSetEmboss(block, UI_EMBOSSN);
		
		/* expand */
		uiItemR(sub, &ptr, "show_expanded", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
		
		/* checkbox for 'active' status (for now) */
		uiItemR(sub, &ptr, "active", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
		
		/* name */
		if (fmi)
			uiItemL(sub, IFACE_(fmi->name), ICON_NONE);
		else
			uiItemL(sub, IFACE_("<Unknown Modifier>"), ICON_NONE);
		
		/* right-align ------------------------------------------- */
		sub = uiLayoutRow(row, TRUE);
		uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_RIGHT);
		
		
		/* 'mute' button */
		uiItemR(sub, &ptr, "mute", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
		
		uiBlockSetEmboss(block, UI_EMBOSSN);
		
		/* delete button */
		but = uiDefIconBut(block, BUT, B_REDR, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y,
		                   NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Delete F-Curve Modifier"));
		uiButSetFunc(but, delete_fmodifier_cb, modifiers, fcm);
		
		uiBlockSetEmboss(block, UI_EMBOSS);
	}
	
	/* when modifier is expanded, draw settings */
	if (fcm->flag & FMODIFIER_FLAG_EXPANDED) {
		/* set up the flexible-box layout which acts as the backdrop for the modifier settings */
		box = uiLayoutBox(layout);
		
		/* draw settings for individual modifiers */
		switch (fcm->type) {
			case FMODIFIER_TYPE_GENERATOR: /* Generator */
				draw_modifier__generator(box, id, fcm, width);
				break;
				
			case FMODIFIER_TYPE_FN_GENERATOR: /* Built-In Function Generator */
				draw_modifier__fn_generator(box, id, fcm, width);
				break;
				
			case FMODIFIER_TYPE_CYCLES: /* Cycles */
				draw_modifier__cycles(box, id, fcm, width);
				break;
				
			case FMODIFIER_TYPE_ENVELOPE: /* Envelope */
				draw_modifier__envelope(box, id, fcm, width);
				break;
				
			case FMODIFIER_TYPE_LIMITS: /* Limits */
				draw_modifier__limits(box, id, fcm, width);
				break;
			
			case FMODIFIER_TYPE_NOISE: /* Noise */
				draw_modifier__noise(box, id, fcm, width);
				break;
				
			case FMODIFIER_TYPE_STEPPED: /* Stepped */
				draw_modifier__stepped(box, id, fcm, width);
				break;
			
			default: /* unknown type */
				break;
		}
		
		/* one last panel below this: FModifier range */
		// TODO: experiment with placement of this
		{
			box = uiLayoutBox(layout);
			
			/* restricted range ----------------------------------------------------- */
			col = uiLayoutColumn(box, TRUE);
			
			/* top row: use restricted range */
			row = uiLayoutRow(col, TRUE);
			uiItemR(row, &ptr, "use_restricted_range", 0, NULL, ICON_NONE);
			
			if (fcm->flag & FMODIFIER_FLAG_RANGERESTRICT) {
				/* second row: settings */
				row = uiLayoutRow(col, TRUE);
				
				uiItemR(row, &ptr, "frame_start", 0, IFACE_("Start"), ICON_NONE);
				uiItemR(row, &ptr, "frame_end", 0, IFACE_("End"), ICON_NONE);
				
				/* third row: blending influence */
				row = uiLayoutRow(col, TRUE);
				
				uiItemR(row, &ptr, "blend_in", 0, IFACE_("In"), ICON_NONE);
				uiItemR(row, &ptr, "blend_out", 0, IFACE_("Out"), ICON_NONE);
			}
			
			/* influence -------------------------------------------------------------- */
			col = uiLayoutColumn(box, TRUE);
			
			/* top row: use influence */
			uiItemR(col, &ptr, "use_influence", 0, NULL, ICON_NONE);
			
			if (fcm->flag & FMODIFIER_FLAG_USEINFLUENCE) {
				/* second row: influence value */
				uiItemR(col, &ptr, "influence", 0, NULL, ICON_NONE);
			}
		}
	}
}
Exemplo n.º 11
0
void ANIM_uiTemplate_fmodifier_draw (uiLayout *layout, ID *id, ListBase *modifiers, FModifier *fcm)
{
	FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
	uiLayout *box, *row, *subrow;
	uiBlock *block;
	uiBut *but;
	short width= 314;
	PointerRNA ptr;
	
	/* init the RNA-pointer */
	RNA_pointer_create(id, &RNA_FModifier, fcm, &ptr);
	
	/* draw header */
	{
		/* get layout-row + UI-block for this */
		box= uiLayoutBox(layout);
		
		row= uiLayoutRow(box, 0);
		block= uiLayoutGetBlock(row); // err...
		
		/* left-align -------------------------------------------- */
		subrow= uiLayoutRow(row, 0);
		uiLayoutSetAlignment(subrow, UI_LAYOUT_ALIGN_LEFT);
		
		uiBlockSetEmboss(block, UI_EMBOSSN);
		
		/* expand */
		uiItemR(subrow, &ptr, "show_expanded", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
		
		/* checkbox for 'active' status (for now) */
		uiItemR(subrow, &ptr, "active", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
		
		/* name */
		if (fmi)
			uiItemL(subrow, fmi->name, ICON_NONE);
		else
			uiItemL(subrow, "<Unknown Modifier>", ICON_NONE);
		
		/* right-align ------------------------------------------- */
		subrow= uiLayoutRow(row, 0);
		uiLayoutSetAlignment(subrow, UI_LAYOUT_ALIGN_RIGHT);
		
		
		/* 'mute' button */
		uiItemR(subrow, &ptr, "mute", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
		
		uiBlockSetEmboss(block, UI_EMBOSSN);
		
		/* delete button */
		but= uiDefIconBut(block, BUT, B_REDR, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, "Delete F-Curve Modifier.");
		uiButSetFunc(but, delete_fmodifier_cb, modifiers, fcm);
		
		uiBlockSetEmboss(block, UI_EMBOSS);
	}
	
	/* when modifier is expanded, draw settings */
	if (fcm->flag & FMODIFIER_FLAG_EXPANDED) {
		/* set up the flexible-box layout which acts as the backdrop for the modifier settings */
		box= uiLayoutBox(layout); 
		
		/* draw settings for individual modifiers */
		switch (fcm->type) {
			case FMODIFIER_TYPE_GENERATOR: /* Generator */
				draw_modifier__generator(box, id, fcm, width);
				break;
				
			case FMODIFIER_TYPE_FN_GENERATOR: /* Built-In Function Generator */
				draw_modifier__fn_generator(box, id, fcm, width);
				break;
				
			case FMODIFIER_TYPE_CYCLES: /* Cycles */
				draw_modifier__cycles(box, id, fcm, width);
				break;
				
			case FMODIFIER_TYPE_ENVELOPE: /* Envelope */
				draw_modifier__envelope(box, id, fcm, width);
				break;
				
			case FMODIFIER_TYPE_LIMITS: /* Limits */
				draw_modifier__limits(box, id, fcm, width);
				break;
			
			case FMODIFIER_TYPE_NOISE: /* Noise */
				draw_modifier__noise(box, id, fcm, width);
				break;
				
			case FMODIFIER_TYPE_STEPPED: /* Stepped */
				draw_modifier__stepped(box, id, fcm, width);
				break;
			
			default: /* unknown type */
				break;
		}
	}
}