Exemple #1
0
BoidState *boid_duplicate_state(BoidSettings *boids, BoidState *state) {
	BoidState *staten = MEM_dupallocN(state);

	BLI_duplicatelist(&staten->rules, &state->rules);
	BLI_duplicatelist(&staten->conditions, &state->conditions);
	BLI_duplicatelist(&staten->actions, &state->actions);

	staten->id = boids->last_state_id++;

	return staten;
}
Exemple #2
0
/**
 * Allocate a new pose on the heap, and copy the src pose and it's channels
 * into the new pose. *dst is set to the newly allocated structure, and assumed to be NULL.
 *
 * \param dst  Should be freed already, makes entire duplicate.
 */
void BKE_pose_copy_data(bPose **dst, bPose *src, const bool copy_constraints)
{
	bPose *outPose;
	bPoseChannel *pchan;
	ListBase listb;

	if (!src) {
		*dst = NULL;
		return;
	}
	
	outPose = MEM_callocN(sizeof(bPose), "pose");
	
	BLI_duplicatelist(&outPose->chanbase, &src->chanbase);

	outPose->iksolver = src->iksolver;
	outPose->ikdata = NULL;
	outPose->ikparam = MEM_dupallocN(src->ikparam);
	outPose->avs = src->avs;
	
	for (pchan = outPose->chanbase.first; pchan; pchan = pchan->next) {

		if (pchan->custom) {
			id_us_plus(&pchan->custom->id);
		}

		/* warning, O(n2) here, but it's a rarely used feature. */
		if (pchan->custom_tx) {
			pchan->custom_tx = BKE_pose_channel_find_name(outPose, pchan->custom_tx->name);
		}

		if (copy_constraints) {
			BKE_constraints_copy(&listb, &pchan->constraints, true);  // BKE_constraints_copy NULLs listb
			pchan->constraints = listb;
			pchan->mpath = NULL; /* motion paths should not get copied yet... */
		}
		
		if (pchan->prop) {
			pchan->prop = IDP_CopyProperty(pchan->prop);
		}
	}

	/* for now, duplicate Bone Groups too when doing this */
	if (copy_constraints) {
		BLI_duplicatelist(&outPose->agroups, &src->agroups);
	}
	
	*dst = outPose;
}
ARegion *BKE_area_region_copy(SpaceType *st, ARegion *ar)
{
	ARegion *newar = MEM_dupallocN(ar);
	Panel *pa, *newpa, *patab;
	
	newar->prev = newar->next = NULL;
	BLI_listbase_clear(&newar->handlers);
	BLI_listbase_clear(&newar->uiblocks);
	BLI_listbase_clear(&newar->panels_category);
	BLI_listbase_clear(&newar->panels_category_active);
	BLI_listbase_clear(&newar->ui_lists);
	newar->swinid = 0;
	
	/* use optional regiondata callback */
	if (ar->regiondata) {
		ARegionType *art = BKE_regiontype_from_id(st, ar->regiontype);

		if (art && art->duplicate)
			newar->regiondata = art->duplicate(ar->regiondata);
		else
			newar->regiondata = MEM_dupallocN(ar->regiondata);
	}

	if (ar->v2d.tab_offset)
		newar->v2d.tab_offset = MEM_dupallocN(ar->v2d.tab_offset);
	
	BLI_listbase_clear(&newar->panels);
	BLI_duplicatelist(&newar->panels, &ar->panels);

	BLI_listbase_clear(&newar->ui_previews);
	BLI_duplicatelist(&newar->ui_previews, &ar->ui_previews);

	/* copy panel pointers */
	for (newpa = newar->panels.first; newpa; newpa = newpa->next) {
		patab = newar->panels.first;
		pa = ar->panels.first;
		while (patab) {
			if (newpa->paneltab == pa) {
				newpa->paneltab = patab;
				break;
			}
			patab = patab->next;
			pa = pa->next;
		}
	}
	
	return newar;
}
Exemple #4
0
static int vertex_group_copy_to_linked_exec(bContext *C, wmOperator *op)
{
	Scene *scene= CTX_data_scene(C);
	Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
	Base *base;
	int retval= OPERATOR_CANCELLED;

	for(base=scene->base.first; base; base= base->next) {
		if(base->object->type==ob->type) {
			if(base->object!=ob && base->object->data==ob->data) {
				BLI_freelistN(&base->object->defbase);
				BLI_duplicatelist(&base->object->defbase, &ob->defbase);
				base->object->actdef= ob->actdef;

				DAG_id_flush_update(&base->object->id, OB_RECALC_DATA);
				WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, base->object);
				WM_event_add_notifier(C, NC_GEOM|ND_DATA, base->object->data);

				retval = OPERATOR_FINISHED;
			}
		}
	}

	return retval;
}
Exemple #5
0
bContextStore *CTX_store_add_all(ListBase *contexts, bContextStore *context)
{
	bContextStoreEntry *entry, *tentry;
	bContextStore *ctx, *lastctx;

	/* ensure we have a context to put the entries in, if it was already used
	 * we have to copy the context to ensure */
	ctx = contexts->last;

	if (!ctx || ctx->used) {
		if (ctx) {
			lastctx = ctx;
			ctx = MEM_dupallocN(lastctx);
			BLI_duplicatelist(&ctx->entries, &lastctx->entries);
		}
		else
			ctx = MEM_callocN(sizeof(bContextStore), "bContextStore");

		BLI_addtail(contexts, ctx);
	}

	for (tentry = context->entries.first; tentry; tentry = tentry->next) {
		entry = MEM_dupallocN(tentry);
		BLI_addtail(&ctx->entries, entry);
	}

	return ctx;
}
Exemple #6
0
/* Duplicate all of the F-Modifiers in the Modifier stacks */
void copy_fmodifiers(ListBase *dst, const ListBase *src)
{
  FModifier *fcm, *srcfcm;

  if (ELEM(NULL, dst, src)) {
    return;
  }

  BLI_listbase_clear(dst);
  BLI_duplicatelist(dst, src);

  for (fcm = dst->first, srcfcm = src->first; fcm && srcfcm;
       srcfcm = srcfcm->next, fcm = fcm->next) {
    const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm);

    /* make a new copy of the F-Modifier's data */
    fcm->data = MEM_dupallocN(fcm->data);
    fcm->curve = NULL;

    /* only do specific constraints if required */
    if (fmi && fmi->copy_data) {
      fmi->copy_data(fcm, srcfcm);
    }
  }
}
Exemple #7
0
bContextStore *CTX_store_add(ListBase *contexts, const char *name, PointerRNA *ptr)
{
	bContextStoreEntry *entry;
	bContextStore *ctx, *lastctx;

	/* ensure we have a context to put the entry in, if it was already used
	 * we have to copy the context to ensure */
	ctx= contexts->last;

	if(!ctx || ctx->used) {
		if(ctx) {
			lastctx= ctx;
			ctx= MEM_dupallocN(lastctx);
			BLI_duplicatelist(&ctx->entries, &lastctx->entries);
		}
		else
			ctx= MEM_callocN(sizeof(bContextStore), "bContextStore");

		BLI_addtail(contexts, ctx);
	}

	entry= MEM_callocN(sizeof(bContextStoreEntry), "bContextStoreEntry");
	BLI_strncpy(entry->name, name, sizeof(entry->name));
	entry->ptr= *ptr;

	BLI_addtail(&ctx->entries, entry);

	return ctx;
}
Exemple #8
0
void screen_data_copy(bScreen *to, bScreen *from)
{
  ScrVert *s1, *s2;
  ScrEdge *se;
  ScrArea *sa, *saf;

  /* free contents of 'to', is from blenkernel screen.c */
  BKE_screen_free(to);

  to->flag = from->flag;

  BLI_duplicatelist(&to->vertbase, &from->vertbase);
  BLI_duplicatelist(&to->edgebase, &from->edgebase);
  BLI_duplicatelist(&to->areabase, &from->areabase);
  BLI_listbase_clear(&to->regionbase);

  s2 = to->vertbase.first;
  for (s1 = from->vertbase.first; s1; s1 = s1->next, s2 = s2->next) {
    s1->newv = s2;
  }

  for (se = to->edgebase.first; se; se = se->next) {
    se->v1 = se->v1->newv;
    se->v2 = se->v2->newv;
    BKE_screen_sort_scrvert(&(se->v1), &(se->v2));
  }

  saf = from->areabase.first;
  for (sa = to->areabase.first; sa; sa = sa->next, saf = saf->next) {
    sa->v1 = sa->v1->newv;
    sa->v2 = sa->v2->newv;
    sa->v3 = sa->v3->newv;
    sa->v4 = sa->v4->newv;

    BLI_listbase_clear(&sa->spacedata);
    BLI_listbase_clear(&sa->regionbase);
    BLI_listbase_clear(&sa->actionzones);
    BLI_listbase_clear(&sa->handlers);

    ED_area_data_copy(sa, saf, true);
  }

  /* put at zero (needed?) */
  for (s1 = from->vertbase.first; s1; s1 = s1->next) {
    s1->newv = NULL;
  }
}
Exemple #9
0
/* dst should be freed already, makes entire duplicate */
void copy_pose (bPose **dst, bPose *src, int copycon)
{
	bPose *outPose;
	bPoseChannel *pchan;
	ListBase listb;
	
	if (!src) {
		*dst=NULL;
		return;
	}
	
	if (*dst==src) {
		printf("copy_pose source and target are the same\n");
		*dst=NULL;
		return;
	}
	
	outPose= MEM_callocN(sizeof(bPose), "pose");
	
	BLI_duplicatelist(&outPose->chanbase, &src->chanbase);
	
	outPose->iksolver = src->iksolver;
	outPose->ikdata = NULL;
	outPose->ikparam = MEM_dupallocN(src->ikparam);
	
	for (pchan=outPose->chanbase.first; pchan; pchan=pchan->next) {
		// TODO: rename this argument...
		if (copycon) {
			copy_constraints(&listb, &pchan->constraints, TRUE);  // copy_constraints NULLs listb
			pchan->constraints= listb;
			pchan->path= NULL; // XXX remove this line when the new motionpaths are ready... (depreceated code)
			pchan->mpath= NULL; /* motion paths should not get copied yet... */
		}
		
		if(pchan->prop) {
			pchan->prop= IDP_CopyProperty(pchan->prop);
		}
	}

	/* for now, duplicate Bone Groups too when doing this */
	if (copycon)
		BLI_duplicatelist(&outPose->agroups, &src->agroups);
	
	*dst=outPose;
}
Exemple #10
0
Group *copy_group(Group *group)
{
	Group *groupn;

	groupn= MEM_dupallocN(group);
	BLI_duplicatelist(&groupn->gobject, &group->gobject);

	return groupn;
}
Exemple #11
0
bContextStore *CTX_store_copy(bContextStore *store)
{
	bContextStore *ctx;

	ctx= MEM_dupallocN(store);
	BLI_duplicatelist(&ctx->entries, &store->entries);

	return ctx;
}
Exemple #12
0
bAction *BKE_action_copy(Main *bmain, bAction *src)
{
	bAction *dst = NULL;
	bActionGroup *dgrp, *sgrp;
	FCurve *dfcu, *sfcu;
	
	if (src == NULL) 
		return NULL;
	dst = BKE_libblock_copy(bmain, &src->id);
	
	/* duplicate the lists of groups and markers */
	BLI_duplicatelist(&dst->groups, &src->groups);
	BLI_duplicatelist(&dst->markers, &src->markers);
	
	/* copy F-Curves, fixing up the links as we go */
	BLI_listbase_clear(&dst->curves);
	
	for (sfcu = src->curves.first; sfcu; sfcu = sfcu->next) {
		/* duplicate F-Curve */
		dfcu = copy_fcurve(sfcu);
		BLI_addtail(&dst->curves, dfcu);
		
		/* fix group links (kindof bad list-in-list search, but this is the most reliable way) */
		for (dgrp = dst->groups.first, sgrp = src->groups.first; dgrp && sgrp; dgrp = dgrp->next, sgrp = sgrp->next) {
			if (sfcu->grp == sgrp) {
				dfcu->grp = dgrp;
				
				if (dgrp->channels.first == sfcu)
					dgrp->channels.first = dfcu;
				if (dgrp->channels.last == sfcu)
					dgrp->channels.last = dfcu;
					
				break;
			}
		}
	}
	
	BKE_id_copy_ensure_local(bmain, &src->id, &dst->id);

	return dst;
}
Exemple #13
0
/* dst should be freed already, makes entire duplicate */
void BKE_pose_copy_data(bPose **dst, bPose *src, int copycon)
{
	bPose *outPose;
	bPoseChannel *pchan;
	ListBase listb;

	if (!src) {
		*dst = NULL;
		return;
	}
	
	outPose = MEM_callocN(sizeof(bPose), "pose");
	
	BLI_duplicatelist(&outPose->chanbase, &src->chanbase);
	
	outPose->iksolver = src->iksolver;
	outPose->ikdata = NULL;
	outPose->ikparam = MEM_dupallocN(src->ikparam);
	outPose->avs = src->avs;
	
	for (pchan = outPose->chanbase.first; pchan; pchan = pchan->next) {
		/* TODO: rename this argument... */
		if (copycon) {
			BKE_copy_constraints(&listb, &pchan->constraints, TRUE);  // BKE_copy_constraints NULLs listb
			pchan->constraints = listb;
			pchan->mpath = NULL; /* motion paths should not get copied yet... */
		}
		
		if (pchan->prop) {
			pchan->prop = IDP_CopyProperty(pchan->prop);
		}
	}

	/* for now, duplicate Bone Groups too when doing this */
	if (copycon)
		BLI_duplicatelist(&outPose->agroups, &src->agroups);
	
	*dst = outPose;
}
Exemple #14
0
BoidSettings *boid_copy_settings(BoidSettings *boids)
{
	BoidSettings *nboids = NULL;

	if (boids) {
		BoidState *state;
		BoidState *nstate;

		nboids = MEM_dupallocN(boids);

		BLI_duplicatelist(&nboids->states, &boids->states);

		state = boids->states.first;
		nstate = nboids->states.first;
		for (; state; state=state->next, nstate=nstate->next) {
			BLI_duplicatelist(&nstate->rules, &state->rules);
			BLI_duplicatelist(&nstate->conditions, &state->conditions);
			BLI_duplicatelist(&nstate->actions, &state->actions);
		}
	}

	return nboids;
}
Exemple #15
0
ListBase *folderlist_duplicate(ListBase* folderlist)
{
	
	if (folderlist) {
		ListBase *folderlistn= MEM_callocN(sizeof(ListBase), "copy folderlist");
		FolderList *folder;
		
		BLI_duplicatelist(folderlistn, folderlist);
		
		for (folder= folderlistn->first; folder; folder= folder->next) {
			folder->foldername= MEM_dupallocN(folder->foldername);
		}
		return folderlistn;
	}
	return NULL;
}
Exemple #16
0
/**
 * Duplicate a workspace including its layouts. Does not activate the workspace, but
 * it stores the screen-layout to be activated (BKE_workspace_temp_layout_store)
 */
