struct ARegion *file_buttons_region(struct ScrArea *sa) { ARegion *ar, *arnew; for(ar= sa->regionbase.first; ar; ar= ar->next) if(ar->regiontype==RGN_TYPE_CHANNELS) return ar; /* add subdiv level; after header */ for(ar= sa->regionbase.first; ar; ar= ar->next) if(ar->regiontype==RGN_TYPE_HEADER) break; /* is error! */ if(ar==NULL) return NULL; arnew= MEM_callocN(sizeof(ARegion), "buttons for file panels"); BLI_insertlinkafter(&sa->regionbase, ar, arnew); arnew->regiontype= RGN_TYPE_CHANNELS; arnew->alignment= RGN_ALIGN_LEFT; arnew->flag = RGN_FLAG_HIDDEN; return arnew; }
static void *ml_addview_cb(void *base, const char *str) { RenderResult *rr = base; RenderView *rv; rv = MEM_callocN(sizeof(RenderView), "new render view"); BLI_strncpy(rv->name, str, EXR_VIEW_MAXNAME); /* For stereo drawing we need to ensure: * STEREO_LEFT_NAME == STEREO_LEFT_ID and * STEREO_RIGHT_NAME == STEREO_RIGHT_ID */ if (STREQ(str, STEREO_LEFT_NAME)) { BLI_addhead(&rr->views, rv); } else if (STREQ(str, STEREO_RIGHT_NAME)) { RenderView *left_rv = BLI_findstring(&rr->views, STEREO_LEFT_NAME, offsetof(RenderView, name)); if (left_rv == NULL) { BLI_addhead(&rr->views, rv); } else { BLI_insertlinkafter(&rr->views, left_rv, rv); } } else { BLI_addtail(&rr->views, rv); } return rv; }
/* Duplicate selected frames from given mask-layer */ void ED_masklayer_frames_duplicate(MaskLayer *masklay) { MaskLayerShape *masklay_shape, *gpfn; /* error checking */ if (masklay == NULL) return; /* duplicate selected frames */ for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = gpfn) { gpfn = masklay_shape->next; /* duplicate this frame */ if (masklay_shape->flag & MASK_SHAPE_SELECT) { MaskLayerShape *mask_shape_dupe; /* duplicate frame, and deselect self */ mask_shape_dupe = BKE_mask_layer_shape_duplicate(masklay_shape); masklay_shape->flag &= ~MASK_SHAPE_SELECT; /* XXX - how to handle duplicate frames? */ BLI_insertlinkafter(&masklay->splines_shapes, masklay_shape, mask_shape_dupe); } } }
/* This uses insertion sort, so NOT ok for large list */ void BLI_sortlist(ListBase *listbase, int (*cmp)(void *, void *)) { Link *current = NULL; Link *previous = NULL; Link *next = NULL; if (cmp == NULL) return; if (listbase == NULL) return; if (listbase->first != listbase->last) { for( previous = listbase->first, current = previous->next; current; current = next ) { next = current->next; previous = current->prev; BLI_remlink(listbase, current); while(previous && cmp(previous, current) == 1) { previous = previous->prev; } BLI_insertlinkafter(listbase, previous, current); } } }
static int mask_layer_move_exec(bContext *C, wmOperator *op) { Mask *mask = CTX_data_edit_mask(C); MaskLayer *mask_layer = BLI_findlink(&mask->masklayers, mask->masklay_act); MaskLayer *mask_layer_other; int direction = RNA_enum_get(op->ptr, "direction"); if (!mask_layer) return OPERATOR_CANCELLED; if (direction == -1) { mask_layer_other = mask_layer->prev; if (!mask_layer_other) return OPERATOR_CANCELLED; BLI_remlink(&mask->masklayers, mask_layer); BLI_insertlinkbefore(&mask->masklayers, mask_layer_other, mask_layer); mask->masklay_act--; } else if (direction == 1) { mask_layer_other = mask_layer->next; if (!mask_layer_other) return OPERATOR_CANCELLED; BLI_remlink(&mask->masklayers, mask_layer); BLI_insertlinkafter(&mask->masklayers, mask_layer_other, mask_layer); mask->masklay_act++; } return OPERATOR_FINISHED; }
static int strip_modifier_move_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); Sequence *seq = BKE_sequencer_active_get(scene); char name[MAX_NAME]; int direction; SequenceModifierData *smd; RNA_string_get(op->ptr, "name", name); direction = RNA_enum_get(op->ptr, "direction"); smd = BKE_sequence_modifier_find_by_name(seq, name); if (!smd) return OPERATOR_CANCELLED; if (direction == SEQ_MODIFIER_MOVE_UP) { if (smd->prev) { BLI_remlink(&seq->modifiers, smd); BLI_insertlinkbefore(&seq->modifiers, smd->prev, smd); } } else if (direction == SEQ_MODIFIER_MOVE_DOWN) { if (smd->next) { BLI_remlink(&seq->modifiers, smd); BLI_insertlinkafter(&seq->modifiers, smd->next, smd); } } BKE_sequence_invalidate_cache(scene, seq); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); return OPERATOR_FINISHED; }
static void move_modifier(ListBase *lb, LineStyleModifier *modifier, int direction) { BLI_remlink(lb, modifier); if (direction > 0) BLI_insertlinkbefore(lb, modifier->prev, modifier); else BLI_insertlinkafter(lb, modifier->next, modifier); }
/* move layer down */ static void gp_ui_layer_down_cb(bContext *C, void *gpd_v, void *gpl_v) { bGPdata *gpd = gpd_v; bGPDlayer *gpl = gpl_v; BLI_remlink(&gpd->layers, gpl); BLI_insertlinkafter(&gpd->layers, gpl->next, gpl); WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); }
int ED_object_gpencil_modifier_move_down(ReportList *UNUSED(reports), Object *ob, GpencilModifierData *md) { if (md->next) { BLI_remlink(&ob->greasepencil_modifiers, md); BLI_insertlinkafter(&ob->greasepencil_modifiers, md->next, md); } return 1; }
static int shape_key_move_exec(bContext *C, wmOperator *op) { Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; int type= RNA_enum_get(op->ptr, "type"); Key *key= ob_get_key(ob); if(key) { KeyBlock *kb, *kb_other; int shapenr_act= ob->shapenr-1; int shapenr_swap= shapenr_act + type; kb= BLI_findlink(&key->block, shapenr_act); if((type==-1 && kb->prev==NULL) || (type==1 && kb->next==NULL)) { return OPERATOR_CANCELLED; } for(kb_other= key->block.first; kb_other; kb_other= kb_other->next) { if(kb_other->relative == shapenr_act) { kb_other->relative += type; } else if(kb_other->relative == shapenr_swap) { kb_other->relative -= type; } } if(type==-1) { /* move back */ kb_other= kb->prev; BLI_remlink(&key->block, kb); BLI_insertlinkbefore(&key->block, kb_other, kb); ob->shapenr--; } else { /* move next */ kb_other= kb->next; BLI_remlink(&key->block, kb); BLI_insertlinkafter(&key->block, kb_other, kb); ob->shapenr++; } } DAG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); return OPERATOR_FINISHED; }
void sca_move_controller(bController *cont_to_move, Object *ob, int move_up) { bController *cont, *tmp; int val; val = move_up ? 1 : 2; /* make sure this controller belongs to this object */ cont= ob->controllers.first; while (cont) { if (cont == cont_to_move) break; cont= cont->next; } if (!cont) return; /* move up */ if (val == 1 && cont->prev) { /* locate the controller that has the same state mask but is earlier in the list */ tmp = cont->prev; while (tmp) { if (tmp->state_mask & cont->state_mask) break; tmp = tmp->prev; } if (tmp) { BLI_remlink(&ob->controllers, cont); BLI_insertlinkbefore(&ob->controllers, tmp, cont); } } /* move down */ else if (val == 2 && cont->next) { tmp = cont->next; while (tmp) { if (tmp->state_mask & cont->state_mask) break; tmp = tmp->next; } BLI_remlink(&ob->controllers, cont); BLI_insertlinkafter(&ob->controllers, tmp, cont); } }
int ED_object_gpencil_modifier_copy(ReportList *reports, Object *ob, GpencilModifierData *md) { GpencilModifierData *nmd; const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type); GpencilModifierType type = md->type; if (mti->flags & eGpencilModifierTypeFlag_Single) { if (BKE_gpencil_modifiers_findByType(ob, type)) { BKE_report(reports, RPT_WARNING, "Only one modifier of this type is allowed"); return 0; } } nmd = BKE_gpencil_modifier_new(md->type); BKE_gpencil_modifier_copyData(md, nmd); BLI_insertlinkafter(&ob->greasepencil_modifiers, md, nmd); BKE_gpencil_modifier_unique_name(&ob->greasepencil_modifiers, nmd); return 1; }
static int constraint_move_down_exec (bContext *C, wmOperator *op) { PointerRNA ptr= CTX_data_pointer_get_type(C, "constraint", &RNA_Constraint); Object *ob= ptr.id.data; bConstraint *con= ptr.data; if (con->next) { ListBase *conlist= get_active_constraints(ob); bConstraint *nextCon= con->next; /* insert the nominated constraint after the one that used to be after it */ BLI_remlink(conlist, con); BLI_insertlinkafter(conlist, nextCon, con); WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT, ob); return OPERATOR_FINISHED; } return OPERATOR_CANCELLED; }
void BLI_listbase_sort_r(ListBase *listbase, void *thunk, int (*cmp)(void *, const void *, const void *)) { Link *current = NULL; Link *previous = NULL; Link *next = NULL; if (listbase->first != listbase->last) { for (previous = listbase->first, current = previous->next; current; current = next) { next = current->next; previous = current->prev; BLI_remlink(listbase, current); while (previous && cmp(thunk, previous, current) == 1) { previous = previous->prev; } BLI_insertlinkafter(listbase, previous, current); } } }
void sca_move_actuator(bActuator *act_to_move, Object *ob, int move_up) { bActuator *act, *tmp; int val; val = move_up ? 1 : 2; /* make sure this actuator belongs to this object */ act= ob->actuators.first; while (act) { if (act == act_to_move) break; act= act->next; } if (!act) return; /* move up */ if (val == 1 && act->prev) { /* locate the first visible actuators before this one */ for (tmp = act->prev; tmp; tmp=tmp->prev) { if (tmp->flag & ACT_VISIBLE) break; } if (tmp) { BLI_remlink(&ob->actuators, act); BLI_insertlinkbefore(&ob->actuators, tmp, act); } } /* move down */ else if (val == 2 && act->next) { /* locate the first visible actuators after this one */ for (tmp=act->next; tmp; tmp=tmp->next) { if (tmp->flag & ACT_VISIBLE) break; } if (tmp) { BLI_remlink(&ob->actuators, act); BLI_insertlinkafter(&ob->actuators, tmp, act); } } }
/* ******************** INTERFACE ******************* */ void sca_move_sensor(bSensor *sens_to_move, Object *ob, int move_up) { bSensor *sens, *tmp; int val; val = move_up ? 1 : 2; /* make sure this sensor belongs to this object */ sens= ob->sensors.first; while (sens) { if (sens == sens_to_move) break; sens= sens->next; } if (!sens) return; /* move up */ if (val == 1 && sens->prev) { for (tmp=sens->prev; tmp; tmp=tmp->prev) { if (tmp->flag & SENS_VISIBLE) break; } if (tmp) { BLI_remlink(&ob->sensors, sens); BLI_insertlinkbefore(&ob->sensors, tmp, sens); } } /* move down */ else if (val == 2 && sens->next) { for (tmp=sens->next; tmp; tmp=tmp->next) { if (tmp->flag & SENS_VISIBLE) break; } if (tmp) { BLI_remlink(&ob->sensors, sens); BLI_insertlinkafter(&ob->sensors, tmp, sens); } } }
static int state_move_down_exec(bContext *C, wmOperator *UNUSED(op)) { PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings); ParticleSettings *part = ptr.data; BoidSettings *boids; BoidState *state; if (!part || part->phystype != PART_PHYS_BOIDS) return OPERATOR_CANCELLED; boids = part->boids; for (state = boids->states.first; state; state=state->next) { if (state->flag & BOIDSTATE_CURRENT && state->next) { BLI_remlink(&boids->states, state); BLI_insertlinkafter(&boids->states, state->next, state); DAG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET); break; } } return OPERATOR_FINISHED; }
static int rule_move_down_exec(bContext *C, wmOperator *UNUSED(op)) { PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings); ParticleSettings *part = ptr.data; BoidRule *rule; BoidState *state; if (!part || part->phystype != PART_PHYS_BOIDS) return OPERATOR_CANCELLED; state = boid_get_current_state(part->boids); for (rule = state->rules.first; rule; rule=rule->next) { if (rule->flag & BOIDRULE_CURRENT && rule->next) { BLI_remlink(&state->rules, rule); BLI_insertlinkafter(&state->rules, rule->next, rule); DAG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET); break; } } return OPERATOR_FINISHED; }
static int target_move_down_exec(bContext *C, wmOperator *UNUSED(op)) { PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); ParticleSystem *psys= ptr.data; Object *ob = ptr.id.data; ParticleTarget *pt; if (!psys) return OPERATOR_CANCELLED; pt = psys->targets.first; for (; pt; pt=pt->next) { if (pt->flag & PTARGET_CURRENT && pt->next) { BLI_remlink(&psys->targets, pt); BLI_insertlinkafter(&psys->targets, pt->next, pt); DAG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob); break; } } return OPERATOR_FINISHED; }
static int dupliob_move_down_exec(bContext *C, wmOperator *UNUSED(op)) { PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); ParticleSystem *psys= ptr.data; ParticleSettings *part; ParticleDupliWeight *dw; if (!psys) return OPERATOR_CANCELLED; part = psys->part; for (dw=part->dupliweights.first; dw; dw=dw->next) { if (dw->flag & PART_DUPLIW_CURRENT && dw->next) { BLI_remlink(&part->dupliweights, dw); BLI_insertlinkafter(&part->dupliweights, dw->next, dw); WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, NULL); break; } } return OPERATOR_FINISHED; }
static ARegion *text_has_properties_region(ScrArea *sa) { ARegion *ar, *arnew; ar = BKE_area_find_region_type(sa, RGN_TYPE_UI); if (ar) return ar; /* add subdiv level; after header */ ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER); /* is error! */ if (ar == NULL) return NULL; arnew = MEM_callocN(sizeof(ARegion), "properties region"); BLI_insertlinkafter(&sa->regionbase, ar, arnew); arnew->regiontype = RGN_TYPE_UI; arnew->alignment = RGN_ALIGN_LEFT; arnew->flag = RGN_FLAG_HIDDEN; return arnew; }
/* Duplicate selected frames from given gp-layer */ void ED_gplayer_frames_duplicate(bGPDlayer *gpl) { bGPDframe *gpf, *gpfn; /* error checking */ if (gpl == NULL) return; /* duplicate selected frames */ for (gpf = gpl->frames.first; gpf; gpf = gpfn) { gpfn = gpf->next; /* duplicate this frame */ if (gpf->flag & GP_FRAME_SELECT) { bGPDframe *gpfd; /* duplicate frame, and deselect self */ gpfd = gpencil_frame_duplicate(gpf); gpf->flag &= ~GP_FRAME_SELECT; BLI_insertlinkafter(&gpl->frames, gpf, gpfd); } } }
static Collection *collection_duplicate_recursive(Main *bmain, Collection *parent, Collection *collection_old, const bool do_hierarchy, const bool do_objects, const bool do_obdata) { Collection *collection_new; bool do_full_process = false; const int object_dupflag = (do_obdata) ? U.dupflag : 0; if (!do_hierarchy || collection_old->id.newid == NULL) { BKE_id_copy(bmain, &collection_old->id, (ID **)&collection_new); id_us_min( &collection_new->id); /* Copying add one user by default, need to get rid of that one. */ if (do_hierarchy) { ID_NEW_SET(collection_old, collection_new); } do_full_process = true; } else { collection_new = (Collection *)collection_old->id.newid; } /* Optionally add to parent (we always want to do that, * even if collection_old had already been duplicated). */ if (parent != NULL) { if (collection_child_add(parent, collection_new, 0, true)) { /* Put collection right after existing one. */ CollectionChild *child = collection_find_child(parent, collection_old); CollectionChild *child_new = collection_find_child(parent, collection_new); if (child && child_new) { BLI_remlink(&parent->children, child_new); BLI_insertlinkafter(&parent->children, child, child_new); } } } /* If we are not doing any kind of deep-copy, we can return immediately. * False do_full_process means collection_old had already been duplicated, * no need to redo some deep-copy on it. */ if (!do_hierarchy || !do_full_process) { return collection_new; } if (do_objects) { /* We can loop on collection_old's objects, that list is currently identical the collection_new * objects, and won't be changed here. */ for (CollectionObject *cob = collection_old->gobject.first; cob; cob = cob->next) { Object *ob_old = cob->ob; Object *ob_new = (Object *)ob_old->id.newid; if (ob_new == NULL) { ob_new = BKE_object_duplicate(bmain, ob_old, object_dupflag); ID_NEW_SET(ob_old, ob_new); } collection_object_add(bmain, collection_new, ob_new, 0, true); collection_object_remove(bmain, collection_new, ob_old, false); } } /* We can loop on collection_old's children, * that list is currently identical the collection_new' children, and won't be changed here. */ for (CollectionChild *child = collection_old->children.first; child; child = child->next) { Collection *child_collection_old = child->collection; collection_duplicate_recursive( bmain, collection_new, child_collection_old, do_hierarchy, do_objects, do_obdata); collection_child_remove(collection_new, child_collection_old); } return collection_new; }
static bool scanfill_preprocess_self_isect( ScanFillContext *sf_ctx, PolyInfo *poly_info, const unsigned short poly_nr, ListBase *filledgebase) { PolyInfo *pi = &poly_info[poly_nr]; GHash *isect_hash = NULL; ListBase isect_lb = {NULL}; /* warning, O(n2) check here, should use spatial lookup */ { ScanFillEdge *eed; for (eed = pi->edge_first; eed; eed = (eed == pi->edge_last) ? NULL : eed->next) { ScanFillEdge *eed_other; for (eed_other = eed->next; eed_other; eed_other = (eed_other == pi->edge_last) ? NULL : eed_other->next) { if (!ELEM(eed->v1, eed_other->v1, eed_other->v2) && !ELEM(eed->v2, eed_other->v1, eed_other->v2) && (eed != eed_other)) { /* check isect */ float pt[2]; BLI_assert(eed != eed_other); if (isect_seg_seg_v2_point(eed->v1->co, eed->v2->co, eed_other->v1->co, eed_other->v2->co, pt) == 1) { ScanFillIsect *isect; if (UNLIKELY(isect_hash == NULL)) { isect_hash = BLI_ghash_ptr_new(__func__); } isect = MEM_mallocN(sizeof(ScanFillIsect), __func__); BLI_addtail(&isect_lb, isect); copy_v2_v2(isect->co, pt); isect->co[2] = eed->v1->co[2]; isect->v = BLI_scanfill_vert_add(sf_ctx, isect->co); isect->v->poly_nr = eed->v1->poly_nr; /* NOTE: vert may belong to 2 polys now */ VFLAG_SET(isect->v, V_ISISECT); edge_isect_ls_add(isect_hash, eed, isect); edge_isect_ls_add(isect_hash, eed_other, isect); } } } } } if (isect_hash == NULL) { return false; } /* now subdiv the edges */ { ScanFillEdge *eed; for (eed = pi->edge_first; eed; eed = (eed == pi->edge_last) ? NULL : eed->next) { if (eed->user_flag & E_ISISECT) { ListBase *e_ls = BLI_ghash_lookup(isect_hash, eed); LinkData *isect_link; /* maintain coorect terminating edge */ if (pi->edge_last == eed) { pi->edge_last = NULL; } if (BLI_listbase_is_single(e_ls) == false) { BLI_sortlist_r(e_ls, eed->v2->co, edge_isect_ls_sort_cb); } /* move original edge to filledgebase and add replacement * (which gets subdivided next) */ { ScanFillEdge *eed_tmp; eed_tmp = BLI_scanfill_edge_add(sf_ctx, eed->v1, eed->v2); BLI_remlink(&sf_ctx->filledgebase, eed_tmp); BLI_insertlinkafter(&sf_ctx->filledgebase, eed, eed_tmp); BLI_remlink(&sf_ctx->filledgebase, eed); BLI_addtail(filledgebase, eed); if (pi->edge_first == eed) { pi->edge_first = eed_tmp; } eed = eed_tmp; } for (isect_link = e_ls->first; isect_link; isect_link = isect_link->next) { ScanFillIsect *isect = isect_link->data; ScanFillEdge *eed_subd; eed_subd = BLI_scanfill_edge_add(sf_ctx, isect->v, eed->v2); eed_subd->poly_nr = poly_nr; eed->v2 = isect->v; BLI_remlink(&sf_ctx->filledgebase, eed_subd); BLI_insertlinkafter(&sf_ctx->filledgebase, eed, eed_subd); /* step to the next edge and continue dividing */ eed = eed_subd; } BLI_freelistN(e_ls); MEM_freeN(e_ls); if (pi->edge_last == NULL) { pi->edge_last = eed; } } } } BLI_freelistN(&isect_lb); BLI_ghash_free(isect_hash, NULL, NULL); { ScanFillEdge *e_init; ScanFillEdge *e_curr; ScanFillEdge *e_next; ScanFillVert *v_prev; ScanFillVert *v_curr; int inside = false; /* first vert */ #if 0 e_init = pi->edge_last; e_curr = e_init; e_next = pi->edge_first; v_prev = e_curr->v1; v_curr = e_curr->v2; #else /* find outside vertex */ { ScanFillEdge *eed; ScanFillEdge *eed_prev; float min_x = FLT_MAX; e_curr = pi->edge_last; e_next = pi->edge_first; eed_prev = pi->edge_last; for (eed = pi->edge_first; eed; eed = (eed == pi->edge_last) ? NULL : eed->next) { if (eed->v2->co[0] < min_x) { min_x = eed->v2->co[0]; e_curr = eed_prev; e_next = eed; } eed_prev = eed; } e_init = e_curr; v_prev = e_curr->v1; v_curr = e_curr->v2; } #endif BLI_assert(e_curr->poly_nr == poly_nr); BLI_assert(pi->edge_last->poly_nr == poly_nr); do { ScanFillVert *v_next; v_next = (e_next->v1 == v_curr) ? e_next->v2 : e_next->v1; BLI_assert(ELEM(v_curr, e_next->v1, e_next->v2)); /* track intersections */ if (inside) { EFLAG_SET(e_next, E_ISDELETE); } if (v_next->user_flag & V_ISISECT) { inside = !inside; } /* now step... */ v_prev = v_curr; v_curr = v_next; e_curr = e_next; e_next = edge_step(poly_info, poly_nr, v_prev, v_curr, e_curr); } while (e_curr != e_init); } return true; }
/* Add given channel into (active) group * - assumes that channel is not linked to anything anymore * - always adds at the end of the group */ void action_groups_add_channel(bAction *act, bActionGroup *agrp, FCurve *fcurve) { /* sanity checks */ if (ELEM(NULL, act, agrp, fcurve)) return; /* if no channels anywhere, just add to two lists at the same time */ if (BLI_listbase_is_empty(&act->curves)) { fcurve->next = fcurve->prev = NULL; agrp->channels.first = agrp->channels.last = fcurve; act->curves.first = act->curves.last = fcurve; } /* if the group already has channels, the F-Curve can simply be added to the list * (i.e. as the last channel in the group) */ else if (agrp->channels.first) { /* if the group's last F-Curve is the action's last F-Curve too, * then set the F-Curve as the last for the action first so that * the lists will be in sync after linking */ if (agrp->channels.last == act->curves.last) act->curves.last = fcurve; /* link in the given F-Curve after the last F-Curve in the group, * which means that it should be able to fit in with the rest of the * list seamlessly */ BLI_insertlinkafter(&agrp->channels, agrp->channels.last, fcurve); } /* otherwise, need to find the nearest F-Curve in group before/after current to link with */ else { bActionGroup *grp; /* firstly, link this F-Curve to the group */ agrp->channels.first = agrp->channels.last = fcurve; /* step through the groups preceding this one, finding the F-Curve there to attach this one after */ for (grp = agrp->prev; grp; grp = grp->prev) { /* if this group has F-Curves, we want weave the given one in right after the last channel there, * but via the Action's list not this group's list * - this is so that the F-Curve is in the right place in the Action, * but won't be included in the previous group */ if (grp->channels.last) { /* once we've added, break here since we don't need to search any further... */ BLI_insertlinkafter(&act->curves, grp->channels.last, fcurve); break; } } /* if grp is NULL, that means we fell through, and this F-Curve should be added as the new first * since group is (effectively) the first group. Thus, the existing first F-Curve becomes the * second in the chain, etc. etc. */ if (grp == NULL) BLI_insertlinkbefore(&act->curves, act->curves.first, fcurve); } /* set the F-Curve's new group */ fcurve->grp = agrp; }