Fix #19311: adding/opening datablocks did not always make the right

one active. Now there's a function to get the pointer + property from
the UI, just like for the animation operators.

Also two fixes for fileselect events, regions are now preserved so that
context is restored to the old region, and the cancel callback is called
when the operator is cancelled.
This commit is contained in:
2009-10-01 23:32:57 +00:00
parent bc942eceac
commit b26ef33b8e
11 changed files with 249 additions and 80 deletions

View File

@@ -86,15 +86,20 @@ World *add_world(char *name)
wrld= alloc_libblock(&G.main->world, ID_WO, name);
wrld->horb= 0.6f;
wrld->skytype= WO_SKYBLEND;
wrld->horr= 0.25f;
wrld->horg= 0.25f;
wrld->horb= 0.25f;
wrld->zenr= 0.1f;
wrld->zeng= 0.1f;
wrld->zenb= 0.1f;
wrld->skytype= 0;
wrld->stardist= 15.0f;
wrld->starsize= 2.0f;
wrld->exp= 0.0f;
wrld->exposure=wrld->range= 1.0f;
wrld->aodist= 5.0f;
wrld->aodist= 10.0f;
wrld->aosamp= 5;
wrld->aoenergy= 1.0f;
wrld->aobias= 0.05f;

View File

@@ -670,6 +670,7 @@ void uiItemMenuEnumR(uiLayout *layout, char *name, int icon, struct PointerRNA *
/* Helpers for Operators */
void uiAnimContextProperty(const struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA **prop, int *index);
void uiFileBrowseContextProperty(const struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA **prop);
void uiIDContextProperty(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA **prop);
/* Styled text draw */
void uiStyleFontSet(struct uiFontStyle *fs);

View File

@@ -153,6 +153,36 @@ static uiBlock *search_menu(bContext *C, ARegion *ar, void *arg_litem)
/************************ ID Template ***************************/
/* for new/open operators */
void uiIDContextProperty(bContext *C, PointerRNA *ptr, PropertyRNA **prop)
{
TemplateID *template;
ARegion *ar= CTX_wm_region(C);
uiBlock *block;
uiBut *but;
memset(ptr, 0, sizeof(*ptr));
*prop= NULL;
if(!ar)
return;
for(block=ar->uiblocks.first; block; block=block->next) {
for(but=block->buttons.first; but; but= but->next) {
/* find the button before the active one */
if((but->flag & (UI_BUT_LAST_ACTIVE|UI_ACTIVE))) {
if(but->func_argN) {
template= but->func_argN;
*ptr= template->ptr;
*prop= template->prop;
return;
}
}
}
}
}
static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
{
TemplateID *template= (TemplateID*)arg_litem;
@@ -167,11 +197,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
break;
case UI_ID_OPEN:
case UI_ID_ADD_NEW:
if(template->idlb->last) {
RNA_id_pointer_create(template->idlb->last, &idptr);
RNA_property_pointer_set(&template->ptr, template->prop, idptr);
RNA_property_update(C, &template->ptr, template->prop);
}
/* these call uiIDContextPropertySet */
break;
case UI_ID_DELETE:
memset(&idptr, 0, sizeof(idptr));
@@ -291,7 +317,7 @@ static void template_ID(bContext *C, uiBlock *block, TemplateID *template, Struc
int w= id?UI_UNIT_X: (flag & UI_ID_OPEN)? UI_UNIT_X*3: UI_UNIT_X*6;
if(newop) {
but= uiDefIconTextButO(block, BUT, newop, WM_OP_EXEC_REGION_WIN, ICON_ZOOMIN, (id)? "": "New", 0, 0, w, UI_UNIT_Y, NULL);
but= uiDefIconTextButO(block, BUT, newop, WM_OP_EXEC_DEFAULT, ICON_ZOOMIN, (id)? "": "New", 0, 0, w, UI_UNIT_Y, NULL);
uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ADD_NEW));
}
else {
@@ -307,7 +333,7 @@ static void template_ID(bContext *C, uiBlock *block, TemplateID *template, Struc
int w= id?UI_UNIT_X: (flag & UI_ID_ADD_NEW)? UI_UNIT_X*3: UI_UNIT_X*6;
if(openop) {
but= uiDefIconTextButO(block, BUT, openop, WM_OP_INVOKE_REGION_WIN, ICON_FILESEL, (id)? "": "Open", 0, 0, w, UI_UNIT_Y, NULL);
but= uiDefIconTextButO(block, BUT, openop, WM_OP_INVOKE_DEFAULT, ICON_FILESEL, (id)? "": "Open", 0, 0, w, UI_UNIT_Y, NULL);
uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_OPEN));
}
else {

View File

@@ -52,7 +52,6 @@
/************************ add/del boid rule operators *********************/
static int rule_add_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
ParticleSystem *psys= ptr.data;
Object *ob= ptr.id.data;
@@ -152,7 +151,6 @@ void BOID_OT_rule_del(wmOperatorType *ot)
/************************ move up/down boid rule operators *********************/
static int rule_move_up_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
ParticleSystem *psys= ptr.data;
Object *ob = ptr.id.data;
@@ -191,7 +189,6 @@ void BOID_OT_rule_move_up(wmOperatorType *ot)
static int rule_move_down_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
ParticleSystem *psys= ptr.data;
Object *ob = ptr.id.data;
@@ -363,7 +360,6 @@ void BOID_OT_state_move_up(wmOperatorType *ot)
static int state_move_down_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
ParticleSystem *psys= ptr.data;
BoidSettings *boids;

View File

@@ -436,9 +436,8 @@ void OBJECT_OT_material_slot_deselect(wmOperatorType *ot)
static int new_material_exec(bContext *C, wmOperator *op)
{
Material *ma= CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
Object *ob;
PointerRNA ptr;
int index;
PointerRNA ptr, idptr;
PropertyRNA *prop;
/* add or copy material */
if(ma)
@@ -446,18 +445,17 @@ static int new_material_exec(bContext *C, wmOperator *op)
else
ma= add_material("Material");
ma->id.us--; /* compensating for us++ in assign_material */
/* hook into UI */
uiIDContextProperty(C, &ptr, &prop);
/* attempt to assign to material slot */
ptr= CTX_data_pointer_get_type(C, "material_slot", &RNA_MaterialSlot);
if(prop) {
/* when creating new ID blocks, use is already 1, but RNA
* pointer se also increases user, so this compensates it */
ma->id.us--;
if(ptr.data) {
ob= ptr.id.data;
index= (Material**)ptr.data - ob->mat;
assign_material(ob, ma, index+1);
WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
RNA_id_pointer_create(&ma->id, &idptr);
RNA_property_pointer_set(&ptr, prop, idptr);
RNA_property_update(C, &ptr, prop);
}
WM_event_add_notifier(C, NC_MATERIAL|NA_ADDED, ma);
@@ -484,9 +482,8 @@ void MATERIAL_OT_new(wmOperatorType *ot)
static int new_texture_exec(bContext *C, wmOperator *op)
{
Tex *tex= CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data;
ID *id;
MTex *mtex;
PointerRNA ptr;
PointerRNA ptr, idptr;
PropertyRNA *prop;
/* add or copy texture */
if(tex)
@@ -494,23 +491,17 @@ static int new_texture_exec(bContext *C, wmOperator *op)
else
tex= add_texture("Texture");
id_us_min(&tex->id);
/* hook into UI */
uiIDContextProperty(C, &ptr, &prop);
/* attempt to assign to texture slot */
ptr= CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot);
if(prop) {
/* when creating new ID blocks, use is already 1, but RNA
* pointer se also increases user, so this compensates it */
tex->id.us--;
if(ptr.data) {
id= ptr.id.data;
mtex= ptr.data;
if(mtex) {
if(mtex->tex)
id_us_min(&mtex->tex->id);
mtex->tex= tex;
id_us_plus(&tex->id);
}
/* XXX nodes, notifier .. */
RNA_id_pointer_create(&tex->id, &idptr);
RNA_property_pointer_set(&ptr, prop, idptr);
RNA_property_update(C, &ptr, prop);
}
WM_event_add_notifier(C, NC_TEXTURE|NA_ADDED, tex);
@@ -536,8 +527,9 @@ void TEXTURE_OT_new(wmOperatorType *ot)
static int new_world_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
World *wo= CTX_data_pointer_get_type(C, "world", &RNA_World).data;
PointerRNA ptr, idptr;
PropertyRNA *prop;
/* add or copy world */
if(wo)
@@ -545,10 +537,18 @@ static int new_world_exec(bContext *C, wmOperator *op)
else
wo= add_world("World");
/* assign to scene */
if(scene->world)
id_us_min(&scene->world->id);
scene->world= wo;
/* hook into UI */
uiIDContextProperty(C, &ptr, &prop);
if(prop) {
/* when creating new ID blocks, use is already 1, but RNA
* pointer se also increases user, so this compensates it */
wo->id.us--;
RNA_id_pointer_create(&wo->id, &idptr);
RNA_property_pointer_set(&ptr, prop, idptr);
RNA_property_update(C, &ptr, prop);
}
WM_event_add_notifier(C, NC_WORLD|NA_ADDED, wo);

View File

@@ -958,17 +958,22 @@ void area_copy_data(ScrArea *sa1, ScrArea *sa2, int swap_space)
/* Note; SPACE_EMPTY is possible on new screens */
/* regions */
if(swap_space<2) {
st= BKE_spacetype_from_id(sa1->spacetype);
for(ar= sa1->regionbase.first; ar; ar= ar->next)
BKE_area_region_free(st, ar);
BLI_freelistN(&sa1->regionbase);
if(swap_space == 1) {
SWAP(ListBase, sa1->regionbase, sa2->regionbase);
}
st= BKE_spacetype_from_id(sa2->spacetype);
for(ar= sa2->regionbase.first; ar; ar= ar->next) {
ARegion *newar= BKE_area_region_copy(st, ar);
BLI_addtail(&sa1->regionbase, newar);
else {
if(swap_space<2) {
st= BKE_spacetype_from_id(sa1->spacetype);
for(ar= sa1->regionbase.first; ar; ar= ar->next)
BKE_area_region_free(st, ar);
BLI_freelistN(&sa1->regionbase);
}
st= BKE_spacetype_from_id(sa2->spacetype);
for(ar= sa2->regionbase.first; ar; ar= ar->next) {
ARegion *newar= BKE_area_region_copy(st, ar);
BLI_addtail(&sa1->regionbase, newar);
}
}
}

View File

@@ -86,6 +86,8 @@
#include "WM_api.h"
#include "WM_types.h"
#include "UI_interface.h"
#include "action_intern.h"
/* ************************************************************************** */
@@ -96,14 +98,25 @@
static int act_new_exec(bContext *C, wmOperator *op)
{
bAction *action;
PointerRNA ptr, idptr;
PropertyRNA *prop;
// XXX need to restore behaviour to copy old actions...
action= add_empty_action("Action");
/* combined with RNA property, this will assign & increase user,
so decrease here to compensate for that */
action->id.us--;
/* hook into UI */
uiIDContextProperty(C, &ptr, &prop);
if(prop) {
/* when creating new ID blocks, use is already 1, but RNA
* pointer se also increases user, so this compensates it */
action->id.us--;
RNA_id_pointer_create(&action->id, &idptr);
RNA_property_pointer_set(&ptr, prop, idptr);
RNA_property_update(C, &ptr, prop);
}
/* set notifier that keyframes have changed */
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);

View File

@@ -616,27 +616,61 @@ static void image_filesel(bContext *C, wmOperator *op, const char *path)
/******************** open image operator ********************/
static void open_init(bContext *C, wmOperator *op)
{
PropertyPointerRNA *pprop;
op->customdata= pprop= MEM_callocN(sizeof(PropertyPointerRNA), "OpenPropertyPointerRNA");
uiIDContextProperty(C, &pprop->ptr, &pprop->prop);
}
static int open_cancel(bContext *C, wmOperator *op)
{
MEM_freeN(op->customdata);
op->customdata= NULL;
return OPERATOR_CANCELLED;
}
static int open_exec(bContext *C, wmOperator *op)
{
SpaceImage *sima= CTX_wm_space_image(C);
Scene *scene= CTX_data_scene(C);
Object *obedit= CTX_data_edit_object(C);
PropertyPointerRNA *pprop;
PointerRNA idptr;
Image *ima= NULL;
char str[FILE_MAX];
RNA_string_get(op->ptr, "path", str);
ima= BKE_add_image_file(str, scene->r.cfra);
if(!ima)
if(!ima) {
if(op->customdata) MEM_freeN(op->customdata);
return OPERATOR_CANCELLED;
}
/* already set later */
ima->id.us--;
if(!op->customdata)
open_init(C, op);
/* hook into UI */
pprop= op->customdata;
if(pprop->prop) {
/* when creating new ID blocks, use is already 1, but RNA
* pointer se also increases user, so this compensates it */
ima->id.us--;
RNA_id_pointer_create(&ima->id, &idptr);
RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr);
RNA_property_update(C, &pprop->ptr, pprop->prop);
}
else if(sima)
ED_space_image_set(C, sima, scene, obedit, ima);
// XXX other users?
BKE_image_signal(ima, (sima)? &sima->iuser: NULL, IMA_SIGNAL_RELOAD);
if(sima)
ED_space_image_set(C, sima, scene, obedit, ima);
MEM_freeN(op->customdata);
return OPERATOR_FINISHED;
}
@@ -649,6 +683,8 @@ static int open_invoke(bContext *C, wmOperator *op, wmEvent *event)
if(RNA_property_is_set(op->ptr, "path"))
return open_exec(C, op);
open_init(C, op);
image_filesel(C, op, path);
return OPERATOR_RUNNING_MODAL;
@@ -663,6 +699,7 @@ void IMAGE_OT_open(wmOperatorType *ot)
/* api callbacks */
ot->exec= open_exec;
ot->invoke= open_invoke;
ot->cancel= open_cancel;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
@@ -1060,6 +1097,8 @@ static int new_exec(bContext *C, wmOperator *op)
Scene *scene;
Object *obedit;
Image *ima;
PointerRNA ptr, idptr;
PropertyRNA *prop;
char name[22];
float color[4];
int width, height, floatbuf, uvtestgrid;
@@ -1078,12 +1117,27 @@ static int new_exec(bContext *C, wmOperator *op)
color[3]= RNA_float_get(op->ptr, "alpha");
ima = BKE_add_image_size(width, height, name, floatbuf, uvtestgrid, color);
ima->id.us--; /* already set later */
if(sima) { // XXX other users?
BKE_image_signal(sima->image, &sima->iuser, IMA_SIGNAL_USER_NEW_IMAGE);
ED_space_image_set(C, sima, scene, obedit, ima);
if(!ima)
return OPERATOR_CANCELLED;
/* hook into UI */
uiIDContextProperty(C, &ptr, &prop);
if(prop) {
/* when creating new ID blocks, use is already 1, but RNA
* pointer se also increases user, so this compensates it */
ima->id.us--;
RNA_id_pointer_create(&ima->id, &idptr);
RNA_property_pointer_set(&ptr, prop, idptr);
RNA_property_update(C, &ptr, prop);
}
else if(sima)
ED_space_image_set(C, sima, scene, obedit, ima);
// XXX other users?
BKE_image_signal(ima, (sima)? &sima->iuser: NULL, IMA_SIGNAL_USER_NEW_IMAGE);
return OPERATOR_FINISHED;
}

View File

@@ -159,10 +159,24 @@ static int new_exec(bContext *C, wmOperator *op)
{
SpaceText *st= CTX_wm_space_text(C);
Text *text;
PointerRNA ptr, idptr;
PropertyRNA *prop;
text= add_empty_text("Text");
if(st) {
/* hook into UI */
uiIDContextProperty(C, &ptr, &prop);
if(prop) {
/* when creating new ID blocks, use is already 1, but RNA
* pointer se also increases user, so this compensates it */
text->id.us--;
RNA_id_pointer_create(&text->id, &idptr);
RNA_property_pointer_set(&ptr, prop, idptr);
RNA_property_update(C, &ptr, prop);
}
else if(st) {
st->text= text;
st->top= 0;
}
@@ -186,23 +200,61 @@ void TEXT_OT_new(wmOperatorType *ot)
/******************* open operator *********************/
static void open_init(bContext *C, wmOperator *op)
{
PropertyPointerRNA *pprop;
op->customdata= pprop= MEM_callocN(sizeof(PropertyPointerRNA), "OpenPropertyPointerRNA");
uiIDContextProperty(C, &pprop->ptr, &pprop->prop);
}
static int open_cancel(bContext *C, wmOperator *op)
{
MEM_freeN(op->customdata);
return OPERATOR_CANCELLED;
}
static int open_exec(bContext *C, wmOperator *op)
{
SpaceText *st= CTX_wm_space_text(C);
Text *text;
PropertyPointerRNA *pprop;
PointerRNA idptr;
char str[FILE_MAX];
RNA_string_get(op->ptr, "path", str);
text= add_text(str, G.sce);
if(st) {
if(!text) {
if(op->customdata) MEM_freeN(op->customdata);
return OPERATOR_CANCELLED;
}
if(!op->customdata)
open_init(C, op);
/* hook into UI */
pprop= op->customdata;
if(pprop->prop) {
/* when creating new ID blocks, use is already 1, but RNA
* pointer se also increases user, so this compensates it */
text->id.us--;
RNA_id_pointer_create(&text->id, &idptr);
RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr);
RNA_property_update(C, &pprop->ptr, pprop->prop);
}
else if(st) {
st->text= text;
st->top= 0;
}
WM_event_add_notifier(C, NC_TEXT|NA_ADDED, text);
MEM_freeN(op->customdata);
return OPERATOR_FINISHED;
}
@@ -214,6 +266,7 @@ static int open_invoke(bContext *C, wmOperator *op, wmEvent *event)
if(RNA_property_is_set(op->ptr, "path"))
return open_exec(C, op);
open_init(C, op);
RNA_string_set(op->ptr, "path", path);
WM_event_add_fileselect(C, op);
@@ -230,6 +283,7 @@ void TEXT_OT_open(wmOperatorType *ot)
/* api callbacks */
ot->exec= open_exec;
ot->invoke= open_invoke;
ot->cancel= open_cancel;
ot->poll= text_new_poll;
/* properties */

View File

@@ -54,6 +54,11 @@ typedef struct PointerRNA {
void *data;
} PointerRNA;
typedef struct PropertyPointerRNA {
PointerRNA ptr;
struct PropertyRNA *prop;
} PropertyPointerRNA;
/* Property */
typedef enum PropertyType {

View File

@@ -298,6 +298,8 @@ static int wm_operator_exec(bContext *C, wmOperator *op, int repeat)
uiPupMenuReports(C, op->reports);
if(retval & OPERATOR_FINISHED) {
op->customdata= NULL;
if(op->type->flag & OPTYPE_UNDO)
ED_undo_push_op(C, op);
@@ -427,6 +429,8 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, P
}
if(retval & OPERATOR_FINISHED) {
op->customdata= NULL;
if(ot->flag & OPTYPE_UNDO)
ED_undo_push_op(C, op);
@@ -813,6 +817,8 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand
}
if(retval & OPERATOR_FINISHED) {
op->customdata= NULL;
if(ot->flag & OPTYPE_UNDO)
ED_undo_push_op(C, op);
@@ -936,9 +942,9 @@ static int wm_handler_fileselect_call(bContext *C, ListBase *handlers, wmEventHa
/* remlink now, for load file case */
BLI_remlink(handlers, handler);
wm_handler_op_context(C, handler);
if(event->val==EVT_FILESELECT_EXEC) {
wm_handler_op_context(C, handler);
/* a bit weak, might become arg for WM_event_fileselect? */
/* XXX also extension code in image-save doesnt work for this yet */
if(strncmp(handler->op->type->name, "Save", 4)==0) {
@@ -954,11 +960,15 @@ static int wm_handler_fileselect_call(bContext *C, ListBase *handlers, wmEventHa
WM_operator_free(handler->op);
}
CTX_wm_area_set(C, NULL);
}
else
else {
if(handler->op->type->cancel)
handler->op->type->cancel(C, handler->op);
WM_operator_free(handler->op);
}
CTX_wm_area_set(C, NULL);
wm_event_free_handler(handler);
if(path)