WorkSpace *ED_workspace_duplicate(WorkSpace *workspace_old, Main *bmain, wmWindow *win)
{
  WorkSpaceLayout *layout_active_old = BKE_workspace_active_layout_get(win->workspace_hook);
  ListBase *layouts_old = BKE_workspace_layouts_get(workspace_old);
  WorkSpace *workspace_new = ED_workspace_add(bmain, workspace_old->id.name + 2);

  workspace_new->flags = workspace_old->flags;
  BLI_duplicatelist(&workspace_new->owner_ids, &workspace_old->owner_ids);

  /* TODO(campbell): tools */

  for (WorkSpaceLayout *layout_old = layouts_old->first; layout_old;
       layout_old = layout_old->next) {
    WorkSpaceLayout *layout_new = ED_workspace_layout_duplicate(
        bmain, workspace_new, layout_old, win);

    if (layout_active_old == layout_old) {
      win->workspace_hook->temp_layout_store = layout_new;
    }
  }
  return workspace_new;
}
Exemple #17
0
MetaBall *BKE_mball_copy(MetaBall *mb)
{
    MetaBall *mbn;
    int a;

    mbn = BKE_libblock_copy(&mb->id);

    BLI_duplicatelist(&mbn->elems, &mb->elems);

    mbn->mat = MEM_dupallocN(mb->mat);
    for (a = 0; a < mbn->totcol; a++) {
        id_us_plus((ID *)mbn->mat[a]);
    }

    mbn->editelems = NULL;
    mbn->lastelem = NULL;

    if (mb->id.lib) {
        BKE_id_lib_local_paths(G.main, mb->id.lib, &mbn->id);
    }

    return mbn;
}
Exemple #18
0
static void layer_collections_copy_data(ViewLayer *view_layer_dst,
                                        const ViewLayer *view_layer_src,
                                        ListBase *layer_collections_dst,
                                        const ListBase *layer_collections_src)
{
  BLI_duplicatelist(layer_collections_dst, layer_collections_src);

  LayerCollection *layer_collection_dst = layer_collections_dst->first;
  const LayerCollection *layer_collection_src = layer_collections_src->first;

  while (layer_collection_dst != NULL) {
    layer_collections_copy_data(view_layer_dst,
                                view_layer_src,
                                &layer_collection_dst->layer_collections,
                                &layer_collection_src->layer_collections);

    if (layer_collection_src == view_layer_src->active_collection) {
      view_layer_dst->active_collection = layer_collection_dst;
    }

    layer_collection_dst = layer_collection_dst->next;
    layer_collection_src = layer_collection_src->next;
  }
}
/** 
 * Move here pose function for game engine so that we can mix with GE objects
 * Principle is as follow:
 * Use Blender structures so that BKE_pose_where_is can be used unchanged
 * Copy the constraint so that they can be enabled/disabled/added/removed at runtime
 * Don't copy the constraints for the pose used by the Action actuator, it does not need them.
 * Scan the constraint structures so that the KX equivalent of target objects are identified and 
 * stored in separate list.
 * When it is about to evaluate the pose, set the KX object position in the obmat of the corresponding
 * Blender objects and restore after the evaluation.
 */
