Exemple #1
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;
}
/* Adds a marker to list of cfra elems */
static void add_marker_to_cfra_elem(ListBase *lb, TimeMarker *marker, short only_sel)
{
	CfraElem *ce, *cen;
	
	/* should this one only be considered if it is selected? */
	if ((only_sel) && ((marker->flag & SELECT) == 0))
		return;
	
	/* insertion sort - try to find a previous cfra elem */
	for (ce = lb->first; ce; ce = ce->next) {
		if (ce->cfra == marker->frame) {
			/* do because of double keys */
			if (marker->flag & SELECT) 
				ce->sel = marker->flag;
			return;
		}
		else if (ce->cfra > marker->frame) {
			break;
		}
	}
	
	cen = MEM_callocN(sizeof(CfraElem), "add_to_cfra_elem");
	if (ce) BLI_insertlinkbefore(lb, ce, cen);
	else BLI_addtail(lb, cen);

	cen->cfra = marker->frame;
	cen->sel = marker->flag;
}
Exemple #4
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);
}
Exemple #5
0
void multiresModifier_join(Object *ob)
{
    Base *base = NULL;
    int highest_lvl = 0;

    /* First find the highest level of subdivision */
    base = FIRSTBASE;
    while(base) {
        if(TESTBASELIB_BGMODE(v3d, base) && base->object->type==OB_MESH) {
            ModifierData *md;
            for(md = base->object->modifiers.first; md; md = md->next) {
                if(md->type == eModifierType_Multires) {
                    int totlvl = ((MultiresModifierData*)md)->totlvl;
                    if(totlvl > highest_lvl)
                        highest_lvl = totlvl;

                    /* Ensure that all updates are processed */
                    multires_force_update(base->object);
                }
            }
        }
        base = base->next;
    }

    /* No multires meshes selected */
    if(highest_lvl == 0)
        return;

    /* Subdivide all the displacements to the highest level */
    base = FIRSTBASE;
    while(base) {
        if(TESTBASELIB_BGMODE(v3d, base) && base->object->type==OB_MESH) {
            ModifierData *md = NULL;
            MultiresModifierData *mmd = NULL;

            for(md = base->object->modifiers.first; md; md = md->next) {
                if(md->type == eModifierType_Multires)
                    mmd = (MultiresModifierData*)md;
            }

            /* If the object didn't have multires enabled, give it a new modifier */
            if(!mmd) {
                md = base->object->modifiers.first;

                while(md && modifierType_getInfo(md->type)->type == eModifierTypeType_OnlyDeform)
                    md = md->next;

                mmd = (MultiresModifierData*)modifier_new(eModifierType_Multires);
                BLI_insertlinkbefore(&base->object->modifiers, md, mmd);
                modifier_unique_name(&base->object->modifiers, mmd);
            }

            if(mmd)
                multiresModifier_subdivide(mmd, base->object, highest_lvl - mmd->totlvl, 0, 0);
        }
        base = base->next;
    }
}
Exemple #6
0
/* move layer up */
static void gp_ui_layer_up_cb(bContext *C, void *gpd_v, void *gpl_v)
{
	bGPdata *gpd = gpd_v;
	bGPDlayer *gpl = gpl_v;
	
	BLI_remlink(&gpd->layers, gpl);
	BLI_insertlinkbefore(&gpd->layers, gpl->prev, gpl);
	
	WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
}
int ED_object_gpencil_modifier_move_up(ReportList *UNUSED(reports),
                                       Object *ob,
                                       GpencilModifierData *md)
{
  if (md->prev) {
    BLI_remlink(&ob->greasepencil_modifiers, md);
    BLI_insertlinkbefore(&ob->greasepencil_modifiers, md->prev, md);
  }

  return 1;
}
Exemple #8
0
static bool addedgetoscanvert(ScanFillVertLink *sc, ScanFillEdge *eed)
{
  /* find first edge to the right of eed, and insert eed before that */
  ScanFillEdge *ed;
  float fac, fac1, x, y;

  if (sc->edge_first == NULL) {
    sc->edge_first = sc->edge_last = eed;
    eed->prev = eed->next = NULL;
    return 1;
  }

  x = eed->v1->xy[0];
  y = eed->v1->xy[1];

  fac1 = eed->v2->xy[1] - y;
  if (fac1 == 0.0f) {
    fac1 = 1.0e10f * (eed->v2->xy[0] - x);
  }
  else {
    fac1 = (x - eed->v2->xy[0]) / fac1;
  }

  for (ed = sc->edge_first; ed; ed = ed->next) {

    if (ed->v2 == eed->v2) {
      return false;
    }

    fac = ed->v2->xy[1] - y;
    if (fac == 0.0f) {
      fac = 1.0e10f * (ed->v2->xy[0] - x);
    }
    else {
      fac = (x - ed->v2->xy[0]) / fac;
    }

    if (fac > fac1) {
      break;
    }
  }
  if (ed) {
    BLI_insertlinkbefore((ListBase *)&(sc->edge_first), ed, eed);
  }
  else {
    BLI_addtail((ListBase *)&(sc->edge_first), eed);
  }

  return true;
}
Exemple #9
0
/* add a new gp-frame to the given layer */
bGPDframe *gpencil_frame_addnew(bGPDlayer *gpl, int cframe)
{
    bGPDframe *gpf = NULL, *gf = NULL;
    short state = 0;

    /* error checking (neg frame only if they are not allowed in Blender!) */
    if (gpl == NULL)
        return NULL;

    /* allocate memory for this frame */
    gpf = MEM_callocN(sizeof(bGPDframe), "bGPDframe");
    gpf->framenum = cframe;

    /* find appropriate place to add frame */
    if (gpl->frames.first) {
        for (gf = gpl->frames.first; gf; gf = gf->next) {
            /* check if frame matches one that is supposed to be added */
            if (gf->framenum == cframe) {
                state = -1;
                break;
            }

            /* if current frame has already exceeded the frame to add, add before */
            if (gf->framenum > cframe) {
                BLI_insertlinkbefore(&gpl->frames, gf, gpf);
                state = 1;
                break;
            }
        }
    }

    /* check whether frame was added successfully */
    if (state == -1) {
        printf("Error: Frame (%d) existed already for this layer. Using existing frame\n", cframe);

        /* free the newly created one, and use the old one instead */
        MEM_freeN(gpf);

        /* return existing frame instead... */
        BLI_assert(gf != NULL);
        gpf = gf;
    }
    else if (state == 0) {
        /* add to end then! */
        BLI_addtail(&gpl->frames, gpf);
    }

    /* return frame */
    return gpf;
}
Exemple #10
0
static void verify_socket_template_list(bNodeTree *ntree, bNode *node, int in_out, ListBase *socklist, bNodeSocketTemplate *stemp_first)
{
	bNodeSocket *sock;
	bNodeSocketTemplate *stemp;
	
	/* no inputs anymore? */
	if(stemp_first==NULL) {
		while(socklist->first) {
			sock = (bNodeSocket*)socklist->first;
			if (!(sock->flag & SOCK_DYNAMIC))
				nodeRemoveSocket(ntree, node, socklist->first);
		}
	}
	else {
		/* step by step compare */
		stemp= stemp_first;
		while(stemp->type != -1) {
			stemp->sock= verify_socket_template(ntree, node, in_out, socklist, stemp);
			stemp++;
		}
		/* leftovers are removed */
		while(socklist->first) {
			sock = (bNodeSocket*)socklist->first;
			if (!(sock->flag & SOCK_DYNAMIC))
				nodeRemoveSocket(ntree, node, socklist->first);
		}
		
		/* and we put back the verified sockets */
		stemp= stemp_first;
		if (socklist->first) {
			/* some dynamic sockets left, store the list start
			 * so we can add static sockets infront of it.
			 */
			sock = socklist->first;
			while(stemp->type != -1) {
				/* put static sockets infront of dynamic */
				BLI_insertlinkbefore(socklist, sock, stemp->sock);
				stemp++;
			}
		}
		else {
			while(stemp->type != -1) {
				BLI_addtail(socklist, stemp->sock);
				stemp++;
			}
		}
	}
}
Exemple #11
0
static void add_hook_object(Main *bmain, Scene *scene, Object *obedit, Object *ob, int mode)
{
	ModifierData *md=NULL;
	HookModifierData *hmd = NULL;
	float cent[3];
	int tot, ok, *indexar;
	char name[32];
	
	ok = object_hook_index_array(obedit, &tot, &indexar, name, cent);
	
	if (!ok) return;	// XXX error("Requires selected vertices or active Vertex Group");
	
	if (mode==OBJECT_ADDHOOK_NEWOB && !ob) {
		
		ob = add_hook_object_new(scene, obedit);
		
		/* transform cent to global coords for loc */
		mul_v3_m4v3(ob->loc, obedit->obmat, cent);
	}
	
	md = obedit->modifiers.first;
	while (md && modifierType_getInfo(md->type)->type==eModifierTypeType_OnlyDeform) {
		md = md->next;
	}
	
	hmd = (HookModifierData*) modifier_new(eModifierType_Hook);
	BLI_insertlinkbefore(&obedit->modifiers, md, hmd);
	BLI_snprintf(hmd->modifier.name, sizeof(hmd->modifier.name), "Hook-%s", ob->id.name+2);
	modifier_unique_name(&obedit->modifiers, (ModifierData*)hmd);
	
	hmd->object= ob;
	hmd->indexar= indexar;
	copy_v3_v3(hmd->cent, cent);
	hmd->totindex= tot;
	BLI_strncpy(hmd->name, name, sizeof(hmd->name));
	
	/* matrix calculus */
	/* vert x (obmat x hook->imat) x hook->obmat x ob->imat */
	/*        (parentinv         )                          */
	where_is_object(scene, ob);
	
	invert_m4_m4(ob->imat, ob->obmat);
	/* apparently this call goes from right to left... */
	mul_serie_m4(hmd->parentinv, ob->imat, obedit->obmat, NULL, 
				 NULL, NULL, NULL, NULL, NULL);
	
	DAG_scene_sort(bmain, scene);
}
Exemple #12
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;
}
Exemple #13
0
static void voronoi_insertEvent(VoronoiProcess *process, VoronoiEvent *event)
{
  VoronoiEvent *current_event = process->queue.first;

  while (current_event) {
    if (current_event->site[1] < event->site[1]) {
      break;
    }
    if (current_event->site[1] == event->site[1]) {
      event->site[1] -= VORONOI_EPS;
    }

    current_event = current_event->next;
  }

  BLI_insertlinkbefore(&process->queue, current_event, event);
}
Exemple #14
0
/* add a new gp-frame to the given layer */
bGPDframe *gpencil_frame_addnew(bGPDlayer *gpl, int cframe)
{
	bGPDframe *gpf, *gf;
	short state = 0;
	
	/* error checking */
	if ((gpl == NULL) || (cframe <= 0))
		return NULL;
		
	/* allocate memory for this frame */
	gpf = MEM_callocN(sizeof(bGPDframe), "bGPDframe");
	gpf->framenum = cframe;
	
	/* find appropriate place to add frame */
	if (gpl->frames.first) {
		for (gf = gpl->frames.first; gf; gf = gf->next) {
			/* check if frame matches one that is supposed to be added */
			if (gf->framenum == cframe) {
				state = -1;
				break;
			}
			
			/* if current frame has already exceeded the frame to add, add before */
			if (gf->framenum > cframe) {
				BLI_insertlinkbefore(&gpl->frames, gf, gpf);
				state = 1;
				break;
			}
		}
	}
	
	/* check whether frame was added successfully */
	if (state == -1) {
		MEM_freeN(gpf);
		printf("Error: frame (%d) existed already for this layer\n", cframe);
	}
	else if (state == 0) {
		/* add to end then! */
		BLI_addtail(&gpl->frames, gpf);
	}
	
	/* return frame */
	return gpf;
}
Exemple #15
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);
	}
}
Exemple #16
0
static short addedgetoscanvert(ScFillVert *sc, EditEdge *eed)
{
	/* find first edge to the right of eed, and insert eed before that */
	EditEdge *ed;
	float fac,fac1,x,y;

	if(sc->first==0) {
		sc->first= sc->last= eed;
		eed->prev= eed->next=0;
		return 1;
	}

	x= eed->v1->co[cox];
	y= eed->v1->co[coy];

	fac1= eed->v2->co[coy]-y;
	if(fac1==0.0) {
		fac1= 1.0e10*(eed->v2->co[cox]-x);

	}
	else fac1= (x-eed->v2->co[cox])/fac1;

	ed= sc->first;
	while(ed) {

		if(ed->v2==eed->v2) return 0;

		fac= ed->v2->co[coy]-y;
		if(fac==0.0) {
			fac= 1.0e10*(ed->v2->co[cox]-x);

		}
		else fac= (x-ed->v2->co[cox])/fac;
		if(fac>fac1) break;

		ed= ed->next;
	}
	if(ed) BLI_insertlinkbefore((ListBase *)&(sc->first), ed, eed);
	else BLI_addtail((ListBase *)&(sc->first),eed);

	return 1;
}
Exemple #17
0
static void wm_keymap_patch(wmKeyMap *km, wmKeyMap *diff_km)
{
	wmKeyMapDiffItem *kmdi;
	wmKeyMapItem *kmi_remove, *kmi_add;

	for(kmdi=diff_km->diff_items.first; kmdi; kmdi=kmdi->next) {
		/* find item to remove */
		kmi_remove = NULL;
		if(kmdi->remove_item) {
			kmi_remove = wm_keymap_find_item_equals(km, kmdi->remove_item);
			if(!kmi_remove)
				kmi_remove = wm_keymap_find_item_equals_result(km, kmdi->remove_item);
		}

		/* add item */
		if(kmdi->add_item) {
			/* only if nothing to remove or item to remove found */
			if(!kmdi->remove_item || kmi_remove) {
				kmi_add = wm_keymap_item_copy(kmdi->add_item);
				kmi_add->flag |= KMI_USER_MODIFIED;

				if(kmi_remove) {
					kmi_add->flag &= ~KMI_EXPANDED;
					kmi_add->flag |= (kmi_remove->flag & KMI_EXPANDED);
					kmi_add->id = kmi_remove->id;
					BLI_insertlinkbefore(&km->items, kmi_remove, kmi_add);
				}
				else {
					keymap_item_set_id(km, kmi_add);
					BLI_addtail(&km->items, kmi_add);
				}
			}
		}

		/* remove item */
		if(kmi_remove) {
			wm_keymap_item_free(kmi_remove);
			BLI_freelinkN(&km->items, kmi_remove);
		}
	}
}
Exemple #18
0
static int constraint_move_up_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->prev) {
		ListBase *conlist= get_active_constraints(ob);
		bConstraint *prevCon= con->prev;
		
		/* insert the nominated constraint before the one that used to be before it */
		BLI_remlink(conlist, con);
		BLI_insertlinkbefore(conlist, prevCon, con);
		
		WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT, ob);
		
		return OPERATOR_FINISHED;
	}
	
	return OPERATOR_CANCELLED;
}
Exemple #19
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);
		}
	}
}
/************************ move up/down boid state operators *********************/
static int state_move_up_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->prev) {
			BLI_remlink(&boids->states, state);
			BLI_insertlinkbefore(&boids->states, state->prev, state);
			break;
		}
	}
	
	return OPERATOR_FINISHED;
}
Exemple #21
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);
		}
	}
}
Exemple #22
0
static void sort_alpha_id(ListBase *lb, ID *id)
{
	ID *idtest;
	
	/* insert alphabetically */
	if(lb->first!=lb->last) {
		BLI_remlink(lb, id);
		
		idtest= lb->first;
		while(idtest) {
			if(BLI_strcasecmp(idtest->name, id->name)>0 || idtest->lib) {
				BLI_insertlinkbefore(lb, idtest, id);
				break;
			}
			idtest= idtest->next;
		}
		/* as last */
		if(idtest==NULL) {
			BLI_addtail(lb, id);
		}
	}
	
}
static int dupliob_move_up_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->prev) {
			BLI_remlink(&part->dupliweights, dw);
			BLI_insertlinkbefore(&part->dupliweights, dw->prev, dw);

			WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, NULL);
			break;
		}
	}
	
	return OPERATOR_FINISHED;
}
/************************ move up/down boid rule operators *********************/
static int rule_move_up_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->prev) {
			BLI_remlink(&state->rules, rule);
			BLI_insertlinkbefore(&state->rules, rule->prev, rule);

			DAG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET);
			break;
		}
	}
	
	return OPERATOR_FINISHED;
}
static int target_move_up_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->prev) {
			BLI_remlink(&psys->targets, pt);
			BLI_insertlinkbefore(&psys->targets, pt->prev, pt);

			DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
			WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
			break;
		}
	}
	
	return OPERATOR_FINISHED;
}
ModifierData *ED_object_modifier_add(ReportList *reports, Main *bmain, Scene *scene, Object *ob, const char *name, int type)
{
	ModifierData *md=NULL, *new_md=NULL;
	ModifierTypeInfo *mti = modifierType_getInfo(type);
	
	/* only geometry objects should be able to get modifiers [#25291] */
	if(!ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) {
		BKE_reportf(reports, RPT_WARNING, "Modifiers cannot be added to Object '%s'", ob->id.name+2);
		return NULL;
	}
	
	if(mti->flags&eModifierTypeFlag_Single) {
		if(modifiers_findByType(ob, type)) {
			BKE_report(reports, RPT_WARNING, "Only one modifier of this type allowed");
			return NULL;
		}
	}
	
	if(type == eModifierType_ParticleSystem) {
		/* don't need to worry about the new modifier's name, since that is set to the number
		 * of particle systems which shouldn't have too many duplicates 
		 */
		new_md = object_add_particle_system(scene, ob, name);
	}
	else {
		/* get new modifier data to add */
		new_md= modifier_new(type);
		
		if(mti->flags&eModifierTypeFlag_RequiresOriginalData) {
			md = ob->modifiers.first;
			
			while(md && modifierType_getInfo(md->type)->type==eModifierTypeType_OnlyDeform)
				md = md->next;
			
			BLI_insertlinkbefore(&ob->modifiers, md, new_md);
		}
		else
			BLI_addtail(&ob->modifiers, new_md);

		if(name)
			BLI_strncpy(new_md->name, name, sizeof(new_md->name));

		/* make sure modifier data has unique name */

		modifier_unique_name(&ob->modifiers, new_md);
		
		/* special cases */
		if(type == eModifierType_Softbody) {
			if(!ob->soft) {
				ob->soft= sbNew(scene);
				ob->softflag |= OB_SB_GOAL|OB_SB_EDGES;
			}
		}
		else if(type == eModifierType_Collision) {
			if(!ob->pd)
				ob->pd= object_add_collision_fields(0);
			
			ob->pd->deflect= 1;
			DAG_scene_sort(bmain, scene);
		}
		else if(type == eModifierType_Surface)
			DAG_scene_sort(bmain, scene);
		else if(type == eModifierType_Multires)
			/* set totlvl from existing MDISPS layer if object already had it */
			multiresModifier_set_levels_from_disps((MultiresModifierData *)new_md, ob);
	}

	DAG_id_tag_update(&ob->id, OB_RECALC_DATA);

	return new_md;
}
static void loop_sync(bNodeTree *ntree, int sync_in_out)
{
	bNodeSocket *sock, *sync, *nsync, *mirror;
	ListBase *sync_lb;
	
	if (sync_in_out==SOCK_IN) {
		sock = ntree->outputs.first;
		
		sync = ntree->inputs.first;
		sync_lb = &ntree->inputs;
	}
	else {
		sock = ntree->inputs.first;
		
		sync = ntree->outputs.first;
		sync_lb = &ntree->outputs;
	}
	
	/* NB: the sock->storage pointer is used here directly to store the own_index int
	 * out the mirrored socket counterpart!
	 */
	
	while (sock) {
		/* skip static and internal sockets on the sync side (preserves socket order!) */
		while (sync && ((sync->flag & SOCK_INTERNAL) || !(sync->flag & SOCK_DYNAMIC)))
			sync = sync->next;
		
		if (sync && !(sync->flag & SOCK_INTERNAL) && (sync->flag & SOCK_DYNAMIC)) {
			if (sock->storage==NULL) {
				/* if mirror index is 0, the sockets is newly added and a new mirror must be created. */
				mirror = node_group_expose_socket(ntree, sock, sync_in_out);
				/* store the mirror index */
				sock->storage = SET_INT_IN_POINTER(mirror->own_index);
				mirror->storage = SET_INT_IN_POINTER(sock->own_index);
				/* move mirror to the right place */
				BLI_remlink(sync_lb, mirror);
				if (sync)
					BLI_insertlinkbefore(sync_lb, sync, mirror);
				else
					BLI_addtail(sync_lb, mirror);
			}
			else {
				/* look up the mirror socket */
				for (mirror=sync; mirror; mirror=mirror->next)
					if (mirror->own_index == GET_INT_FROM_POINTER(sock->storage))
						break;
				/* make sure the name is the same (only for identification by user, no deeper meaning) */
				BLI_strncpy(mirror->name, sock->name, sizeof(mirror->name));
				/* fix the socket order if necessary */
				if (mirror != sync) {
					BLI_remlink(sync_lb, mirror);
					BLI_insertlinkbefore(sync_lb, sync, mirror);
				}
				else
					sync = sync->next;
			}
		}
		
		sock = sock->next;
	}
	
	/* remaining sockets in sync_lb are leftovers from deleted sockets, remove them */
	while (sync) {
		nsync = sync->next;
		if (!(sync->flag & SOCK_INTERNAL) && (sync->flag & SOCK_DYNAMIC))
			node_group_remove_socket(ntree, sync, sync_in_out);
		sync = nsync;
	}
}
Exemple #28
0
static void scanfill(PolyFill *pf, int mat_nr)
{
	ScFillVert *sc = NULL, *sc1;
	EditVert *eve,*v1,*v2,*v3;
	EditEdge *eed,*nexted,*ed1,*ed2,*ed3;
	float miny = 0.0;
	int a,b,verts, maxface, totface;	
	short nr, test, twoconnected=0;

	nr= pf->nr;

	/* PRINTS
	verts= pf->verts;
	eve= fillvertbase.first;
	while(eve) {
		printf("vert: %x co: %f %f\n",eve,eve->co[cox],eve->co[coy]);
		eve= eve->next;
	}	
	eed= filledgebase.first;
	while(eed) {
		printf("edge: %x  verts: %x %x\n",eed,eed->v1,eed->v2);
		eed= eed->next;
	} */

	/* STEP 0: remove zero sized edges */
	eed= filledgebase.first;
	while(eed) {
		if(eed->v1->co[cox]==eed->v2->co[cox]) {
			if(eed->v1->co[coy]==eed->v2->co[coy]) {
				if(eed->v1->f==255 && eed->v2->f!=255) {
					eed->v2->f= 255;
					eed->v2->tmp.v= eed->v1->tmp.v;
				}
				else if(eed->v2->f==255 && eed->v1->f!=255) {
					eed->v1->f= 255;
					eed->v1->tmp.v= eed->v2->tmp.v;
				}
				else if(eed->v2->f==255 && eed->v1->f==255) {
					eed->v1->tmp.v= eed->v2->tmp.v;
				}
				else {
					eed->v2->f= 255;
					eed->v2->tmp.v = eed->v1->tmp.v;
				}
			}
		}
		eed= eed->next;
	}

	/* STEP 1: make using FillVert and FillEdge lists a sorted
		ScFillVert list
	*/
	sc= scdata= (ScFillVert *)MEM_callocN(pf->verts*sizeof(ScFillVert),"Scanfill1");
	eve= fillvertbase.first;
	verts= 0;
	while(eve) {
		if(eve->xs==nr) {
			if(eve->f!= 255) {
				verts++;
				eve->f= 0;	/* flag for connectedges later on */
				sc->v1= eve;
				sc++;
			}
		}
		eve= eve->next;
	}

	qsort(scdata, verts, sizeof(ScFillVert), vergscdata);

	eed= filledgebase.first;
	while(eed) {
		nexted= eed->next;
		eed->f= 0;
		BLI_remlink(&filledgebase,eed);
/* commented all of this out, this I have no idea for what it is for, probably from ancient past */
/* it does crash blender, since it uses mixed original and new vertices (ton) */
//		if(eed->v1->f==255) {
//			v1= eed->v1;
//			while((eed->v1->f == 255) && (eed->v1->tmp.v != v1)) 
//				eed->v1 = eed->v1->tmp.v;
//		}
//		if(eed->v2->f==255) {
//			v2= eed->v2;
//			while((eed->v2->f == 255) && (eed->v2->tmp.v != v2))
//				eed->v2 = eed->v2->tmp.v;
//		}
		if(eed->v1!=eed->v2) addedgetoscanlist(eed,verts);

		eed= nexted;
	}
	/*
	sc= scdata;
	for(a=0;a<verts;a++) {
		printf("\nscvert: %x\n",sc->v1);
		eed= sc->first;
		while(eed) {
			printf(" ed %x %x %x\n",eed,eed->v1,eed->v2);
			eed= eed->next;
		}
		sc++;
	}*/


	/* STEP 2: FILL LOOP */

	if(pf->f==0) twoconnected= 1;

	/* (temporal) security: never much more faces than vertices */
	totface= 0;
	maxface= 2*verts;		/* 2*verts: based at a filled circle within a triangle */

	sc= scdata;
	for(a=0;a<verts;a++) {
		/* printf("VERTEX %d %x\n",a,sc->v1); */
		ed1= sc->first;
		while(ed1) {	/* set connectflags  */
			nexted= ed1->next;
			if(ed1->v1->h==1 || ed1->v2->h==1) {
				BLI_remlink((ListBase *)&(sc->first),ed1);
				BLI_addtail(&filledgebase,ed1);
				if(ed1->v1->h>1) ed1->v1->h--;
				if(ed1->v2->h>1) ed1->v2->h--;
			}
			else ed1->v2->f= 1;

			ed1= nexted;
		}
		while(sc->first) {	/* for as long there are edges */
			ed1= sc->first;
			ed2= ed1->next;
			
			/* commented out... the ESC here delivers corrupted memory (and doesnt work during grab) */
			/* if(callLocalInterruptCallBack()) break; */
			if(totface>maxface) {
				/* printf("Fill error: endless loop. Escaped at vert %d,  tot: %d.\n", a, verts); */
				a= verts;
				break;
			}
			if(ed2==0) {
				sc->first=sc->last= 0;
				/* printf("just 1 edge to vert\n"); */
				BLI_addtail(&filledgebase,ed1);
				ed1->v2->f= 0;
				ed1->v1->h--; 
				ed1->v2->h--;
			} else {
				/* test rest of vertices */
				v1= ed1->v2;
				v2= ed1->v1;
				v3= ed2->v2;
				/* this happens with a serial of overlapping edges */
				if(v1==v2 || v2==v3) break;
				/* printf("test verts %x %x %x\n",v1,v2,v3); */
				miny = ( (v1->co[coy])<(v3->co[coy]) ? (v1->co[coy]) : (v3->co[coy]) );
				/*  miny= MIN2(v1->co[coy],v3->co[coy]); */
				sc1= sc+1;
				test= 0;

				for(b=a+1;b<verts;b++) {
					if(sc1->v1->f==0) {
						if(sc1->v1->co[coy] <= miny) break;

						if(testedgeside(v1->co,v2->co,sc1->v1->co))
							if(testedgeside(v2->co,v3->co,sc1->v1->co))
								if(testedgeside(v3->co,v1->co,sc1->v1->co)) {
									/* point in triangle */
								
									test= 1;
									break;
								}
					}
					sc1++;
				}
				if(test) {
					/* make new edge, and start over */
					/* printf("add new edge %x %x and start again\n",v2,sc1->v1); */

					ed3= BLI_addfilledge(v2, sc1->v1);
					BLI_remlink(&filledgebase, ed3);
					BLI_insertlinkbefore((ListBase *)&(sc->first), ed2, ed3);
					ed3->v2->f= 1;
					ed3->f= 2;
					ed3->v1->h++; 
					ed3->v2->h++;
				}
				else {
					/* new triangle */
					/* printf("add face %x %x %x\n",v1,v2,v3); */
					addfillface(v1, v2, v3, mat_nr);
					totface++;
					BLI_remlink((ListBase *)&(sc->first),ed1);
					BLI_addtail(&filledgebase,ed1);
					ed1->v2->f= 0;
					ed1->v1->h--; 
					ed1->v2->h--;
					/* ed2 can be removed when it's an old one */
					if(ed2->f==0 && twoconnected) {
						BLI_remlink((ListBase *)&(sc->first),ed2);
						BLI_addtail(&filledgebase,ed2);
						ed2->v2->f= 0;
						ed2->v1->h--; 
						ed2->v2->h--;
					}

					/* new edge */
					ed3= BLI_addfilledge(v1, v3);
					BLI_remlink(&filledgebase, ed3);
					ed3->f= 2;
					ed3->v1->h++; 
					ed3->v2->h++;
					
					/* printf("add new edge %x %x\n",v1,v3); */
					sc1= addedgetoscanlist(ed3, verts);
					
					if(sc1) {	/* ed3 already exists: remove */
						/* printf("Edge exists\n"); */
						ed3->v1->h--; 
						ed3->v2->h--;

						if(twoconnected) ed3= sc1->first;
						else ed3= 0;
						while(ed3) {
							if( (ed3->v1==v1 && ed3->v2==v3) || (ed3->v1==v3 && ed3->v2==v1) ) {
								BLI_remlink((ListBase *)&(sc1->first),ed3);
								BLI_addtail(&filledgebase,ed3);
								ed3->v1->h--; 
								ed3->v2->h--;
								break;
							}
							ed3= ed3->next;
						}
					}

				}
			}
			/* test for loose edges */
			ed1= sc->first;
			while(ed1) {
				nexted= ed1->next;
				if(ed1->v1->h<2 || ed1->v2->h<2) {
					BLI_remlink((ListBase *)&(sc->first),ed1);
					BLI_addtail(&filledgebase,ed1);
					if(ed1->v1->h>1) ed1->v1->h--;
					if(ed1->v2->h>1) ed1->v2->h--;
				}

				ed1= nexted;
			}
		}
		sc++;
	}

	MEM_freeN(scdata);
}
Exemple #29
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;
}	
Exemple #30
0
static unsigned int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int flag)
{
	ScanFillVertLink *scdata;
	ScanFillVertLink *sc = NULL, *sc1;
	ScanFillVert *eve, *v1, *v2, *v3;
	ScanFillEdge *eed, *eed_next, *ed1, *ed2, *ed3;
	unsigned int a, b, verts, maxface, totface;
	const unsigned short nr = pf->nr;
	bool twoconnected = false;

	/* PRINTS */
#if 0
	verts = pf->verts;
	for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) {
		printf("vert: %x co: %f %f\n", eve, eve->xy[0], eve->xy[1]);
	}

	for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) {
		printf("edge: %x  verts: %x %x\n", eed, eed->v1, eed->v2);
	}
