Index: release/scripts/ui/properties_data_empty.py =================================================================== --- release/scripts/ui/properties_data_empty.py (revision 27632) +++ release/scripts/ui/properties_data_empty.py (working copy) @@ -18,10 +18,10 @@ # import bpy +from bpy.props import * narrowui = 180 - class DataButtonsPanel(bpy.types.Panel): bl_space_type = 'PROPERTIES' bl_region_type = 'WINDOW' @@ -30,13 +30,12 @@ def poll(self, context): return (context.object and context.object.type == 'EMPTY') - class DATA_PT_empty(DataButtonsPanel): + "Empty Object Properties" bl_label = "Empty" def draw(self, context): layout = self.layout - ob = context.object wide_ui = context.region.width > narrowui @@ -45,8 +44,19 @@ else: layout.prop(ob, "empty_draw_type", text="") - layout.prop(ob, "empty_draw_size", text="Size") + #If empty_draw_type is Image display Image properties + if (ob.empty_draw_type == "IMAGE"): + layout.template_ID(ob, "empty_image", open="image.open") + row = layout.row(align = True) + row.prop(ob, "color", text="Transperency", index = 3, slider=True) + row = layout.row(align = True) + row.prop(ob, "empty_draw_size", text="Size") + row = layout.row(align=True) + row.prop(ob, "origin_offset", text="X", index = 0) + row.prop(ob, "origin_offset", text="Y", index = 1) + else: + layout.prop(ob, "empty_draw_size", text="Size") classes = [ DATA_PT_empty] @@ -64,4 +74,4 @@ unregister(cls) if __name__ == "__main__": - register() + register() \ No newline at end of file Index: source/blender/makesdna/DNA_object_types.h =================================================================== --- source/blender/makesdna/DNA_object_types.h (revision 27632) +++ source/blender/makesdna/DNA_object_types.h (working copy) @@ -392,6 +392,7 @@ #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 Index: source/blender/makesrna/intern/rna_object.c =================================================================== --- source/blender/makesrna/intern/rna_object.c (revision 27632) +++ source/blender/makesrna/intern/rna_object.c (working copy) @@ -89,7 +89,7 @@ {0, "", 0, NULL, NULL}, {OB_CAMERA, "CAMERA", 0, "Camera", ""}, {OB_LAMP, "LAMP", 0, "Lamp", ""}, - {0, NULL, 0, NULL, NULL}}; + {0, NULL, 0, NULL, NULL}}; #ifdef RNA_RUNTIME @@ -206,6 +206,9 @@ ob->lay= base->lay; } +//This can be removed since it is not needed any more due to empties +//containing images, object->empty->data was the only case that was checked +//see rna_Object_data_editable_func static int rna_Object_data_editable(PointerRNA *ptr) { Object *ob= (Object*)ptr->data; @@ -218,25 +221,30 @@ Object *ob= (Object*)ptr->data; ID *id= value.data; - if(ob->type == OB_EMPTY || id == NULL || ob->mode & OB_MODE_EDIT) - return; + //If type is empty object allow setting Image or null only + if((ob->type == OB_EMPTY) && (ob->empty_drawtype == OB_EMPTY_IMAGE)){ + ob->data = id; + } + else if(ob->type == OB_EMPTY || id == NULL || ob->mode & OB_MODE_EDIT){ + return; + } if(ob->type == OB_MESH) { - set_mesh(ob, (Mesh*)id); + set_mesh(ob, (Mesh*)id); } else { - if(ob->data) - id_us_min((ID*)ob->data); - if(id) - id_us_plus(id); + if(ob->data) + id_us_min((ID*)ob->data); + if(id) + id_us_plus(id); - ob->data= id; - test_object_materials(id); + ob->data= id; + test_object_materials(id); - if(GS(id->name)==ID_CU) - test_curve_type(ob); - else if(ob->type==OB_ARMATURE) - armature_rebuild_pose(ob, ob->data); + if(GS(id->name)==ID_CU) + test_curve_type(ob); + else if(ob->type==OB_ARMATURE) + armature_rebuild_pose(ob, ob->data); } } @@ -608,17 +616,17 @@ static int rna_Object_location_editable(PointerRNA *ptr, int index) { - Object *ob= (Object *)ptr->data; - - /* only if the axis in question is locked, not editable... */ - if ((index == 0) && (ob->protectflag & OB_LOCK_LOCX)) - return 0; - else if ((index == 1) && (ob->protectflag & OB_LOCK_LOCY)) - return 0; - else if ((index == 2) && (ob->protectflag & OB_LOCK_LOCZ)) - return 0; - else - return PROP_EDITABLE; + Object *ob= (Object *)ptr->data; + + /* only if the axis in question is locked, not editable... */ + if ((index == 0) && (ob->protectflag & OB_LOCK_LOCX)) + return 0; + else if ((index == 1) && (ob->protectflag & OB_LOCK_LOCY)) + return 0; + else if ((index == 2) && (ob->protectflag & OB_LOCK_LOCZ)) + return 0; + else + return PROP_EDITABLE; } static int rna_Object_scale_editable(PointerRNA *ptr, int index) @@ -671,7 +679,6 @@ return PROP_EDITABLE; } - static PointerRNA rna_MaterialSlot_material_get(PointerRNA *ptr) { Object *ob= (Object*)ptr->id.data; @@ -1388,6 +1395,7 @@ {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[] = { @@ -1455,7 +1463,7 @@ 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"); - RNA_def_property_editable_func(prop, "rna_Object_data_editable"); + //RNA_def_property_editable_func(prop, "rna_Object_data_editable"); //Removed to allow object->data to be set via Python A. Braham 3/20/10 RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Data", "Object data"); RNA_def_property_update(prop, 0, "rna_Object_update_data"); @@ -1485,6 +1493,12 @@ RNA_def_property_ui_text(prop, "Selected", "Object selection state"); RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, "rna_Object_select_update"); + prop= RNA_def_property(srna, "origin_offset", PROP_FLOAT, PROP_DISTANCE); + RNA_def_property_float_sdna(prop, NULL, "orig"); + RNA_def_property_ui_text(prop, "Origin Offset", "Origin offset distance"); + RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 0.1f, 3); + RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, NULL); + /* for data access */ prop= RNA_def_property(srna, "bound_box", PROP_FLOAT, PROP_NONE); RNA_def_property_multi_array(prop, 2, boundbox_dimsize); @@ -1577,9 +1591,9 @@ RNA_def_property_ui_text(prop, "Quaternion Rotation", "Rotation in Quaternions"); RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM, "rna_Object_update"); - /* XXX: for axis-angle, it would have been nice to have 2 separate fields for UI purposes, but - * having a single one is better for Keyframing and other property-management situations... - */ + /* XXX: for axis-angle, it would have been nice to have 2 separate fields for UI purposes, but + * having a single one is better for Keyframing and other property-management situations... + */ prop= RNA_def_property(srna, "rotation_axis_angle", PROP_FLOAT, PROP_AXISANGLE); RNA_def_property_array(prop, 4); RNA_def_property_float_funcs(prop, "rna_Object_rotation_axis_angle_get", "rna_Object_rotation_axis_angle_set", NULL); @@ -1727,20 +1741,28 @@ prop= RNA_def_property(srna, "empty_draw_size", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_float_sdna(prop, NULL, "empty_drawsize"); RNA_def_property_range(prop, 0.1f, 1000.0f); - RNA_def_property_ui_range(prop, 0.01, 100, 1, 1); + RNA_def_property_ui_range(prop, 0.01, 100, 1, 3); 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", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "data"); + RNA_def_property_struct_type(prop, "Image"); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Image", ""); + 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"); RNA_def_property_ui_text(prop, "Pass Index", "Index # for the IndexOB render pass"); RNA_def_property_update(prop, NC_OBJECT, NULL); - prop= RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR); - RNA_def_property_float_sdna(prop, NULL, "col"); - RNA_def_property_ui_text(prop, "Color", "Object color and alpha, used when faces have the ObColor mode enabled"); - RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, NULL); + prop= RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "col"); + RNA_def_property_ui_text(prop, "Color", "Object color and alpha, used when faces have the ObColor mode enabled"); + RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.01f, 3); + RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, NULL); /* physics */ prop= RNA_def_property(srna, "field", PROP_POINTER, PROP_NONE); Index: source/blender/makesrna/RNA_define.h =================================================================== --- source/blender/makesrna/RNA_define.h (revision 27632) +++ source/blender/makesrna/RNA_define.h (working copy) @@ -96,7 +96,7 @@ float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax); PropertyRNA *RNA_def_float_array(StructOrFunctionRNA *cont, const char *identifier, int len, const float *default_value, float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax); - /* + /* PropertyRNA *RNA_def_float_dynamic_array(StructOrFunctionRNA *cont, const char *identifier, float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax, unsigned int dimension, unsigned short dim_size[]); */ Index: source/blender/imbuf/IMB_imbuf.h =================================================================== --- source/blender/imbuf/IMB_imbuf.h (revision 27632) +++ source/blender/imbuf/IMB_imbuf.h (working copy) @@ -105,7 +105,7 @@ /** * - * @attention defined in ??? + * @attention defined in ??? -- Defined in IMG_imbuf_types.h AB 3/20/10 */ struct ImBuf; Index: source/blender/editors/space_view3d/drawobject.c =================================================================== --- source/blender/editors/space_view3d/drawobject.c (revision 27632) +++ source/blender/editors/space_view3d/drawobject.c (working copy) @@ -35,10 +35,10 @@ #include "MEM_guardedalloc.h" #include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" - #include "DNA_armature_types.h" #include "DNA_boid_types.h" #include "DNA_camera_types.h" @@ -332,6 +332,108 @@ 1.00000000 }; +//*** Function to draw an Image on a empty Object *** +void draw_image_3D(Object *ob, Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d) +{ + Image *img = (Image*)ob->data; + ImBuf *ibuf = NULL; + float scale; + float offset[3]; + float v1[3], v2[3], v3[3], v4[3]; + float sel_col[3]; + + //Make sure we have a valid Image + if(img == NULL){ + return; + } + + //Get the image buffer for displaying Image + ibuf = BKE_image_get_ibuf(img, NULL); + + //Make sure the Image Buffer was created ok + if(ibuf==NULL || (ibuf->rect == NULL && ibuf->rect_float == NULL)){ + return; + } + if(ibuf->channels!=4){ + return; + } + if(ibuf->rect==NULL){ + IMB_rect_from_float(ibuf); + } + + //Calculate Image scale + scale = ((((float)ibuf->x / 150.0f) / (float)ibuf->x) * scene->unit.scale_length); + + //Setup GL params + glDepthMask(1); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + //Set color to outline color and object alpha + glColor4f(ob->col[0], ob->col[1], ob->col[2], ob->col[3]); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + + //Make sure we are drawing at the origin + glTranslatef(0.0f, 0.0f, 0.0f); + + //Calculate the scale center based on objects origin + offset[0] = (ob->orig[0] / scale); + offset[1] = (ob->orig[1] / scale); + + //Set the object scale + glScalef((scale * ob->empty_drawsize), (scale * ob->empty_drawsize), (scale * ob->empty_drawsize)); + + //Draw the Image on the screen + glaDrawPixelsTex(offset[0], offset[1], ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, ibuf->rect); + glPixelTransferf(GL_ALPHA_SCALE, 1.0f); + + //Set zbuffer, outline shows up better + glDepthMask(1); + + //Check to see if the object is active and selected + if (ob==OBACT || (ob->flag & SELECT)){ + //Set color to outline color and object alpha + UI_GetThemeColor3fv(TH_VERTEX_SELECT, sel_col); + glColor4f(sel_col[0], sel_col[1], sel_col[2], ob->col[3]); + } + + //Calculate the outline vertex positions + v1[0] = offset[0]; + v1[1] = offset[1]; + v1[2] = 0.0f; + + v2[0] = offset[0] + ibuf->x; + v2[1] = offset[1]; + v2[2] = 0.0f; + + v3[0] = offset[0] + ibuf->x; + v3[1] = offset[1] + ibuf->y; + v3[2] = 0.0f; + + v4[0] = offset[0]; + v4[1] = offset[1] + ibuf->y; + v4[2] = 0.0f; + + glBegin(GL_LINES); + glVertex3fv(v1); + glVertex3fv(v2); + glVertex3fv(v2); + glVertex3fv(v3); + glVertex3fv(v3); + glVertex3fv(v4); + glVertex3fv(v4); + glVertex3fv(v1); + glEnd(); + + //Reset GL settings + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + glDisable(GL_BLEND); + glDepthMask(1); +} + /* flag is same as for draw_object */ void drawaxes(float size, int flag, char drawtype) { @@ -5763,9 +5865,18 @@ break; } case OB_EMPTY: - if((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) - drawaxes(ob->empty_drawsize, flag, ob->empty_drawtype); + if((v3d->flag2 & V3D_RENDER_OVERRIDE)==0){ + //Check if Empty has Image + if (ob->empty_drawtype == OB_EMPTY_IMAGE){ + //Draw the image + draw_image_3D(ob, scene, ar, v3d, rv3d); + } + else{ + drawaxes(ob->empty_drawsize, flag, ob->empty_drawtype); + } + } break; + case OB_LAMP: if((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) { drawlamp(scene, v3d, rv3d, base, dt, flag); Index: source/blender/editors/space_view3d/view3d_intern.h =================================================================== --- source/blender/editors/space_view3d/view3d_intern.h (revision 27632) +++ source/blender/editors/space_view3d/view3d_intern.h (working copy) @@ -105,6 +105,7 @@ void draw_object_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, int dt, int outline); void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob); void drawaxes(float size, int flag, char drawtype); +void draw_image_3D(Object *ob, Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d); //Draws Image on Object void view3d_cached_text_draw_begin(void); void view3d_cached_text_draw_add(float x, float y, float z, char *str, short xoffs, short flag); Index: source/blender/editors/object/object_edit.c =================================================================== --- source/blender/editors/object/object_edit.c (revision 27632) +++ source/blender/editors/object/object_edit.c (working copy) @@ -2146,3 +2146,82 @@ RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "Property index to remove ", 0, INT_MAX); } + +//###################### Object->Empty->Image ###################### + +//************************ Add Empty Image ************************ +static int object_empty_image_add_exec(bContext *C, wmOperator *op) +{ + Object *ob = CTX_data_active_object(C); + Image *img = MEM_callocN(sizeof(Image), "Empty Object Image"); + bProperty *prop; + + if(!ob) + return OPERATOR_CANCELLED; + + //Set the image into Object->Data + ob->data = img; + + return OPERATOR_FINISHED; +} + +static int object_empty_image_add_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + return object_empty_image_add_exec(C, op); +} + +void OBJECT_OT_object_empty_image_add(wmOperatorType *ot) +{ + //Setup Operator information + ot->name = "Add Empty Object Image"; + ot->description = "Adds a new Image to a Empty Object"; + ot->idname = "OBJECT_OT_object_empty_image_add"; + + //Set Callback Fuctions + ot->invoke = object_empty_image_add_invoke; + ot->exec = object_empty_image_add_exec; + ot->poll = ED_operator_object_active_editable; + + //Set the Operator Flags to register our operator type + //and that it should be included in the undeo stack + ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; +} + + +//************************ Remove Empty Image ************************ + +static int object_empty_image_remove_exec(bContext *C, wmOperator *op) +{ + Image *img = CTX_data_pointer_get_type(C, "image", &RNA_Image).data; + Scene *scene= CTX_data_scene(C); + + if(img) { + img->id.us--; + MEM_freeN(img); + } + + WM_event_add_notifier(C, NC_SCENE|NS_MODE_OBJECT, scene); + + return OPERATOR_FINISHED; +} + +static int object_empty_image_remove_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + return object_empty_image_remove_exec(C, op); +} + +void OBJECT_OT_object_empty_image_remove(wmOperatorType *ot) +{ + //Setup Operator information + ot->name = "Remove Empty Object Image"; + ot->description = "Removes the Image from a Empty Object"; + ot->idname = "OBJECT_OT_object_empty_image_remove"; + + //Set Callback Fuctions + ot->invoke = object_empty_image_remove_invoke; + ot->exec = object_empty_image_remove_exec; + ot->poll = ED_operator_object_active_editable; + + /* flags */ + ot->flag = 0; +} Index: source/blender/editors/object/object_ops.c =================================================================== --- source/blender/editors/object/object_ops.c (revision 27632) +++ source/blender/editors/object/object_ops.c (working copy) @@ -206,6 +206,9 @@ WM_operatortype_append(OBJECT_OT_bake_image); WM_operatortype_append(OBJECT_OT_drop_named_material); + + WM_operatortype_append(OBJECT_OT_object_empty_image_add); + WM_operatortype_append(OBJECT_OT_object_empty_image_remove); } void ED_operatormacros_object(void) Index: source/blender/editors/object/object_intern.h =================================================================== --- source/blender/editors/object/object_intern.h (revision 27632) +++ source/blender/editors/object/object_intern.h (working copy) @@ -82,6 +82,8 @@ void OBJECT_OT_shade_flat(struct wmOperatorType *ot); void OBJECT_OT_paths_calculate(struct wmOperatorType *ot); void OBJECT_OT_paths_clear(struct wmOperatorType *ot); +void OBJECT_OT_object_empty_image_add(wmOperatorType *ot); +void OBJECT_OT_object_empty_image_remove(wmOperatorType *ot); /* object_select.c */ void OBJECT_OT_select_all(struct wmOperatorType *ot);