improve image sequence usability, problem was when the image didn't load there was no way to know the frame that blender was attempting to read.
added a label for image sequence images showing the image file's frame, even when not able to load, this also gives realtime feedback to the user while dragging the frame offset/start/duration buttons about so they can better understand how these settings work.
This commit is contained in:
@@ -133,6 +133,7 @@ void BKE_image_assign_ibuf(struct Image *ima, struct ImBuf *ibuf);
|
||||
|
||||
/* called on frame change or before render */
|
||||
void BKE_image_user_calc_frame(struct ImageUser *iuser, int cfra, int fieldnr);
|
||||
int BKE_image_user_get_frame(const struct ImageUser *iuser, int cfra, int fieldnr);
|
||||
|
||||
/* fix things in ImageUser when new image gets assigned */
|
||||
void BKE_image_user_new_image(struct Image *ima, struct ImageUser *iuser);
|
||||
|
||||
@@ -1671,8 +1671,15 @@ static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame)
|
||||
|
||||
/* read ibuf */
|
||||
ibuf = IMB_loadiffname(name, flag);
|
||||
if(G.f & G_DEBUG) printf("loaded %s\n", name);
|
||||
|
||||
|
||||
#if 0
|
||||
if(ibuf) {
|
||||
printf(AT" loaded %s\n", name);
|
||||
} else {
|
||||
printf(AT" missed %s\n", name);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ibuf) {
|
||||
#ifdef WITH_OPENEXR
|
||||
/* handle multilayer case, don't assign ibuf. will be handled in BKE_image_get_ibuf */
|
||||
@@ -2228,21 +2235,19 @@ void BKE_image_release_ibuf(Image *ima, void *lock)
|
||||
/* warning, this can allocate generated images */
|
||||
ImBuf *BKE_image_get_ibuf(Image *ima, ImageUser *iuser)
|
||||
{
|
||||
/* here (+fie_ima/2-1) makes sure that division happens correctly */
|
||||
return BKE_image_acquire_ibuf(ima, iuser, NULL);
|
||||
}
|
||||
|
||||
void BKE_image_user_calc_frame(ImageUser *iuser, int cfra, int fieldnr)
|
||||
int BKE_image_user_get_frame(const ImageUser *iuser, int cfra, int fieldnr)
|
||||
{
|
||||
int len;
|
||||
|
||||
/* here (+fie_ima/2-1) makes sure that division happens correctly */
|
||||
len= (iuser->fie_ima*iuser->frames)/2;
|
||||
|
||||
const int len= (iuser->fie_ima*iuser->frames)/2;
|
||||
|
||||
if(len==0) {
|
||||
iuser->framenr= 0;
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
int imanr;
|
||||
int framenr;
|
||||
cfra= cfra - iuser->sfra+1;
|
||||
|
||||
/* cyclic */
|
||||
@@ -2251,31 +2256,38 @@ void BKE_image_user_calc_frame(ImageUser *iuser, int cfra, int fieldnr)
|
||||
if(cfra < 0) cfra+= len;
|
||||
if(cfra==0) cfra= len;
|
||||
}
|
||||
|
||||
|
||||
if(cfra<0) cfra= 0;
|
||||
else if(cfra>len) cfra= len;
|
||||
|
||||
|
||||
/* convert current frame to current field */
|
||||
cfra= 2*(cfra);
|
||||
if(fieldnr) cfra++;
|
||||
|
||||
|
||||
/* transform to images space */
|
||||
imanr= (cfra+iuser->fie_ima-2)/iuser->fie_ima;
|
||||
if(imanr>iuser->frames) imanr= iuser->frames;
|
||||
imanr+= iuser->offset;
|
||||
|
||||
framenr= (cfra+iuser->fie_ima-2)/iuser->fie_ima;
|
||||
if(framenr>iuser->frames) framenr= iuser->frames;
|
||||
framenr+= iuser->offset;
|
||||
|
||||
if(iuser->cycl) {
|
||||
imanr= ( (imanr) % len );
|
||||
while(imanr < 0) imanr+= len;
|
||||
if(imanr==0) imanr= len;
|
||||
framenr= ( (framenr) % len );
|
||||
while(framenr < 0) framenr+= len;
|
||||
if(framenr==0) framenr= len;
|
||||
}
|
||||
|
||||
/* allows image users to handle redraws */
|
||||
if(iuser->flag & IMA_ANIM_ALWAYS)
|
||||
if(imanr!=iuser->framenr)
|
||||
iuser->flag |= IMA_ANIM_REFRESHED;
|
||||
|
||||
iuser->framenr= imanr;
|
||||
if(iuser->ok==0) iuser->ok= 1;
|
||||
|
||||
return framenr;
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_image_user_calc_frame(ImageUser *iuser, int cfra, int fieldnr)
|
||||
{
|
||||
const int framenr= BKE_image_user_get_frame(iuser, cfra, fieldnr);
|
||||
|
||||
/* allows image users to handle redraws */
|
||||
if(iuser->flag & IMA_ANIM_ALWAYS)
|
||||
if(framenr!=iuser->framenr)
|
||||
iuser->flag |= IMA_ANIM_REFRESHED;
|
||||
|
||||
iuser->framenr= framenr;
|
||||
if(iuser->ok==0) iuser->ok= 1;
|
||||
}
|
||||
|
||||
@@ -119,53 +119,62 @@ static void do_image_panel_events(bContext *C, void *UNUSED(arg), int event)
|
||||
WM_event_add_notifier(C, NC_IMAGE, sima->image);
|
||||
}
|
||||
|
||||
static void image_info(Image *ima, ImBuf *ibuf, char *str)
|
||||
static void image_info(Scene *scene, ImageUser *iuser, Image *ima, ImBuf *ibuf, char *str)
|
||||
{
|
||||
int ofs= 0;
|
||||
|
||||
|
||||
str[0]= 0;
|
||||
|
||||
if(ima==NULL) return;
|
||||
|
||||
if(ibuf==NULL) {
|
||||
sprintf(str, "Can not get an image");
|
||||
return;
|
||||
}
|
||||
|
||||
if(ima->source==IMA_SRC_MOVIE) {
|
||||
ofs= sprintf(str, "Movie");
|
||||
if(ima->anim)
|
||||
ofs+= sprintf(str+ofs, "%d frs", IMB_anim_get_duration(ima->anim));
|
||||
}
|
||||
else
|
||||
ofs= sprintf(str, "Image");
|
||||
|
||||
ofs+= sprintf(str+ofs, ": size %d x %d,", ibuf->x, ibuf->y);
|
||||
|
||||
if(ibuf->rect_float) {
|
||||
if(ibuf->channels!=4) {
|
||||
ofs+= sprintf(str+ofs, "%d float channel(s)", ibuf->channels);
|
||||
}
|
||||
else if(ibuf->depth==32)
|
||||
ofs+= sprintf(str+ofs, " RGBA float");
|
||||
else
|
||||
ofs+= sprintf(str+ofs, " RGB float");
|
||||
ofs+= sprintf(str, "Can't Load Image");
|
||||
}
|
||||
else {
|
||||
if(ibuf->depth==32)
|
||||
ofs+= sprintf(str+ofs, " RGBA byte");
|
||||
if(ima->source==IMA_SRC_MOVIE) {
|
||||
ofs+= sprintf(str, "Movie");
|
||||
if(ima->anim)
|
||||
ofs+= sprintf(str+ofs, "%d frs", IMB_anim_get_duration(ima->anim));
|
||||
}
|
||||
else
|
||||
ofs+= sprintf(str+ofs, " RGB byte");
|
||||
}
|
||||
if(ibuf->zbuf || ibuf->zbuf_float)
|
||||
ofs+= sprintf(str+ofs, " + Z");
|
||||
ofs+= sprintf(str, "Image");
|
||||
|
||||
if(ima->source==IMA_SRC_SEQUENCE) {
|
||||
char *file= BLI_last_slash(ibuf->name);
|
||||
if(file==NULL) file= ibuf->name;
|
||||
else file++;
|
||||
sprintf(str+ofs, ", %s", file);
|
||||
ofs+= sprintf(str+ofs, ": size %d x %d,", ibuf->x, ibuf->y);
|
||||
|
||||
if(ibuf->rect_float) {
|
||||
if(ibuf->channels!=4) {
|
||||
ofs+= sprintf(str+ofs, "%d float channel(s)", ibuf->channels);
|
||||
}
|
||||
else if(ibuf->depth==32)
|
||||
ofs+= sprintf(str+ofs, " RGBA float");
|
||||
else
|
||||
ofs+= sprintf(str+ofs, " RGB float");
|
||||
}
|
||||
else {
|
||||
if(ibuf->depth==32)
|
||||
ofs+= sprintf(str+ofs, " RGBA byte");
|
||||
else
|
||||
ofs+= sprintf(str+ofs, " RGB byte");
|
||||
}
|
||||
if(ibuf->zbuf || ibuf->zbuf_float)
|
||||
ofs+= sprintf(str+ofs, " + Z");
|
||||
|
||||
if(ima->source==IMA_SRC_SEQUENCE) {
|
||||
char *file= BLI_last_slash(ibuf->name);
|
||||
if(file==NULL) file= ibuf->name;
|
||||
else file++;
|
||||
ofs+= sprintf(str+ofs, ", %s", file);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* the frame number, even if we cant */
|
||||
if(ima->source==IMA_SRC_SEQUENCE) {
|
||||
/* don't use iuser->framenr directly because it may not be updated if auto-refresh is off */
|
||||
const int framenr= BKE_image_user_get_frame(iuser, CFRA, 0);
|
||||
ofs+= sprintf(str+ofs, ", Frame: %d", framenr);
|
||||
}
|
||||
|
||||
(void)ofs;
|
||||
}
|
||||
|
||||
/* gets active viewer user */
|
||||
@@ -816,7 +825,7 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
|
||||
|
||||
if(ima->source == IMA_SRC_VIEWER) {
|
||||
ibuf= BKE_image_acquire_ibuf(ima, iuser, &lock);
|
||||
image_info(ima, ibuf, str);
|
||||
image_info(scene, iuser, ima, ibuf, str);
|
||||
BKE_image_release_ibuf(ima, lock);
|
||||
|
||||
uiItemL(layout, ima->id.name+2, ICON_NONE);
|
||||
@@ -888,7 +897,7 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
|
||||
else if(ima->source != IMA_SRC_GENERATED) {
|
||||
if(compact == 0) {
|
||||
ibuf= BKE_image_acquire_ibuf(ima, iuser, &lock);
|
||||
image_info(ima, ibuf, str);
|
||||
image_info(scene, iuser, ima, ibuf, str);
|
||||
BKE_image_release_ibuf(ima, lock);
|
||||
uiItemL(layout, str, ICON_NONE);
|
||||
}
|
||||
|
||||
@@ -482,6 +482,7 @@ static void node_composit_buts_image(uiLayout *layout, bContext *C, PointerRNA *
|
||||
bNode *node= ptr->data;
|
||||
PointerRNA imaptr;
|
||||
PropertyRNA *prop;
|
||||
int source;
|
||||
|
||||
uiTemplateID(layout, C, ptr, "image", NULL, "IMAGE_OT_open", NULL);
|
||||
|
||||
@@ -495,7 +496,19 @@ static void node_composit_buts_image(uiLayout *layout, bContext *C, PointerRNA *
|
||||
|
||||
uiItemR(col, &imaptr, "source", 0, NULL, ICON_NONE);
|
||||
|
||||
if (ELEM(RNA_enum_get(&imaptr, "source"), IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) {
|
||||
source= RNA_enum_get(&imaptr, "source");
|
||||
|
||||
if(source == IMA_SRC_SEQUENCE) {
|
||||
/* don't use iuser->framenr directly because it may not be updated if auto-refresh is off */
|
||||
Scene *scene= CTX_data_scene(C);
|
||||
ImageUser *iuser= node->storage;
|
||||
char tstr[32];
|
||||
const int framenr= BKE_image_user_get_frame(iuser, CFRA, 0);
|
||||
BLI_snprintf(tstr, sizeof(tstr), "Frame: %d", framenr);
|
||||
uiItemL(layout, tstr, ICON_NONE);
|
||||
}
|
||||
|
||||
if (ELEM(source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) {
|
||||
col= uiLayoutColumn(layout, 1);
|
||||
uiItemR(col, ptr, "frame_duration", 0, NULL, ICON_NONE);
|
||||
uiItemR(col, ptr, "frame_start", 0, NULL, ICON_NONE);
|
||||
|
||||
@@ -1262,29 +1262,29 @@ static void def_cmp_image(StructRNA *srna)
|
||||
prop = RNA_def_property(srna, "frame_duration", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "frames");
|
||||
RNA_def_property_range(prop, 0, MAXFRAMEF);
|
||||
RNA_def_property_ui_text(prop, "Frames", "Number of images used in animation");
|
||||
RNA_def_property_ui_text(prop, "Frames", "Sets the number of images of a movie to use"); /* copied from the rna_image.c */
|
||||
RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update");
|
||||
|
||||
prop = RNA_def_property(srna, "frame_start", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "sfra");
|
||||
RNA_def_property_range(prop, MINAFRAMEF, MAXFRAMEF);
|
||||
RNA_def_property_ui_text(prop, "Start Frame", "");
|
||||
RNA_def_property_ui_text(prop, "Start Frame", "Sets the global starting frame of the movie/sequence, assuming first picture has a #1"); /* copied from the rna_image.c */
|
||||
RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update");
|
||||
|
||||
prop = RNA_def_property(srna, "frame_offset", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "offset");
|
||||
RNA_def_property_range(prop, MINAFRAMEF, MAXFRAMEF);
|
||||
RNA_def_property_ui_text(prop, "Offset", "Offsets the number of the frame to use in the animation");
|
||||
RNA_def_property_ui_text(prop, "Offset", "Offsets the number of the frame to use in the animation"); /* copied from the rna_image.c */
|
||||
RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_cyclic", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "cycl", 1);
|
||||
RNA_def_property_ui_text(prop, "Cyclic", "");
|
||||
RNA_def_property_ui_text(prop, "Cyclic", "Cycle the images in the movie"); /* copied from the rna_image.c */
|
||||
RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_auto_refresh", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_ANIM_ALWAYS);
|
||||
RNA_def_property_ui_text(prop, "Auto-Refresh", "");
|
||||
RNA_def_property_ui_text(prop, "Auto-Refresh", "Always refresh image on frame changes"); /* copied from the rna_image.c */
|
||||
RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update");
|
||||
|
||||
prop= RNA_def_property(srna, "layer", PROP_ENUM, PROP_NONE);
|
||||
|
||||
Reference in New Issue
Block a user