static void rna_GPencil_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr)) { WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL); }
static void rna_Paint_brush_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { Brush *br = (Brush *)ptr->data; BKE_paint_invalidate_overlay_all(); WM_main_add_notifier(NC_BRUSH | NA_EDITED, br); }
static void render_endjob(void *rjv) { RenderJob *rj = rjv; /* this render may be used again by the sequencer without the active 'Render' where the callbacks * would be re-assigned. assign dummy callbacks to avoid referencing freed renderjobs bug [#24508] */ RE_InitRenderCB(rj->re); if (rj->main != G.main) BKE_main_free(rj->main); /* else the frame will not update for the original value */ if (rj->anim && !(rj->scene->r.scemode & R_NO_FRAME_UPDATE)) { /* possible this fails of loading new file while rendering */ if (G.main->wm.first) { ED_update_for_newframe(G.main, rj->scene, 1); } } /* XXX above function sets all tags in nodes */ ntreeCompositClearTags(rj->scene->nodetree); /* potentially set by caller */ rj->scene->r.scemode &= ~R_NO_FRAME_UPDATE; if (rj->srl) { nodeUpdateID(rj->scene->nodetree, &rj->scene->id); WM_main_add_notifier(NC_NODE | NA_EDITED, rj->scene); } if (rj->sa) { render_image_restore_layer(rj); } /* XXX render stability hack */ G.is_rendering = false; WM_main_add_notifier(NC_SCENE | ND_RENDER_RESULT, NULL); /* Partial render result will always update display buffer * for first render layer only. This is nice because you'll * see render progress during rendering, but it ends up in * wrong display buffer shown after rendering. * * The code below will mark display buffer as invalid after * rendering in case multiple layers were rendered, which * ensures display buffer matches render layer after * rendering. * * Perhaps proper way would be to toggle active render * layer in image editor and job, so we always display * layer being currently rendered. But this is not so much * trivial at this moment, especially because of external * engine API, so lets use simple and robust way for now * - sergey - */ if (rj->scene->r.layers.first != rj->scene->r.layers.last || rj->image_outdated) { void *lock; Image *ima = rj->image; ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &rj->iuser, &lock); if (ibuf) ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; BKE_image_release_ibuf(ima, ibuf, lock); } /* Finally unlock the user interface (if it was locked). */ if (rj->interface_locked) { Scene *scene; /* Interface was locked, so window manager couldn't have been changed * and using one from Global will unlock exactly the same manager as * was locked before running the job. */ WM_set_locked_interface(G.main->wm.first, false); /* We've freed all the derived caches before rendering, which is * effectively the same as if we re-loaded the file. * * So let's not try being smart here and just reset all updated * scene layers and use generic DAG_on_visible_update. */ for (scene = G.main->scene.first; scene; scene = scene->id.next) { scene->lay_updated = 0; } DAG_on_visible_update(G.main, false); } }
static void render_endjob(void *rjv) { RenderJob *rj = rjv; /* this render may be used again by the sequencer without the active 'Render' where the callbacks * would be re-assigned. assign dummy callbacks to avoid referencing freed renderjobs bug [#24508] */ RE_InitRenderCB(rj->re); if (rj->main != G.main) free_main(rj->main); /* else the frame will not update for the original value */ if (!(rj->scene->r.scemode & R_NO_FRAME_UPDATE)) { /* possible this fails of loading new file while rendering */ if (G.main->wm.first) { ED_update_for_newframe(G.main, rj->scene, 1); } } /* XXX above function sets all tags in nodes */ ntreeCompositClearTags(rj->scene->nodetree); /* potentially set by caller */ rj->scene->r.scemode &= ~R_NO_FRAME_UPDATE; if (rj->srl) { nodeUpdateID(rj->scene->nodetree, &rj->scene->id); WM_main_add_notifier(NC_NODE | NA_EDITED, rj->scene); } /* XXX render stability hack */ G.is_rendering = FALSE; WM_main_add_notifier(NC_WINDOW, NULL); /* Partial render result will always update display buffer * for first render layer only. This is nice because you'll * see render progress during rendering, but it ends up in * wrong display buffer shown after rendering. * * The code below will mark display buffer as invalid after * rendering in case multiple layers were rendered, which * ensures display buffer matches render layer after * rendering. * * Perhaps proper way would be to toggle active render * layer in image editor and job, so we always display * layer being currently rendered. But this is not so much * trivial at this moment, especially because of external * engine API, so lets use simple and robust way for now * - sergey - */ if (rj->scene->r.layers.first != rj->scene->r.layers.last) { void *lock; Image *ima = rj->image; ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &rj->iuser, &lock); if (ibuf) ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; BKE_image_release_ibuf(ima, ibuf, lock); } }
static Sequence *rna_Sequences_new_effect(ID *id, Editing *ed, ReportList *reports, const char *name, int type, int channel, int frame_start, int frame_end, Sequence *seq1, Sequence *seq2, Sequence *seq3) { Scene *scene = (Scene *)id; Sequence *seq; struct SeqEffectHandle sh; int num_inputs = BKE_sequence_effect_get_num_inputs(type); switch (num_inputs) { case 0: if (frame_end <= frame_start) { BKE_report(reports, RPT_ERROR, "Sequences.new_effect: end frame not set"); return NULL; } break; case 1: if (seq1 == NULL) { BKE_report(reports, RPT_ERROR, "Sequences.new_effect: effect takes 1 input sequence"); return NULL; } break; case 2: if (seq1 == NULL || seq2 == NULL) { BKE_report(reports, RPT_ERROR, "Sequences.new_effect: effect takes 2 input sequences"); return NULL; } break; case 3: if (seq1 == NULL || seq2 == NULL || seq3 == NULL) { BKE_report(reports, RPT_ERROR, "Sequences.new_effect: effect takes 3 input sequences"); return NULL; } break; default: BKE_reportf(reports, RPT_ERROR, "Sequences.new_effect: effect expects more than 3 inputs (%d, should never happen!)", num_inputs); return NULL; } seq = alloc_generic_sequence(ed, name, frame_start, channel, type, NULL); sh = BKE_sequence_get_effect(seq); seq->seq1 = seq1; seq->seq2 = seq2; seq->seq3 = seq3; sh.init(seq); if (!seq1) { /* effect has no deps */ seq->len = 1; BKE_sequence_tx_set_final_right(seq, frame_end); } seq->flag |= SEQ_USE_EFFECT_DEFAULT_FADE; BKE_sequence_calc_disp(scene, seq); WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, scene); return seq; }
static StructRNA *rna_Panel_register(Main *bmain, ReportList *reports, void *data, const char *identifier, StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free) { ARegionType *art; PanelType *pt, dummypt = {NULL}; Panel dummypanel= {NULL}; PointerRNA dummyptr; int have_function[3]; /* setup dummy panel & panel type to store static properties in */ dummypanel.type= &dummypt; RNA_pointer_create(NULL, &RNA_Panel, &dummypanel, &dummyptr); /* validate the python class */ if(validate(&dummyptr, data, have_function) != 0) return NULL; if(strlen(identifier) >= sizeof(dummypt.idname)) { BKE_reportf(reports, RPT_ERROR, "registering panel class: '%s' is too long, maximum length is %d", identifier, (int)sizeof(dummypt.idname)); return NULL; } if(!(art=region_type_find(reports, dummypt.space_type, dummypt.region_type))) return NULL; /* check if we have registered this panel type before, and remove it */ for(pt=art->paneltypes.first; pt; pt=pt->next) { if(strcmp(pt->idname, dummypt.idname) == 0) { if(pt->ext.srna) rna_Panel_unregister(bmain, pt->ext.srna); else BLI_freelinkN(&art->paneltypes, pt); break; } } /* create a new panel type */ pt= MEM_callocN(sizeof(PanelType), "python buttons panel"); memcpy(pt, &dummypt, sizeof(dummypt)); pt->ext.srna= RNA_def_struct(&BLENDER_RNA, pt->idname, "Panel"); pt->ext.data= data; pt->ext.call= call; pt->ext.free= free; RNA_struct_blender_type_set(pt->ext.srna, pt); RNA_def_struct_flag(pt->ext.srna, STRUCT_NO_IDPROPERTIES); pt->poll= (have_function[0])? panel_poll: NULL; pt->draw= (have_function[1])? panel_draw: NULL; pt->draw_header= (have_function[2])? panel_draw_header: NULL; /* XXX use "no header" flag for some ordering of panels until we have real panel ordering */ if(pt->flag & PNL_NO_HEADER) { PanelType *pth = art->paneltypes.first; while(pth && pth->flag & PNL_NO_HEADER) pth=pth->next; if(pth) BLI_insertlinkbefore(&art->paneltypes, pth, pt); else BLI_addtail(&art->paneltypes, pt); } else BLI_addtail(&art->paneltypes, pt); /* update while blender is running */ WM_main_add_notifier(NC_SCREEN|NA_EDITED, NULL); return pt->ext.srna; }
static void rna_Armature_redraw_data(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { ID *id = ptr->id.data; WM_main_add_notifier(NC_GEOM | ND_DATA, id); }
/* Given a KeyingSet and context info (if required), modify keyframes for the channels specified * by the KeyingSet. This takes into account many of the different combinations of using KeyingSets. * Returns the number of channels that keyframes were added to */ int ANIM_apply_keyingset(bContext *C, ListBase *dsources, bAction *act, KeyingSet *ks, short mode, float cfra) { Scene *scene = CTX_data_scene(C); ReportList *reports = CTX_wm_reports(C); KS_Path *ksp; int kflag = 0, success = 0; const char *groupname = NULL; /* sanity checks */ if (ks == NULL) return 0; /* get flags to use */ if (mode == MODIFYKEY_MODE_INSERT) { /* use KeyingSet's flags as base */ kflag = ks->keyingflag; /* supplement with info from the context */ kflag |= ANIM_get_keyframing_flags(scene, 1); } else if (mode == MODIFYKEY_MODE_DELETE) kflag = 0; /* if relative Keying Sets, poll and build up the paths */ success = ANIM_validate_keyingset(C, dsources, ks); if (success != 0) { /* return error code if failed */ return success; } /* apply the paths as specified in the KeyingSet now */ for (ksp = ks->paths.first; ksp; ksp = ksp->next) { int arraylen, i; short kflag2; /* skip path if no ID pointer is specified */ if (ksp->id == NULL) { BKE_reportf(reports, RPT_WARNING, "Skipping path in keying set, as it has no ID (KS = '%s', path = '%s[%d]')", ks->name, ksp->rna_path, ksp->array_index); continue; } /* since keying settings can be defined on the paths too, extend the path before using it */ kflag2 = (kflag | ksp->keyingflag); /* get pointer to name of group to add channels to */ if (ksp->groupmode == KSP_GROUP_NONE) groupname = NULL; else if (ksp->groupmode == KSP_GROUP_KSNAME) groupname = ks->name; else groupname = ksp->group; /* init arraylen and i - arraylen should be greater than i so that * normal non-array entries get keyframed correctly */ i = ksp->array_index; arraylen = i; /* get length of array if whole array option is enabled */ if (ksp->flag & KSP_FLAG_WHOLE_ARRAY) { PointerRNA id_ptr, ptr; PropertyRNA *prop; RNA_id_pointer_create(ksp->id, &id_ptr); if (RNA_path_resolve_property(&id_ptr, ksp->rna_path, &ptr, &prop)) arraylen = RNA_property_array_length(&ptr, prop); } /* we should do at least one step */ if (arraylen == i) arraylen++; /* for each possible index, perform operation * - assume that arraylen is greater than index */ for (; i < arraylen; i++) { /* action to take depends on mode */ if (mode == MODIFYKEY_MODE_INSERT) success += insert_keyframe(reports, ksp->id, act, groupname, ksp->rna_path, i, cfra, kflag2); else if (mode == MODIFYKEY_MODE_DELETE) success += delete_keyframe(reports, ksp->id, act, groupname, ksp->rna_path, i, cfra, kflag2); } /* set recalc-flags */ switch (GS(ksp->id->name)) { case ID_OB: /* Object (or Object-Related) Keyframes */ { Object *ob = (Object *)ksp->id; // XXX: only object transforms? DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); break; } } /* send notifiers for updates (this doesn't require context to work!) */ WM_main_add_notifier(NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL); } /* return the number of channels successfully affected */ return success; }
static void preview_endjob(void *data) { PreviewJob *pj = data; WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, pj->scene); }
static void rna_ImaPaint_viewport_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr)) { /* not the best solution maybe, but will refresh the 3D viewport */ WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL); }
static void rna_Text_write(Text *text, const char *str) { BKE_text_write(text, str); WM_main_add_notifier(NC_TEXT|NA_EDITED, text); }
static void rna_Text_clear(Text *text) { BKE_text_clear(text); WM_main_add_notifier(NC_TEXT|NA_EDITED, text); }
static StructRNA *rna_Menu_register(Main *bmain, ReportList *reports, void *data, const char *identifier, StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free) { MenuType *mt, dummymt = {NULL}; Menu dummymenu = {NULL}; PointerRNA dummymtr; int have_function[2]; size_t over_alloc = 0; /* warning, if this becomes a bess, we better do another alloc */ size_t description_size = 0; char _menu_descr[RNA_DYN_DESCR_MAX]; /* setup dummy menu & menu type to store static properties in */ dummymenu.type = &dummymt; _menu_descr[0] = '\0'; dummymenu.type->description = _menu_descr; RNA_pointer_create(NULL, &RNA_Menu, &dummymenu, &dummymtr); /* We have to set default context! Else we get a void string... */ strcpy(dummymt.translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); /* validate the python class */ if (validate(&dummymtr, data, have_function) != 0) return NULL; if (strlen(identifier) >= sizeof(dummymt.idname)) { BKE_reportf(reports, RPT_ERROR, "Registering menu class: '%s' is too long, maximum length is %d", identifier, (int)sizeof(dummymt.idname)); return NULL; } /* check if we have registered this menu type before, and remove it */ mt = WM_menutype_find(dummymt.idname, true); if (mt && mt->ext.srna) rna_Menu_unregister(bmain, mt->ext.srna); /* create a new menu type */ if (_menu_descr[0]) { description_size = strlen(_menu_descr) + 1; over_alloc += description_size; } mt = MEM_callocN(sizeof(MenuType) + over_alloc, "python buttons menu"); memcpy(mt, &dummymt, sizeof(dummymt)); if (_menu_descr[0]) { char *buf = (char *)(mt + 1); memcpy(buf, _menu_descr, description_size); mt->description = buf; } else mt->description = ""; mt->ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, mt->idname, &RNA_Menu); RNA_def_struct_translation_context(mt->ext.srna, mt->translation_context); mt->ext.data = data; mt->ext.call = call; mt->ext.free = free; RNA_struct_blender_type_set(mt->ext.srna, mt); RNA_def_struct_flag(mt->ext.srna, STRUCT_NO_IDPROPERTIES); mt->poll = (have_function[0]) ? menu_poll : NULL; mt->draw = (have_function[1]) ? menu_draw : NULL; WM_menutype_add(mt); /* update while blender is running */ WM_main_add_notifier(NC_WINDOW, NULL); return mt->ext.srna; }
static StructRNA *rna_Panel_register(Main *bmain, ReportList *reports, void *data, const char *identifier, StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free) { ARegionType *art; PanelType *pt, dummypt = {NULL}; Panel dummypanel = {NULL}; PointerRNA dummyptr; int have_function[3]; /* setup dummy panel & panel type to store static properties in */ dummypanel.type = &dummypt; RNA_pointer_create(NULL, &RNA_Panel, &dummypanel, &dummyptr); /* We have to set default context! Else we get a void string... */ strcpy(dummypt.translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); /* validate the python class */ if (validate(&dummyptr, data, have_function) != 0) return NULL; if (strlen(identifier) >= sizeof(dummypt.idname)) { BKE_reportf(reports, RPT_ERROR, "Registering panel class: '%s' is too long, maximum length is %d", identifier, (int)sizeof(dummypt.idname)); return NULL; } if ((dummypt.category[0] == '\0') && (dummypt.region_type == RGN_TYPE_TOOLS)) { /* Use a fallback, otherwise an empty value will draw the panel in every category. */ strcpy(dummypt.category, PNL_CATEGORY_FALLBACK); } if (!(art = region_type_find(reports, dummypt.space_type, dummypt.region_type))) return NULL; /* check if we have registered this panel type before, and remove it */ for (pt = art->paneltypes.first; pt; pt = pt->next) { if (STREQ(pt->idname, dummypt.idname)) { if (pt->ext.srna) rna_Panel_unregister(bmain, pt->ext.srna); else BLI_freelinkN(&art->paneltypes, pt); break; } } /* create a new panel type */ pt = MEM_callocN(sizeof(PanelType), "python buttons panel"); memcpy(pt, &dummypt, sizeof(dummypt)); pt->ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, pt->idname, &RNA_Panel); RNA_def_struct_translation_context(pt->ext.srna, pt->translation_context); pt->ext.data = data; pt->ext.call = call; pt->ext.free = free; RNA_struct_blender_type_set(pt->ext.srna, pt); RNA_def_struct_flag(pt->ext.srna, STRUCT_NO_IDPROPERTIES); pt->poll = (have_function[0]) ? panel_poll : NULL; pt->draw = (have_function[1]) ? panel_draw : NULL; pt->draw_header = (have_function[2]) ? panel_draw_header : NULL; /* XXX use "no header" flag for some ordering of panels until we have real panel ordering */ if (pt->flag & PNL_NO_HEADER) { PanelType *pth = art->paneltypes.first; while (pth && pth->flag & PNL_NO_HEADER) pth = pth->next; if (pth) BLI_insertlinkbefore(&art->paneltypes, pth, pt); else BLI_addtail(&art->paneltypes, pt); } else BLI_addtail(&art->paneltypes, pt); /* update while blender is running */ WM_main_add_notifier(NC_WINDOW, NULL); return pt->ext.srna; }