static void game_copy_pose(bPose **dst, bPose *src, int copy_constraint)
{
	bPose *out;
	bPoseChannel *pchan, *outpchan;
	GHash *ghash;
	
	/* the game engine copies the current armature pose and then swaps
	 * the object pose pointer. this makes it possible to change poses
	 * without affecting the original blender data. */

	if (!src) {
		*dst=NULL;
		return;
	}
	else if (*dst==src) {
		printf("game_copy_pose source and target are the same\n");
		*dst=NULL;
		return;
	}
	
	out= (bPose*)MEM_dupallocN(src);
	out->chanhash = NULL;
	out->agroups.first= out->agroups.last= NULL;
	out->ikdata = NULL;
	out->ikparam = MEM_dupallocN(src->ikparam);
	out->flag |= POSE_GAME_ENGINE;
	BLI_duplicatelist(&out->chanbase, &src->chanbase);

	/* remap pointers */
	ghash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "game_copy_pose gh");

	pchan= (bPoseChannel *)src->chanbase.first;
	outpchan= (bPoseChannel *)out->chanbase.first;
	for (; pchan; pchan=pchan->next, outpchan=outpchan->next)
		BLI_ghash_insert(ghash, pchan, outpchan);

	for (pchan = (bPoseChannel *)out->chanbase.first; pchan; pchan = pchan->next) {
		pchan->parent= (bPoseChannel *)BLI_ghash_lookup(ghash, pchan->parent);
		pchan->child= (bPoseChannel *)BLI_ghash_lookup(ghash, pchan->child);

		if (copy_constraint) {
			ListBase listb;
			// copy all constraint for backward compatibility
			// BKE_constraints_copy NULLs listb, no need to make extern for this operation.
			BKE_constraints_copy(&listb, &pchan->constraints, false);
			pchan->constraints= listb;
		}
		else {
			BLI_listbase_clear(&pchan->constraints);
		}

		if (pchan->custom) {
			id_us_plus(&pchan->custom->id);
		}

		// fails to link, props are not used in the BGE yet.
#if 0
		if (pchan->prop)
			pchan->prop= IDP_CopyProperty(pchan->prop);
#endif
		pchan->prop= NULL;
	}

	BLI_ghash_free(ghash, NULL, NULL);
	// set acceleration structure for channel lookup
	BKE_pose_channels_hash_make(out);
	*dst=out;
}
Exemple #20
0
/**
 * Allocate a new pose on the heap, and copy the src pose and it's channels
 * into the new pose. *dst is set to the newly allocated structure, and assumed to be NULL.
 *
 * \param dst  Should be freed already, makes entire duplicate.
 */