#endif

	/* STEP 0: remove zero sized edges */
	if (flag & BLI_SCANFILL_CALC_REMOVE_DOUBLES) {
		for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) {
			if (equals_v2v2(eed->v1->xy, eed->v2->xy)) {
				if (eed->v1->f == SF_VERT_ZERO_LEN && eed->v2->f != SF_VERT_ZERO_LEN) {
					eed->v2->f = SF_VERT_ZERO_LEN;
					eed->v2->tmp.v = eed->v1->tmp.v;
				}
				else if (eed->v2->f == SF_VERT_ZERO_LEN && eed->v1->f != SF_VERT_ZERO_LEN) {
					eed->v1->f = SF_VERT_ZERO_LEN;
					eed->v1->tmp.v = eed->v2->tmp.v;
				}
				else if (eed->v2->f == SF_VERT_ZERO_LEN && eed->v1->f == SF_VERT_ZERO_LEN) {
					eed->v1->tmp.v = eed->v2->tmp.v;
				}
				else {
					eed->v2->f = SF_VERT_ZERO_LEN;
					eed->v2->tmp.v = eed->v1;
				}
			}
		}
	}

	/* STEP 1: make using FillVert and FillEdge lists a sorted
	 * ScanFillVertLink list
	 */
	sc = scdata = MEM_mallocN(sizeof(*scdata) * pf->verts, "Scanfill1");
	verts = 0;
	for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) {
		if (eve->poly_nr == nr) {
			if (eve->f != SF_VERT_ZERO_LEN) {
				verts++;
				eve->f = SF_VERT_NEW;  /* flag for connectedges later on */
				sc->vert = eve;
				sc->edge_first = sc->edge_last = NULL;
				/* if (even->tmp.v == NULL) eve->tmp.u = verts; */ /* Note, debug print only will work for curve polyfill, union is in use for mesh */
				sc++;
			}
		}
	}

	qsort(scdata, verts, sizeof(ScanFillVertLink), vergscdata);

	if (flag & BLI_SCANFILL_CALC_REMOVE_DOUBLES) {
		for (eed = sf_ctx->filledgebase.first; eed; eed = eed_next) {
			eed_next = eed->next;
			BLI_remlink(&sf_ctx->filledgebase, eed);
			/* This code is for handling zero-length edges that get
			 * collapsed in step 0. It was removed for some time to
			 * fix trunk bug #4544, so if that comes back, this code
			 * may need some work, or there will have to be a better
			 * fix to #4544.
			 *
			 * warning, this can hang on un-ordered edges, see: [#33281]
			 * for now disable 'BLI_SCANFILL_CALC_REMOVE_DOUBLES' for ngons.
			 */
			if (eed->v1->f == SF_VERT_ZERO_LEN) {
				v1 = eed->v1;
				while ((eed->v1->f == SF_VERT_ZERO_LEN) && (eed->v1->tmp.v != v1) && (eed->v1 != eed->v1->tmp.v))
					eed->v1 = eed->v1->tmp.v;
			}
			if (eed->v2->f == SF_VERT_ZERO_LEN) {
				v2 = eed->v2;
				while ((eed->v2->f == SF_VERT_ZERO_LEN) && (eed->v2->tmp.v != v2) && (eed->v2 != eed->v2->tmp.v))
					eed->v2 = eed->v2->tmp.v;
			}
			if (eed->v1 != eed->v2) {
				addedgetoscanlist(scdata, eed, verts);
			}
		}
	}
	else {
		for (eed = sf_ctx->filledgebase.first; eed; eed = eed_next) {
			eed_next = eed->next;
			BLI_remlink(&sf_ctx->filledgebase, eed);
			if (eed->v1 != eed->v2) {
				addedgetoscanlist(scdata, eed, verts);
			}
		}
	}
