NLA SoC: Assorted fixes
* Made NLA Editing functions more aware of transitions. - A transition can only be added between a pair of action-clips. Previous, two transitions could be added next to each other, which has undefined behaviour - Deleting a strip with transition(s) on either side will remove the transitions too. Feedback welcome on this - The 'type' setting for NLA-Strips is no longer editable. This was dangerous as it could result in transitions with undefined behaviour (though nothing would happen). * Menus for adding F-Modifiers now only show relevant modifiers (i.e. 'Invalid' is not included in the list, and 'Cycles' doesn't need to be shown for NLA since we've got repeat) * Function Generator and Noise F-Modifiers now have complete GUI's. A few settings were missed during the porting process. * F-Modifier buttons now have their source-ID's included in the RNA Pointers used. This didn't get them animateable directly, but is a step closer.
This commit is contained in:
@@ -1,12 +1,33 @@
|
||||
/* Testing code for new animation system in 2.5
|
||||
* Copyright 2009, Joshua Leung
|
||||
/**
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
|
||||
* All rights reserved.
|
||||
*
|
||||
* Contributor(s): Joshua Leung (full recode)
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#ifndef BKE_FCURVE_H
|
||||
#define BKE_FCURVE_H
|
||||
|
||||
//struct ListBase;
|
||||
|
||||
struct FCurve;
|
||||
struct FModifier;
|
||||
struct ChannelDriver;
|
||||
@@ -54,8 +75,8 @@ typedef struct FModifierTypeInfo {
|
||||
short size; /* size in bytes of the struct */
|
||||
short acttype; /* eFMI_Action_Types */
|
||||
short requires; /* eFMI_Requirement_Flags */
|
||||
char name[32]; /* name of modifier in interface */
|
||||
char structName[32]; /* name of struct for SDNA */
|
||||
char name[64]; /* name of modifier in interface */
|
||||
char structName[64]; /* name of struct for SDNA */
|
||||
|
||||
/* data management function pointers - special handling */
|
||||
/* free any data that is allocated separately (optional) */
|
||||
|
||||
@@ -66,7 +66,6 @@
|
||||
/* Remove the given NLA strip from the NLA track it occupies, free the strip's data,
|
||||
* and the strip itself.
|
||||
*/
|
||||
// TODO: with things like transitions, should these get freed too? Maybe better as a UI tool
|
||||
void free_nlastrip (ListBase *strips, NlaStrip *strip)
|
||||
{
|
||||
/* sanity checks */
|
||||
@@ -793,6 +792,7 @@ void BKE_nla_action_pushdown (AnimData *adt)
|
||||
/* not first, so extend mode can only be NLASTRIP_EXTEND_HOLD_FORWARD not NLASTRIP_EXTEND_HOLD,
|
||||
* so that it doesn't override strips in previous tracks
|
||||
*/
|
||||
// FIXME: this needs to be more automated, since user can rearrange strips
|
||||
strip->extendmode= NLASTRIP_EXTEND_HOLD_FORWARD;
|
||||
}
|
||||
}
|
||||
@@ -844,7 +844,7 @@ short BKE_nla_tweakmode_enter (AnimData *adt)
|
||||
if (strip->act == activeStrip->act)
|
||||
strip->flag |= NLASTRIP_FLAG_TWEAKUSER;
|
||||
else
|
||||
strip->flag &= ~NLASTRIP_FLAG_TWEAKUSER; // XXX probably don't need to clear this...
|
||||
strip->flag &= ~NLASTRIP_FLAG_TWEAKUSER;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -887,8 +887,8 @@ void BKE_nla_tweakmode_exit (AnimData *adt)
|
||||
|
||||
// TODO: need to sync the user-strip with the new state of the action!
|
||||
|
||||
/* for all NLA-tracks, clear the 'disabled' flag
|
||||
* for all NLA-strips, clear the 'tweak-user' flag
|
||||
/* for all Tracks, clear the 'disabled' flag
|
||||
* for all Strips, clear the 'tweak-user' flag
|
||||
*/
|
||||
for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
|
||||
nlt->flag &= ~NLATRACK_DISABLED;
|
||||
|
||||
@@ -134,7 +134,7 @@ static void delete_fmodifier_cb (bContext *C, void *fmods_v, void *fcm_v)
|
||||
/* --------------- */
|
||||
|
||||
/* draw settings for generator modifier */
|
||||
static void draw_modifier__generator(uiLayout *layout, FModifier *fcm, short width)
|
||||
static void draw_modifier__generator(uiLayout *layout, ID *id, FModifier *fcm, short width)
|
||||
{
|
||||
FMod_Generator *data= (FMod_Generator *)fcm->data;
|
||||
uiLayout *col, *row;
|
||||
@@ -143,7 +143,7 @@ static void draw_modifier__generator(uiLayout *layout, FModifier *fcm, short wid
|
||||
PointerRNA ptr;
|
||||
|
||||
/* init the RNA-pointer */
|
||||
RNA_pointer_create(NULL, &RNA_FModifierFunctionGenerator, fcm, &ptr);
|
||||
RNA_pointer_create(id, &RNA_FModifierFunctionGenerator, fcm, &ptr);
|
||||
|
||||
/* basic settings (backdrop + mode selector + some padding) */
|
||||
col= uiLayoutColumn(layout, 1);
|
||||
@@ -248,31 +248,36 @@ static void draw_modifier__generator(uiLayout *layout, FModifier *fcm, short wid
|
||||
/* --------------- */
|
||||
|
||||
/* draw settings for noise modifier */
|
||||
static void draw_modifier__fn_generator(uiLayout *layout, FModifier *fcm, short width)
|
||||
static void draw_modifier__fn_generator(uiLayout *layout, ID *id, FModifier *fcm, short width)
|
||||
{
|
||||
uiLayout *col= uiLayoutColumn(layout, 0); // no grouping for now
|
||||
uiLayout *col;
|
||||
PointerRNA ptr;
|
||||
|
||||
/* init the RNA-pointer */
|
||||
RNA_pointer_create(NULL, &RNA_FModifierFunctionGenerator, fcm, &ptr);
|
||||
RNA_pointer_create(id, &RNA_FModifierFunctionGenerator, fcm, &ptr);
|
||||
|
||||
/* add the settings */
|
||||
uiItemR(col, NULL, 0, &ptr, "amplitude", 0, 0, 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "phase_multiplier", 0, 0, 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "phase_offset", 0, 0, 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "value_offset", 0, 0, 0);
|
||||
col= uiLayoutColumn(layout, 1);
|
||||
uiItemR(col, "", 0, &ptr, "type", 0, 0, 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "additive", 0, 0, 1);
|
||||
|
||||
col= uiLayoutColumn(layout, 0); // no grouping for now
|
||||
uiItemR(col, NULL, 0, &ptr, "amplitude", 0, 0, 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "phase_multiplier", 0, 0, 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "phase_offset", 0, 0, 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "value_offset", 0, 0, 0);
|
||||
}
|
||||
|
||||
/* --------------- */
|
||||
|
||||
/* draw settings for cycles modifier */
|
||||
static void draw_modifier__cycles(uiLayout *layout, FModifier *fcm, short width)
|
||||
static void draw_modifier__cycles(uiLayout *layout, ID *id, FModifier *fcm, short width)
|
||||
{
|
||||
uiLayout *split, *col;
|
||||
PointerRNA ptr;
|
||||
|
||||
/* init the RNA-pointer */
|
||||
RNA_pointer_create(NULL, &RNA_FModifierCycles, fcm, &ptr);
|
||||
RNA_pointer_create(id, &RNA_FModifierCycles, fcm, &ptr);
|
||||
|
||||
/* split into 2 columns
|
||||
* NOTE: the mode comboboxes shouldn't get labels, otherwise there isn't enough room
|
||||
@@ -295,13 +300,16 @@ static void draw_modifier__cycles(uiLayout *layout, FModifier *fcm, short width)
|
||||
/* --------------- */
|
||||
|
||||
/* draw settings for noise modifier */
|
||||
static void draw_modifier__noise(uiLayout *layout, FModifier *fcm, short width)
|
||||
static void draw_modifier__noise(uiLayout *layout, ID *id, FModifier *fcm, short width)
|
||||
{
|
||||
uiLayout *split, *col;
|
||||
PointerRNA ptr;
|
||||
|
||||
/* init the RNA-pointer */
|
||||
RNA_pointer_create(NULL, &RNA_FModifierNoise, fcm, &ptr);
|
||||
RNA_pointer_create(id, &RNA_FModifierNoise, fcm, &ptr);
|
||||
|
||||
/* blending mode */
|
||||
uiItemR(layout, NULL, 0, &ptr, "modification", 0, 0, 0);
|
||||
|
||||
/* split into 2 columns */
|
||||
split= uiLayoutSplit(layout, 0.5f);
|
||||
@@ -479,7 +487,7 @@ static void fmod_envelope_deletepoint_cb (bContext *C, void *fcm_dv, void *ind_v
|
||||
}
|
||||
|
||||
/* draw settings for envelope modifier */
|
||||
static void draw_modifier__envelope(uiLayout *layout, FModifier *fcm, short width)
|
||||
static void draw_modifier__envelope(uiLayout *layout, ID *id, FModifier *fcm, short width)
|
||||
{
|
||||
FMod_Envelope *env= (FMod_Envelope *)fcm->data;
|
||||
FCM_EnvelopeData *fed;
|
||||
@@ -490,7 +498,7 @@ static void draw_modifier__envelope(uiLayout *layout, FModifier *fcm, short widt
|
||||
int i;
|
||||
|
||||
/* init the RNA-pointer */
|
||||
RNA_pointer_create(NULL, &RNA_FModifierEnvelope, fcm, &ptr);
|
||||
RNA_pointer_create(id, &RNA_FModifierEnvelope, fcm, &ptr);
|
||||
|
||||
/* general settings */
|
||||
col= uiLayoutColumn(layout, 1);
|
||||
@@ -534,13 +542,13 @@ static void draw_modifier__envelope(uiLayout *layout, FModifier *fcm, short widt
|
||||
/* --------------- */
|
||||
|
||||
/* draw settings for limits modifier */
|
||||
static void draw_modifier__limits(uiLayout *layout, FModifier *fcm, short width)
|
||||
static void draw_modifier__limits(uiLayout *layout, ID *id, FModifier *fcm, short width)
|
||||
{
|
||||
uiLayout *split, *col, *row;
|
||||
PointerRNA ptr;
|
||||
|
||||
/* init the RNA-pointer */
|
||||
RNA_pointer_create(NULL, &RNA_FModifierLimits, fcm, &ptr);
|
||||
RNA_pointer_create(id, &RNA_FModifierLimits, fcm, &ptr);
|
||||
|
||||
/* row 1: minimum */
|
||||
{
|
||||
@@ -582,7 +590,7 @@ static void draw_modifier__limits(uiLayout *layout, FModifier *fcm, short width)
|
||||
/* --------------- */
|
||||
|
||||
|
||||
void ANIM_uiTemplate_fmodifier_draw (uiLayout *layout, ListBase *modifiers, FModifier *fcm)
|
||||
void ANIM_uiTemplate_fmodifier_draw (uiLayout *layout, ID *id, ListBase *modifiers, FModifier *fcm)
|
||||
{
|
||||
FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
|
||||
uiLayout *box, *row, *subrow;
|
||||
@@ -639,27 +647,27 @@ void ANIM_uiTemplate_fmodifier_draw (uiLayout *layout, ListBase *modifiers, FMod
|
||||
/* draw settings for individual modifiers */
|
||||
switch (fcm->type) {
|
||||
case FMODIFIER_TYPE_GENERATOR: /* Generator */
|
||||
draw_modifier__generator(box, fcm, width);
|
||||
draw_modifier__generator(box, id, fcm, width);
|
||||
break;
|
||||
|
||||
case FMODIFIER_TYPE_FN_GENERATOR: /* Built-In Function Generator */
|
||||
draw_modifier__fn_generator(box, fcm, width);
|
||||
draw_modifier__fn_generator(box, id, fcm, width);
|
||||
break;
|
||||
|
||||
case FMODIFIER_TYPE_CYCLES: /* Cycles */
|
||||
draw_modifier__cycles(box, fcm, width);
|
||||
draw_modifier__cycles(box, id, fcm, width);
|
||||
break;
|
||||
|
||||
case FMODIFIER_TYPE_ENVELOPE: /* Envelope */
|
||||
draw_modifier__envelope(box, fcm, width);
|
||||
draw_modifier__envelope(box, id, fcm, width);
|
||||
break;
|
||||
|
||||
case FMODIFIER_TYPE_LIMITS: /* Limits */
|
||||
draw_modifier__limits(box, fcm, width);
|
||||
draw_modifier__limits(box, id, fcm, width);
|
||||
break;
|
||||
|
||||
case FMODIFIER_TYPE_NOISE: /* Noise */
|
||||
draw_modifier__noise(box, fcm, width);
|
||||
draw_modifier__noise(box, id, fcm, width);
|
||||
break;
|
||||
|
||||
default: /* unknown type */
|
||||
|
||||
@@ -300,7 +300,7 @@ struct uiLayout;
|
||||
|
||||
/* draw a given F-Modifier for some layout/UI-Block */
|
||||
// XXX not quite complete yet
|
||||
void ANIM_uiTemplate_fmodifier_draw(struct uiLayout *layout, ListBase *modifiers, struct FModifier *fcm);
|
||||
void ANIM_uiTemplate_fmodifier_draw(struct uiLayout *layout, struct ID *id, ListBase *modifiers, struct FModifier *fcm);
|
||||
|
||||
/* ************************************************* */
|
||||
/* ASSORTED TOOLS */
|
||||
|
||||
@@ -388,7 +388,7 @@ static void graph_panel_modifiers(const bContext *C, Panel *pa)
|
||||
for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next) {
|
||||
col= uiLayoutColumn(pa->layout, 1);
|
||||
|
||||
ANIM_uiTemplate_fmodifier_draw(col, &fcu->modifiers, fcm);
|
||||
ANIM_uiTemplate_fmodifier_draw(col, ale->id, &fcu->modifiers, fcm);
|
||||
}
|
||||
|
||||
MEM_freeN(ale);
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
#include "BKE_report.h"
|
||||
#include "BKE_utildefines.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_view2d.h"
|
||||
|
||||
#include "BIF_transform.h"
|
||||
@@ -1743,6 +1744,34 @@ void GRAPH_OT_smooth (wmOperatorType *ot)
|
||||
|
||||
/* ******************** Add F-Modifier Operator *********************** */
|
||||
|
||||
/* present a special customised popup menu for this, with some filtering */
|
||||
static int graph_fmodifier_add_invoke (bContext *C, wmOperator *op, wmEvent *event)
|
||||
{
|
||||
uiPopupMenu *pup;
|
||||
uiLayout *layout;
|
||||
int i;
|
||||
|
||||
pup= uiPupMenuBegin(C, "Add F-Curve Modifier", 0);
|
||||
layout= uiPupMenuLayout(pup);
|
||||
|
||||
/* start from 1 to skip the 'Invalid' modifier type */
|
||||
for (i = 1; i < FMODIFIER_NUM_TYPES; i++) {
|
||||
FModifierTypeInfo *fmi= get_fmodifier_typeinfo(i);
|
||||
|
||||
/* check if modifier is valid for this context */
|
||||
if (fmi == NULL)
|
||||
continue;
|
||||
|
||||
/* add entry to add this type of modifier */
|
||||
uiItemEnumO(layout, fmi->name, 0, "GRAPH_OT_fmodifier_add", "type", i);
|
||||
}
|
||||
uiItemS(layout);
|
||||
|
||||
uiPupMenuEnd(C, pup);
|
||||
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
static int graph_fmodifier_add_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
bAnimContext ac;
|
||||
@@ -1793,7 +1822,7 @@ void GRAPH_OT_fmodifier_add (wmOperatorType *ot)
|
||||
ot->idname= "GRAPH_OT_fmodifier_add";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke= WM_menu_invoke;
|
||||
ot->invoke= graph_fmodifier_add_invoke;
|
||||
ot->exec= graph_fmodifier_add_exec;
|
||||
ot->poll= graphop_active_fcurve_poll;
|
||||
|
||||
|
||||
@@ -341,7 +341,7 @@ static void nla_panel_modifiers(const bContext *C, Panel *pa)
|
||||
for (fcm= strip->modifiers.first; fcm; fcm= fcm->next) {
|
||||
col= uiLayoutColumn(pa->layout, 1);
|
||||
|
||||
ANIM_uiTemplate_fmodifier_draw(col, &strip->modifiers, fcm);
|
||||
ANIM_uiTemplate_fmodifier_draw(col, strip_ptr.id.data, &strip->modifiers, fcm);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -386,6 +386,12 @@ static int nlaedit_add_transition_exec (bContext *C, wmOperator *op)
|
||||
/* check if there's space between the two */
|
||||
if (IS_EQ(s1->end, s2->start))
|
||||
continue;
|
||||
/* make neither one is a transition
|
||||
* - although this is impossible to create with the standard tools,
|
||||
* the user may have altered the settings
|
||||
*/
|
||||
if (ELEM(NLASTRIP_TYPE_TRANSITION, s1->type, s2->type))
|
||||
continue;
|
||||
|
||||
/* allocate new strip */
|
||||
strip= MEM_callocN(sizeof(NlaStrip), "NlaStrip");
|
||||
@@ -577,8 +583,18 @@ static int nlaedit_delete_exec (bContext *C, wmOperator *op)
|
||||
nstrip= strip->next;
|
||||
|
||||
/* if selected, delete */
|
||||
if (strip->flag & NLASTRIP_FLAG_SELECT)
|
||||
if (strip->flag & NLASTRIP_FLAG_SELECT) {
|
||||
/* if a strip either side of this was a transition, delete those too */
|
||||
if ((strip->prev) && (strip->prev->type == NLASTRIP_TYPE_TRANSITION))
|
||||
free_nlastrip(&nlt->strips, strip->prev);
|
||||
if ((nstrip) && (nstrip->type == NLASTRIP_TYPE_TRANSITION)) {
|
||||
nstrip= nstrip->next;
|
||||
free_nlastrip(&nlt->strips, strip->next);
|
||||
}
|
||||
|
||||
/* finally, delete this strip */
|
||||
free_nlastrip(&nlt->strips, strip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1026,6 +1042,36 @@ void NLA_OT_clear_scale (wmOperatorType *ot)
|
||||
|
||||
/* ******************** Add F-Modifier Operator *********************** */
|
||||
|
||||
/* present a special customised popup menu for this, with some filtering */
|
||||
static int nla_fmodifier_add_invoke (bContext *C, wmOperator *op, wmEvent *event)
|
||||
{
|
||||
uiPopupMenu *pup;
|
||||
uiLayout *layout;
|
||||
int i;
|
||||
|
||||
pup= uiPupMenuBegin(C, "Add F-Modifier", 0);
|
||||
layout= uiPupMenuLayout(pup);
|
||||
|
||||
/* start from 1 to skip the 'Invalid' modifier type */
|
||||
for (i = 1; i < FMODIFIER_NUM_TYPES; i++) {
|
||||
FModifierTypeInfo *fmi= get_fmodifier_typeinfo(i);
|
||||
|
||||
/* check if modifier is valid for this context */
|
||||
if (fmi == NULL)
|
||||
continue;
|
||||
if (i == FMODIFIER_TYPE_CYCLES) /* we already have repeat... */
|
||||
continue;
|
||||
|
||||
/* add entry to add this type of modifier */
|
||||
uiItemEnumO(layout, fmi->name, 0, "NLA_OT_fmodifier_add", "type", i);
|
||||
}
|
||||
uiItemS(layout);
|
||||
|
||||
uiPupMenuEnd(C, pup);
|
||||
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
static int nla_fmodifier_add_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
bAnimContext ac;
|
||||
@@ -1089,7 +1135,7 @@ void NLA_OT_fmodifier_add (wmOperatorType *ot)
|
||||
ot->idname= "NLA_OT_fmodifier_add";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke= WM_menu_invoke;
|
||||
ot->invoke= nla_fmodifier_add_invoke;
|
||||
ot->exec= nla_fmodifier_add_exec;
|
||||
ot->poll= nlaop_poll_tweakmode_off;
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ enum {
|
||||
FMODIFIER_TYPE_FN_GENERATOR,
|
||||
FMODIFIER_TYPE_ENVELOPE,
|
||||
FMODIFIER_TYPE_CYCLES,
|
||||
FMODIFIER_TYPE_NOISE, /* unimplemented - generate variations using some basic noise generator... */
|
||||
FMODIFIER_TYPE_NOISE,
|
||||
FMODIFIER_TYPE_FILTER, /* unimplemented - for applying: fft, high/low pass filters, etc. */
|
||||
FMODIFIER_TYPE_PYTHON,
|
||||
FMODIFIER_TYPE_LIMITS,
|
||||
|
||||
@@ -228,6 +228,7 @@ void rna_def_nlastrip(BlenderRNA *brna)
|
||||
/* Enums */
|
||||
prop= RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "type");
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE); // XXX for now, not editable, since this is dangerous
|
||||
RNA_def_property_enum_items(prop, prop_type_items);
|
||||
RNA_def_property_ui_text(prop, "Type", "Type of NLA Strip.");
|
||||
|
||||
@@ -296,7 +297,10 @@ void rna_def_nlastrip(BlenderRNA *brna)
|
||||
RNA_def_property_range(prop, 0.0001f, 1000.0f); /* these limits can be extended, but beyond this, we can get some crazy+annoying bugs due to numeric errors */
|
||||
RNA_def_property_ui_text(prop, "Scale", "Scaling factor for action.");
|
||||
|
||||
// TODO: strip's F-Curves?
|
||||
/* Strip's F-Curves */
|
||||
prop= RNA_def_property(srna, "fcurves", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "FCurve");
|
||||
RNA_def_property_ui_text(prop, "F-Curves", "F-Curves for controlling the strip's influence and timing.");
|
||||
|
||||
/* Strip's F-Modifiers */
|
||||
prop= RNA_def_property(srna, "modifiers", PROP_COLLECTION, PROP_NONE);
|
||||
|
||||
Reference in New Issue
Block a user