void BKE_pose_copy_data(bPose **dst, bPose *src, const bool copy_constraints)
{
	bPose *outPose;
	bPoseChannel *pchan;
	ListBase listb;

	if (!src) {
		*dst = NULL;
		return;
	}
	
	outPose = MEM_callocN(sizeof(bPose), "pose");
	
	BLI_duplicatelist(&outPose->chanbase, &src->chanbase);
	
	/* Rebuild ghash here too, so that name lookups below won't be too bad...
	 * BUT this will have the penalty that the ghash will be built twice
	 * if BKE_pose_rebuild() gets called after this...
	 */
	if (outPose->chanbase.first != outPose->chanbase.last) {
		outPose->chanhash = NULL;
		BKE_pose_channels_hash_make(outPose);
	}
	
	outPose->iksolver = src->iksolver;
	outPose->ikdata = NULL;
	outPose->ikparam = MEM_dupallocN(src->ikparam);
	outPose->avs = src->avs;
	
	for (pchan = outPose->chanbase.first; pchan; pchan = pchan->next) {

		if (pchan->custom) {
			id_us_plus(&pchan->custom->id);
		}

		/* warning, O(n2) here, if done without the hash, but these are rarely used features. */
		if (pchan->custom_tx) {
			pchan->custom_tx = BKE_pose_channel_find_name(outPose, pchan->custom_tx->name);
		}
		if (pchan->bbone_prev) {
			pchan->bbone_prev = BKE_pose_channel_find_name(outPose, pchan->bbone_prev->name);
		}
		if (pchan->bbone_next) {
			pchan->bbone_next = BKE_pose_channel_find_name(outPose, pchan->bbone_next->name);
		}

		if (copy_constraints) {
			BKE_constraints_copy(&listb, &pchan->constraints, true);  // BKE_constraints_copy NULLs listb
			pchan->constraints = listb;
			pchan->mpath = NULL; /* motion paths should not get copied yet... */
		}
		
		if (pchan->prop) {
			pchan->prop = IDP_CopyProperty(pchan->prop);
		}
	}

	/* for now, duplicate Bone Groups too when doing this */
	if (copy_constraints) {
		BLI_duplicatelist(&outPose->agroups, &src->agroups);
	}
	
	*dst = outPose;
}
/* position block relative to but, result is in window space */
static void ui_popup_block_position(wmWindow *window,
                                    ARegion *butregion,
                                    uiBut *but,
                                    uiBlock *block)
{
  uiPopupBlockHandle *handle = block->handle;

  /* Compute button position in window coordinates using the source
   * button region/block, to position the popup attached to it. */
  rctf butrct;

  if (!handle->refresh) {
    ui_block_to_window_rctf(butregion, but->block, &butrct, &but->rect);

    /* widget_roundbox_set has this correction too, keep in sync */
    if (but->type != UI_BTYPE_PULLDOWN) {
      if (but->drawflag & UI_BUT_ALIGN_TOP) {
        butrct.ymax += U.pixelsize;
      }
      if (but->drawflag & UI_BUT_ALIGN_LEFT) {
        butrct.xmin -= U.pixelsize;
      }
    }

    handle->prev_butrct = butrct;
  }
  else {
    /* For refreshes, keep same button position so popup doesn't move. */
    butrct = handle->prev_butrct;
  }

  /* Compute block size in window space, based on buttons contained in it. */
  if (block->rect.xmin == 0.0f && block->rect.xmax == 0.0f) {
    if (block->buttons.first) {
      BLI_rctf_init_minmax(&block->rect);

      for (uiBut *bt = block->buttons.first; bt; bt = bt->next) {
        if (block->content_hints & UI_BLOCK_CONTAINS_SUBMENU_BUT) {
          bt->rect.xmax += UI_MENU_SUBMENU_PADDING;
        }
        BLI_rctf_union(&block->rect, &bt->rect);
      }
    }
    else {
      /* we're nice and allow empty blocks too */
      block->rect.xmin = block->rect.ymin = 0;
      block->rect.xmax = block->rect.ymax = 20;
    }
  }

  ui_block_to_window_rctf(butregion, but->block, &block->rect, &block->rect);

  /* Compute direction relative to button, based on available space. */
  const int size_x = BLI_rctf_size_x(&block->rect) + 0.2f * UI_UNIT_X; /* 4 for shadow */
  const int size_y = BLI_rctf_size_y(&block->rect) + 0.2f * UI_UNIT_Y;
  const int center_x = (block->direction & UI_DIR_CENTER_X) ? size_x / 2 : 0;
  const int center_y = (block->direction & UI_DIR_CENTER_Y) ? size_y / 2 : 0;

  short dir1 = 0, dir2 = 0;

  if (!handle->refresh) {
    bool left = 0, right = 0, top = 0, down = 0;

    const int win_x = WM_window_pixels_x(window);
    const int win_y = WM_window_pixels_y(window);

    /* Take into account maximum size so we don't have to flip on refresh. */
    const float max_size_x = max_ff(size_x, handle->max_size_x);
    const float max_size_y = max_ff(size_y, handle->max_size_y);

    /* check if there's space at all */
    if (butrct.xmin - max_size_x + center_x > 0.0f) {
      left = 1;
    }
    if (butrct.xmax + max_size_x - center_x < win_x) {
      right = 1;
    }
    if (butrct.ymin - max_size_y + center_y > 0.0f) {
      down = 1;
    }
    if (butrct.ymax + max_size_y - center_y < win_y) {
      top = 1;
    }

    if (top == 0 && down == 0) {
      if (butrct.ymin - max_size_y < win_y - butrct.ymax - max_size_y) {
        top = 1;
      }
      else {
        down = 1;
      }
    }

    dir1 = (block->direction & UI_DIR_ALL);

    /* Secondary directions. */
    if (dir1 & (UI_DIR_UP | UI_DIR_DOWN)) {
      if (dir1 & UI_DIR_LEFT) {
        dir2 = UI_DIR_LEFT;
      }
      else if (dir1 & UI_DIR_RIGHT) {
        dir2 = UI_DIR_RIGHT;
      }
      dir1 &= (UI_DIR_UP | UI_DIR_DOWN);
    }

    if ((dir2 == 0) && (dir1 == UI_DIR_LEFT || dir1 == UI_DIR_RIGHT)) {
      dir2 = UI_DIR_DOWN;
    }
    if ((dir2 == 0) && (dir1 == UI_DIR_UP || dir1 == UI_DIR_DOWN)) {
      dir2 = UI_DIR_LEFT;
    }

    /* no space at all? don't change */
    if (left || right) {
      if (dir1 == UI_DIR_LEFT && left == 0) {
        dir1 = UI_DIR_RIGHT;
      }
      if (dir1 == UI_DIR_RIGHT && right == 0) {
        dir1 = UI_DIR_LEFT;
      }
      /* this is aligning, not append! */
      if (dir2 == UI_DIR_LEFT && right == 0) {
        dir2 = UI_DIR_RIGHT;
      }
      if (dir2 == UI_DIR_RIGHT && left == 0) {
        dir2 = UI_DIR_LEFT;
      }
    }
    if (down || top) {
      if (dir1 == UI_DIR_UP && top == 0) {
        dir1 = UI_DIR_DOWN;
      }
      if (dir1 == UI_DIR_DOWN && down == 0) {
        dir1 = UI_DIR_UP;
      }
      BLI_assert(dir2 != UI_DIR_UP);
      //          if (dir2 == UI_DIR_UP   && top == 0)  { dir2 = UI_DIR_DOWN; }
      if (dir2 == UI_DIR_DOWN && down == 0) {
        dir2 = UI_DIR_UP;
      }
    }

    handle->prev_dir1 = dir1;
    handle->prev_dir2 = dir2;
  }
  else {
    /* For refreshes, keep same popup direct so popup doesn't move
     * to a totally different position while editing in it. */
    dir1 = handle->prev_dir1;
    dir2 = handle->prev_dir2;
  }

  /* Compute offset based on direction. */
  float offset_x = 0, offset_y = 0;

  /* Ensure buttons don't come between the parent button and the popup, see: T63566. */
  const float offset_overlap = max_ff(U.pixelsize, 1.0f);

  if (dir1 == UI_DIR_LEFT) {
    offset_x = (butrct.xmin - block->rect.xmax) + offset_overlap;
    if (dir2 == UI_DIR_UP) {
      offset_y = butrct.ymin - block->rect.ymin - center_y - UI_MENU_PADDING;
    }
    else {
      offset_y = butrct.ymax - block->rect.ymax + center_y + UI_MENU_PADDING;
    }
  }
  else if (dir1 == UI_DIR_RIGHT) {
    offset_x = (butrct.xmax - block->rect.xmin) - offset_overlap;
    if (dir2 == UI_DIR_UP) {
      offset_y = butrct.ymin - block->rect.ymin - center_y - UI_MENU_PADDING;
    }
    else {
      offset_y = butrct.ymax - block->rect.ymax + center_y + UI_MENU_PADDING;
    }
  }
  else if (dir1 == UI_DIR_UP) {
    offset_y = (butrct.ymax - block->rect.ymin) - offset_overlap;
    if (dir2 == UI_DIR_RIGHT) {
      offset_x = butrct.xmax - block->rect.xmax + center_x;
    }
    else {
      offset_x = butrct.xmin - block->rect.xmin - center_x;
    }
    /* changed direction? */
    if ((dir1 & block->direction) == 0) {
      /* TODO: still do */
      UI_block_order_flip(block);
    }
  }
  else if (dir1 == UI_DIR_DOWN) {
    offset_y = (butrct.ymin - block->rect.ymax) + offset_overlap;
    if (dir2 == UI_DIR_RIGHT) {
      offset_x = butrct.xmax - block->rect.xmax + center_x;
    }
    else {
      offset_x = butrct.xmin - block->rect.xmin - center_x;
    }
    /* changed direction? */
    if ((dir1 & block->direction) == 0) {
      /* TODO: still do */
      UI_block_order_flip(block);
    }
  }

  /* Center over popovers for eg. */
  if (block->direction & UI_DIR_CENTER_X) {
    offset_x += BLI_rctf_size_x(&butrct) / ((dir2 == UI_DIR_LEFT) ? 2 : -2);
  }

  /* Apply offset, buttons in window coords. */
  for (uiBut *bt = block->buttons.first; bt; bt = bt->next) {
    ui_block_to_window_rctf(butregion, but->block, &bt->rect, &bt->rect);

    BLI_rctf_translate(&bt->rect, offset_x, offset_y);

    /* ui_but_update recalculates drawstring size in pixels */
    ui_but_update(bt);
  }

  BLI_rctf_translate(&block->rect, offset_x, offset_y);

  /* Safety calculus. */
  {
    const float midx = BLI_rctf_cent_x(&butrct);
    const float midy = BLI_rctf_cent_y(&butrct);

    /* when you are outside parent button, safety there should be smaller */

    /* parent button to left */
    if (midx < block->rect.xmin) {
      block->safety.xmin = block->rect.xmin - 3;
    }
    else {
      block->safety.xmin = block->rect.xmin - 40;
    }
    /* parent button to right */
    if (midx > block->rect.xmax) {
      block->safety.xmax = block->rect.xmax + 3;
    }
    else {
      block->safety.xmax = block->rect.xmax + 40;
    }

    /* parent button on bottom */
    if (midy < block->rect.ymin) {
      block->safety.ymin = block->rect.ymin - 3;
    }
    else {
      block->safety.ymin = block->rect.ymin - 40;
    }
    /* parent button on top */
    if (midy > block->rect.ymax) {
      block->safety.ymax = block->rect.ymax + 3;
    }
    else {
      block->safety.ymax = block->rect.ymax + 40;
    }

    /* exception for switched pulldowns... */
    if (dir1 && (dir1 & block->direction) == 0) {
      if (dir2 == UI_DIR_RIGHT) {
        block->safety.xmax = block->rect.xmax + 3;
      }
      if (dir2 == UI_DIR_LEFT) {
        block->safety.xmin = block->rect.xmin - 3;
      }
    }
    block->direction = dir1;
  }

  /* keep a list of these, needed for pulldown menus */
  uiSafetyRct *saferct = MEM_callocN(sizeof(uiSafetyRct), "uiSafetyRct");
  saferct->parent = butrct;
  saferct->safety = block->safety;
  BLI_freelistN(&block->saferct);
  BLI_duplicatelist(&block->saferct, &but->block->saferct);
  BLI_addhead(&block->saferct, saferct);
}
Exemple #22
0
Scene *BKE_scene_copy(Scene *sce, int type)
{
	Scene *scen;
	ToolSettings *ts;
	Base *base, *obase;
	
	if (type == SCE_COPY_EMPTY) {
		ListBase lb;
		/* XXX. main should become an arg */
		scen = BKE_scene_add(G.main, sce->id.name + 2);
		
		lb = scen->r.layers;
		scen->r = sce->r;
		scen->r.layers = lb;
		scen->unit = sce->unit;
		scen->physics_settings = sce->physics_settings;
		scen->gm = sce->gm;
		scen->audio = sce->audio;

		MEM_freeN(scen->toolsettings);
	}
	else {
		scen = BKE_libblock_copy(&sce->id);
		BLI_duplicatelist(&(scen->base), &(sce->base));
		
		clear_id_newpoins();
		
		id_us_plus((ID *)scen->world);
		id_us_plus((ID *)scen->set);
		id_us_plus((ID *)scen->gm.dome.warptext);

		scen->ed = NULL;
		scen->theDag = NULL;
		scen->obedit = NULL;
		scen->stats = NULL;
		scen->fps_info = NULL;

		BLI_duplicatelist(&(scen->markers), &(sce->markers));
		BLI_duplicatelist(&(scen->transform_spaces), &(sce->transform_spaces));
		BLI_duplicatelist(&(scen->r.layers), &(sce->r.layers));
		BKE_keyingsets_copy(&(scen->keyingsets), &(sce->keyingsets));

		if (sce->nodetree) {
			/* ID's are managed on both copy and switch */
			scen->nodetree = ntreeCopyTree(sce->nodetree);
			ntreeSwitchID(scen->nodetree, &sce->id, &scen->id);
		}

		obase = sce->base.first;
		base = scen->base.first;
		while (base) {
			id_us_plus(&base->object->id);
			if (obase == sce->basact) scen->basact = base;
	
			obase = obase->next;
			base = base->next;
		}

		/* copy color management settings */
		BKE_color_managed_display_settings_copy(&scen->display_settings, &sce->display_settings);
		BKE_color_managed_view_settings_copy(&scen->view_settings, &sce->view_settings);
		BKE_color_managed_view_settings_copy(&scen->r.im_format.view_settings, &sce->r.im_format.view_settings);

		BLI_strncpy(scen->sequencer_colorspace_settings.name, sce->sequencer_colorspace_settings.name,
		            sizeof(scen->sequencer_colorspace_settings.name));

		/* remove animation used by sequencer */
		if (type != SCE_COPY_FULL)
			remove_sequencer_fcurves(scen);
	}

	/* tool settings */
	scen->toolsettings = MEM_dupallocN(sce->toolsettings);

	ts = scen->toolsettings;
	if (ts) {
		if (ts->vpaint) {
			ts->vpaint = MEM_dupallocN(ts->vpaint);
			ts->vpaint->paintcursor = NULL;
			ts->vpaint->vpaint_prev = NULL;
			ts->vpaint->wpaint_prev = NULL;
			BKE_paint_copy(&ts->vpaint->paint, &ts->vpaint->paint);
		}
		if (ts->wpaint) {
			ts->wpaint = MEM_dupallocN(ts->wpaint);
			ts->wpaint->paintcursor = NULL;
			ts->wpaint->vpaint_prev = NULL;
			ts->wpaint->wpaint_prev = NULL;
			BKE_paint_copy(&ts->wpaint->paint, &ts->wpaint->paint);
		}
		if (ts->sculpt) {
			ts->sculpt = MEM_dupallocN(ts->sculpt);
			BKE_paint_copy(&ts->sculpt->paint, &ts->sculpt->paint);
		}

		BKE_paint_copy(&ts->imapaint.paint, &ts->imapaint.paint);
		ts->imapaint.paintcursor = NULL;
		ts->particle.paintcursor = NULL;
	}
	
	/* make a private copy of the avicodecdata */
	if (sce->r.avicodecdata) {
		scen->r.avicodecdata = MEM_dupallocN(sce->r.avicodecdata);
		scen->r.avicodecdata->lpFormat = MEM_dupallocN(scen->r.avicodecdata->lpFormat);
		scen->r.avicodecdata->lpParms = MEM_dupallocN(scen->r.avicodecdata->lpParms);
	}
	
	/* make a private copy of the qtcodecdata */
	if (sce->r.qtcodecdata) {
		scen->r.qtcodecdata = MEM_dupallocN(sce->r.qtcodecdata);
		scen->r.qtcodecdata->cdParms = MEM_dupallocN(scen->r.qtcodecdata->cdParms);
	}
	
	if (sce->r.ffcodecdata.properties) { /* intentionally check scen not sce. */
		scen->r.ffcodecdata.properties = IDP_CopyProperty(sce->r.ffcodecdata.properties);
	}

	/* NOTE: part of SCE_COPY_LINK_DATA and SCE_COPY_FULL operations
	 * are done outside of blenkernel with ED_objects_single_users! */

	/*  camera */
	if (type == SCE_COPY_LINK_DATA || type == SCE_COPY_FULL) {
		ID_NEW(scen->camera);
	}
	
	/* before scene copy */
	sound_create_scene(scen);

	/* world */
	if (type == SCE_COPY_FULL) {
		BKE_copy_animdata_id_action((ID *)scen);
		if (scen->world) {
			id_us_plus((ID *)scen->world);
			scen->world = BKE_world_copy(scen->world);
			BKE_copy_animdata_id_action((ID *)scen->world);
		}

		if (sce->ed) {
			scen->ed = MEM_callocN(sizeof(Editing), "addseq");
			scen->ed->seqbasep = &scen->ed->seqbase;
			BKE_sequence_base_dupli_recursive(sce, scen, &scen->ed->seqbase, &sce->ed->seqbase, SEQ_DUPE_ALL);
		}
	}

	return scen;
}