#if 0
	sc = sf_ctx->_scdata;
	for (a = 0; a < verts; a++) {
		printf("\nscvert: %x\n", sc->vert);
		for (eed = sc->edge_first; eed; eed = eed->next) {
			printf(" ed %x %x %x\n", eed, eed->v1, eed->v2);
		}
		sc++;
	}
#endif


	/* STEP 2: FILL LOOP */

	if (pf->f == SF_POLY_NEW)
		twoconnected = true;

	/* (temporal) security: never much more faces than vertices */
	totface = 0;
	if (flag & BLI_SCANFILL_CALC_HOLES) {
		maxface = 2 * verts;       /* 2*verts: based at a filled circle within a triangle */
	}
	else {
		maxface = verts - 2;       /* when we don't calc any holes, we assume face is a non overlapping loop */
	}

	sc = scdata;
	for (a = 0; a < verts; a++) {
		/* printf("VERTEX %d index %d\n", a, sc->vert->tmp.u); */
		/* set connectflags  */
		for (ed1 = sc->edge_first; ed1; ed1 = eed_next) {
			eed_next = ed1->next;
			if (ed1->v1->edge_tot == 1 || ed1->v2->edge_tot == 1) {
				BLI_remlink((ListBase *)&(sc->edge_first), ed1);
				BLI_addtail(&sf_ctx->filledgebase, ed1);
				if (ed1->v1->edge_tot > 1) ed1->v1->edge_tot--;
				if (ed1->v2->edge_tot > 1) ed1->v2->edge_tot--;
			}
			else {
				ed1->v2->f = SF_VERT_AVAILABLE;
			}
		}
		while (sc->edge_first) { /* for as long there are edges */
			ed1 = sc->edge_first;
			ed2 = ed1->next;
			
			/* commented out... the ESC here delivers corrupted memory (and doesnt work during grab) */
			/* if (callLocalInterruptCallBack()) break; */
			if (totface >= maxface) {
				/* printf("Fill error: endless loop. Escaped at vert %d,  tot: %d.\n", a, verts); */
				a = verts;
				break;
			}
			if (ed2 == NULL) {
				sc->edge_first = sc->edge_last = NULL;
				/* printf("just 1 edge to vert\n"); */
				BLI_addtail(&sf_ctx->filledgebase, ed1);
				ed1->v2->f = SF_VERT_NEW;
				ed1->v1->edge_tot--;
				ed1->v2->edge_tot--;
			}
			else {
				/* test rest of vertices */
				ScanFillVertLink *best_sc = NULL;
				float best_angle = 3.14f;
				float miny;
				bool firsttime = false;
				
				v1 = ed1->v2;
				v2 = ed1->v1;
				v3 = ed2->v2;
				
				/* this happens with a serial of overlapping edges */
				if (v1 == v2 || v2 == v3) break;
				
				/* printf("test verts %d %d %d\n", v1->tmp.u, v2->tmp.u, v3->tmp.u); */
				miny = min_ff(v1->xy[1], v3->xy[1]);
				sc1 = sc + 1;

				for (b = a + 1; b < verts; b++, sc1++) {
					if (sc1->vert->f == SF_VERT_NEW) {
						if (sc1->vert->xy[1] <= miny) break;
						if (testedgeside(v1->xy, v2->xy, sc1->vert->xy)) {
							if (testedgeside(v2->xy, v3->xy, sc1->vert->xy)) {
								if (testedgeside(v3->xy, v1->xy, sc1->vert->xy)) {
									/* point is in triangle */
									
									/* because multiple points can be inside triangle (concave holes) */
									/* we continue searching and pick the one with sharpest corner */
									
									if (best_sc == NULL) {
										/* even without holes we need to keep checking [#35861] */
										best_sc = sc1;
									}
									else {
										float angle;
										
										/* prevent angle calc for the simple cases only 1 vertex is found */
										if (firsttime == false) {
											best_angle = angle_v2v2v2(v2->xy, v1->xy, best_sc->vert->xy);
											firsttime = true;
										}

										angle = angle_v2v2v2(v2->xy, v1->xy, sc1->vert->xy);
										if (angle < best_angle) {
											best_sc = sc1;
											best_angle = angle;
										}
									}
										
								}
							}
						}
					}
				}
					
				if (best_sc) {
					/* make new edge, and start over */
					/* printf("add new edge %d %d and start again\n", v2->tmp.u, best_sc->vert->tmp.u); */

					ed3 = BLI_scanfill_edge_add(sf_ctx, v2, best_sc->vert);
					BLI_remlink(&sf_ctx->filledgebase, ed3);
					BLI_insertlinkbefore((ListBase *)&(sc->edge_first), ed2, ed3);
					ed3->v2->f = SF_VERT_AVAILABLE;
					ed3->f = SF_EDGE_INTERNAL;
					ed3->v1->edge_tot++;
					ed3->v2->edge_tot++;
				}
				else {
					/* new triangle */
					/* printf("add face %d %d %d\n", v1->tmp.u, v2->tmp.u, v3->tmp.u); */
					addfillface(sf_ctx, v1, v2, v3);
					totface++;
					BLI_remlink((ListBase *)&(sc->edge_first), ed1);
					BLI_addtail(&sf_ctx->filledgebase, ed1);
					ed1->v2->f = SF_VERT_NEW;
					ed1->v1->edge_tot--;
					ed1->v2->edge_tot--;
					/* ed2 can be removed when it's a boundary edge */
					if (((ed2->f == SF_EDGE_NEW) && twoconnected) /* || (ed2->f == SF_EDGE_BOUNDARY) */) {
						BLI_remlink((ListBase *)&(sc->edge_first), ed2);
						BLI_addtail(&sf_ctx->filledgebase, ed2);
						ed2->v2->f = SF_VERT_NEW;
						ed2->v1->edge_tot--;
						ed2->v2->edge_tot--;
					}

					/* new edge */
					ed3 = BLI_scanfill_edge_add(sf_ctx, v1, v3);
					BLI_remlink(&sf_ctx->filledgebase, ed3);
					ed3->f = SF_EDGE_INTERNAL;
					ed3->v1->edge_tot++;
					ed3->v2->edge_tot++;
					
					/* printf("add new edge %x %x\n", v1, v3); */
					sc1 = addedgetoscanlist(scdata, ed3, verts);
					
					if (sc1) {  /* ed3 already exists: remove if a boundary */
						/* printf("Edge exists\n"); */
						ed3->v1->edge_tot--;
						ed3->v2->edge_tot--;

						for (ed3 = sc1->edge_first; ed3; ed3 = ed3->next) {
							if ((ed3->v1 == v1 && ed3->v2 == v3) || (ed3->v1 == v3 && ed3->v2 == v1)) {
								if (twoconnected /* || (ed3->f == SF_EDGE_BOUNDARY) */) {
									BLI_remlink((ListBase *)&(sc1->edge_first), ed3);
									BLI_addtail(&sf_ctx->filledgebase, ed3);
									ed3->v1->edge_tot--;
									ed3->v2->edge_tot--;
								}
								break;
							}
						}
					}
				}
			}

			/* test for loose edges */
			for (ed1 = sc->edge_first; ed1; ed1 = eed_next) {
				eed_next = ed1->next;
				if (ed1->v1->edge_tot < 2 || ed1->v2->edge_tot < 2) {
					BLI_remlink((ListBase *)&(sc->edge_first), ed1);
					BLI_addtail(&sf_ctx->filledgebase, ed1);
					if (ed1->v1->edge_tot > 1) ed1->v1->edge_tot--;
					if (ed1->v2->edge_tot > 1) ed1->v2->edge_tot--;
				}
			}
			/* done with loose edges */
		}

		sc++;
	}

	MEM_freeN(scdata);

	BLI_assert(totface <= maxface);

	return totface;
}