Beispiel #1
0
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);
		}
	}
}
Beispiel #4
0
/* 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);
        }
    }
}
Beispiel #5
0
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;
}
Beispiel #7
0
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);
}
Beispiel #8
0
/* 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;
}
Beispiel #10
0
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;
}
Beispiel #11
0
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;
}
Beispiel #13
0
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;
}
Beispiel #14
0
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);
		}
	}
}
Beispiel #15
0
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);
		}
	}
}
Beispiel #16
0
/* ******************** 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;
}
Beispiel #21
0
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;
}
Beispiel #22
0
/* 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);
		}
	}
}
Beispiel #23
0
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;
}
Beispiel #25
0
/* 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;
}