diff options
author | Campbell Barton <ideasman42@gmail.com> | 2011-05-09 20:31:54 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2011-05-09 20:31:54 +0400 |
commit | 885141c9dec9828172471b0e58dc4d975d250a04 (patch) | |
tree | 4901c666de40a3159f107f9b985a94a1612777e2 | |
parent | 1e0c3d315b8b5db4b5d594c05c7b1b92d5bf967a (diff) |
patch [#21740] Image support for Empty Objects
from Andy Braham (andybraham)
This adds support for empties to reference images and draw in the 3D view.
Modifications from the original patch.
- use an empty draw 'image' type
- use image aspect ratio for non-square-pixels
- when the image is not found, still draw the frame.
-rw-r--r-- | release/scripts/startup/bl_ui/properties_data_empty.py | 11 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/drawobject.c | 111 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_object_types.h | 4 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_object.c | 33 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_ui_api.c | 2 |
5 files changed, 146 insertions, 15 deletions
diff --git a/release/scripts/startup/bl_ui/properties_data_empty.py b/release/scripts/startup/bl_ui/properties_data_empty.py index e46cd1270ad..80f83e7fabe 100644 --- a/release/scripts/startup/bl_ui/properties_data_empty.py +++ b/release/scripts/startup/bl_ui/properties_data_empty.py @@ -39,6 +39,17 @@ class DATA_PT_empty(DataButtonsPanel, bpy.types.Panel): ob = context.object layout.prop(ob, "empty_draw_type", text="Display") + + if ob.empty_draw_type == 'IMAGE': + # layout.template_image(ob, "data", None) + layout.template_ID(ob, "data", open="image.open", unlink="image.unlink") + + row = layout.row(align = True) + row.prop(ob, "color", text="Transparency", index=3, slider=True) + row = layout.row(align = True) + row.prop(ob, "empty_image_offset", text="Offset X", index=0) + row.prop(ob, "empty_image_offset", text="Offset Y", index=1) + layout.prop(ob, "empty_draw_size", text="Size") if __name__ == "__main__": # only for live edit. diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index a3a139181d5..ba30aecc9ab 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -46,6 +46,7 @@ #include "DNA_scene_types.h" #include "DNA_smoke_types.h" #include "DNA_world_types.h" +#include "DNA_armature_types.h" #include "BLI_blenlib.h" #include "BLI_math.h" @@ -76,6 +77,9 @@ #include "smoke_API.h" +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" + #include "BIF_gl.h" #include "BIF_glutil.h" @@ -515,6 +519,96 @@ void drawaxes(float size, char drawtype) } } + +/* Function to draw an Image on a empty Object */ +static void draw_empty_image(Object *ob) +{ + Image *ima = (Image*)ob->data; + ImBuf *ibuf = ima ? BKE_image_get_ibuf(ima, NULL) : NULL; + + float scale, ofs_x, ofs_y, sca_x, sca_y; + int ima_x, ima_y; + + if(ibuf && (ibuf->rect == NULL) && (ibuf->rect_float != NULL)) { + IMB_rect_from_float(ibuf); + } + + /* Get the buffer dimensions so we can fallback to fake ones */ + if(ibuf && ibuf->rect) { + ima_x= ibuf->x; + ima_y= ibuf->y; + } + else { + ima_x= 1; + ima_y= 1; + } + + /* Get the image aspect even if the buffer is invalid */ + if(ima) { + if(ima->aspx > ima->aspy) { + sca_x= 1.0f; + sca_y= ima->aspy / ima->aspx; + } + else if(ima->aspx < ima->aspy) { + sca_x= ima->aspx / ima->aspy; + sca_y= 1.0f; + } + else { + sca_x= 1.0f; + sca_y= 1.0f; + } + } + else { + sca_x= 1.0f; + sca_y= 1.0f; + } + + /* Calculate the scale center based on objects origin */ + ofs_x= ob->ima_ofs[0] * ima_x; + ofs_y= ob->ima_ofs[1] * ima_y; + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + + /* Make sure we are drawing at the origin */ + glTranslatef(0.0f, 0.0f, 0.0f); + + /* Calculate Image scale */ + scale= (ob->empty_drawsize / (float)MAX2(ima_x * sca_x, ima_y * sca_y)); + + /* Set the object scale */ + glScalef(scale * sca_x, scale * sca_y, 1.0f); + + if(ibuf && ibuf->rect) { + /* Setup GL params */ + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + /* Use the object color and alpha */ + glColor4fv(ob->col); + + /* Draw the Image on the screen */ + glaDrawPixelsTex(ofs_x, ofs_y, ima_x, ima_y, GL_UNSIGNED_BYTE, ibuf->rect); + glPixelTransferf(GL_ALPHA_SCALE, 1.0f); + + glDisable(GL_BLEND); + } + + UI_ThemeColor((ob->flag & SELECT) ? TH_SELECT : TH_WIRE); + + /* Calculate the outline vertex positions */ + glBegin(GL_LINE_LOOP); + glVertex2f(ofs_x, ofs_y); + glVertex2f(ofs_x + ima_x, ofs_y); + glVertex2f(ofs_x + ima_x, ofs_y + ima_y); + glVertex2f(ofs_x, ofs_y + ima_y); + glEnd(); + + /* Reset GL settings */ + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); +} + void drawcircball(int mode, const float cent[3], float rad, float tmat[][4]) { float vec[3], vx[3], vy[3]; @@ -5954,8 +6048,14 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) break; } case OB_EMPTY: - if((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) - drawaxes(ob->empty_drawsize, ob->empty_drawtype); + if((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) { + if (ob->empty_drawtype == OB_EMPTY_IMAGE) { + draw_empty_image(ob); + } + else { + drawaxes(ob->empty_drawsize, ob->empty_drawtype); + } + } break; case OB_LAMP: if((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) { @@ -6564,7 +6664,12 @@ void draw_object_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object draw_object_mesh_instance(scene, v3d, rv3d, ob, dt, outline); break; case OB_EMPTY: - drawaxes(ob->empty_drawsize, ob->empty_drawtype); + if (ob->empty_drawtype == OB_EMPTY_IMAGE) { + draw_empty_image(ob); + } + else { + drawaxes(ob->empty_drawsize, ob->empty_drawtype); + } break; } } diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index c97a1d8fef5..54a885a0860 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -259,6 +259,9 @@ typedef struct Object { ListBase gpulamp; /* runtime, for lamps only */ ListBase pc_ids; ListBase *duplilist; /* for temporary dupli list storage, only for use by RNA API */ + + float ima_ofs[2]; /* offset for image empties */ + char pad3[8]; } Object; /* Warning, this is not used anymore because hooks are now modifiers */ @@ -399,6 +402,7 @@ extern Object workob; #define OB_CUBE 5 #define OB_EMPTY_SPHERE 6 #define OB_EMPTY_CONE 7 +#define OB_EMPTY_IMAGE 8 /* boundtype */ #define OB_BOUND_BOX 0 diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 11e7dd81cb6..d5d7f2917b9 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -307,22 +307,26 @@ static void rna_Base_layer_update(Main *bmain, Scene *scene, PointerRNA *ptr) WM_main_add_notifier(NC_SCENE|ND_LAYER_CONTENT, scene); } -static int rna_Object_data_editable(PointerRNA *ptr) -{ - Object *ob= (Object*)ptr->data; - - return (ob->type == OB_EMPTY)? 0: PROP_EDITABLE; -} - static void rna_Object_data_set(PointerRNA *ptr, PointerRNA value) { Object *ob= (Object*)ptr->data; ID *id= value.data; - if(ob->type == OB_EMPTY || id == NULL || ob->mode & OB_MODE_EDIT) + if (id == NULL || ob->mode & OB_MODE_EDIT) return; - - if(ob->type == OB_MESH) { + + if (ob->type == OB_EMPTY) { + if(ob->data) { + id_us_min((ID*)ob->data); + ob->data = NULL; + } + + if (id && GS(id->name) == ID_IM) { + id_us_plus(id); + ob->data = id; + } + } + else if(ob->type == OB_MESH) { set_mesh(ob, (Mesh*)id); } else { @@ -346,6 +350,7 @@ static StructRNA *rna_Object_data_typef(PointerRNA *ptr) Object *ob= (Object*)ptr->data; switch(ob->type) { + case OB_EMPTY: return &RNA_Image; case OB_MESH: return &RNA_Mesh; case OB_CURVE: return &RNA_Curve; case OB_SURF: return &RNA_Curve; @@ -1691,6 +1696,7 @@ static void rna_def_object(BlenderRNA *brna) {OB_CUBE, "CUBE", 0, "Cube", ""}, {OB_EMPTY_SPHERE, "SPHERE", 0, "Sphere", ""}, {OB_EMPTY_CONE, "CONE", 0, "Cone", ""}, + {OB_EMPTY_IMAGE, "IMAGE", 0, "Image", ""}, {0, NULL, 0, NULL, NULL}}; static EnumPropertyItem track_items[] = { @@ -1758,7 +1764,6 @@ static void rna_def_object(BlenderRNA *brna) prop= RNA_def_property(srna, "data", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "ID"); RNA_def_property_pointer_funcs(prop, NULL, "rna_Object_data_set", "rna_Object_data_typef", NULL); - RNA_def_property_editable_func(prop, "rna_Object_data_editable"); RNA_def_property_flag(prop, PROP_EDITABLE|PROP_NEVER_UNLINK); RNA_def_property_ui_text(prop, "Data", "Object data"); RNA_def_property_update(prop, 0, "rna_Object_internal_update_data"); @@ -2043,6 +2048,12 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Empty Display Size", "Size of display for empties in the viewport"); RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, NULL); + prop= RNA_def_property(srna, "empty_image_offset", PROP_FLOAT, PROP_DISTANCE); + RNA_def_property_float_sdna(prop, NULL, "ima_ofs"); + RNA_def_property_ui_text(prop, "Origin Offset", "Origin offset distance"); + RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 0.1f, 2); + RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, NULL); + /* render */ prop= RNA_def_property(srna, "pass_index", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "index"); diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c index ae308b9423f..d4ac9880290 100644 --- a/source/blender/makesrna/intern/rna_ui_api.c +++ b/source/blender/makesrna/intern/rna_ui_api.c @@ -389,7 +389,7 @@ void RNA_api_ui_layout(StructRNA *srna) RNA_def_function_flag(func, FUNC_USE_CONTEXT); api_ui_item_rna_common(func); parm= RNA_def_pointer(func, "image_user", "ImageUser", "", ""); - RNA_def_property_flag(parm, PROP_REQUIRED|PROP_RNAPTR); + RNA_def_property_flag(parm, PROP_REQUIRED|PROP_RNAPTR|PROP_NEVER_NULL); RNA_def_boolean(func, "compact", 0, "", "Use more compact layout."); func= RNA_def_function(srna, "template_list", "uiTemplateList"); |