Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/sculpt_paint/paint_image_proj.c
| Context not available. | |||||
| #include "BKE_material.h" | #include "BKE_material.h" | ||||
| #include "BKE_mesh.h" | #include "BKE_mesh.h" | ||||
| #include "BKE_mesh_mapping.h" | #include "BKE_mesh_mapping.h" | ||||
| #include "BKE_node.h" | |||||
| #include "BKE_paint.h" | #include "BKE_paint.h" | ||||
| #include "BKE_report.h" | #include "BKE_report.h" | ||||
| #include "BKE_scene.h" | #include "BKE_scene.h" | ||||
| Context not available. | |||||
| #include "ED_image.h" | #include "ED_image.h" | ||||
| #include "ED_mesh.h" | #include "ED_mesh.h" | ||||
| #include "ED_node.h" | |||||
| #include "ED_paint.h" | #include "ED_paint.h" | ||||
| #include "ED_screen.h" | #include "ED_screen.h" | ||||
| #include "ED_uvedit.h" | #include "ED_uvedit.h" | ||||
| Context not available. | |||||
| { | { | ||||
| MFace *mf = ps->dm_mface + face_index; | MFace *mf = ps->dm_mface + face_index; | ||||
| Material *ma = ps->dm->mat[mf->mat_nr]; | Material *ma = ps->dm->mat[mf->mat_nr]; | ||||
| return ma ? ma->texpaintslot + ma->paint_active_slot : NULL; | return ma->texpaintslot + ma->paint_active_slot; | ||||
| } | } | ||||
| static Image *project_paint_face_paint_image(const ProjPaintState *ps, int face_index) | static Image *project_paint_face_paint_image(const ProjPaintState *ps, int face_index) | ||||
| Context not available. | |||||
| else { | else { | ||||
| MFace *mf = ps->dm_mface + face_index; | MFace *mf = ps->dm_mface + face_index; | ||||
| Material *ma = ps->dm->mat[mf->mat_nr]; | Material *ma = ps->dm->mat[mf->mat_nr]; | ||||
| TexPaintSlot *slot = ma ? ma->texpaintslot + ma->paint_active_slot : NULL; | TexPaintSlot *slot = ma->texpaintslot + ma->paint_active_slot; | ||||
| return slot ? slot->ima : ps->canvas_ima; | return slot ? slot->ima : ps->canvas_ima; | ||||
| } | } | ||||
| } | } | ||||
| Context not available. | |||||
| { | { | ||||
| MFace *mf = ps->dm_mface + face_index; | MFace *mf = ps->dm_mface + face_index; | ||||
| Material *ma = ps->dm->mat[mf->mat_nr]; | Material *ma = ps->dm->mat[mf->mat_nr]; | ||||
| return ma ? ma->texpaintslot + ma->paint_clone_slot : NULL; | return ma->texpaintslot + ma->paint_clone_slot; | ||||
| } | } | ||||
| static Image *project_paint_face_clone_image(const ProjPaintState *ps, int face_index) | static Image *project_paint_face_clone_image(const ProjPaintState *ps, int face_index) | ||||
| { | { | ||||
| MFace *mf = ps->dm_mface + face_index; | MFace *mf = ps->dm_mface + face_index; | ||||
| Material *ma = ps->dm->mat[mf->mat_nr]; | Material *ma = ps->dm->mat[mf->mat_nr]; | ||||
| TexPaintSlot *slot = ma ? ma->texpaintslot + ma->paint_clone_slot : NULL; | TexPaintSlot *slot = ma->texpaintslot + ma->paint_clone_slot; | ||||
| return slot ? slot->ima : ps->clone_ima; | return slot ? slot->ima : ps->clone_ima; | ||||
| } | } | ||||
| Context not available. | |||||
| IDProperty *idgroup; | IDProperty *idgroup; | ||||
| IDProperty *view_data = NULL; | IDProperty *view_data = NULL; | ||||
| Object *ob = OBACT; | Object *ob = OBACT; | ||||
| bool uvs, mat, tex; | |||||
| if (ob == NULL || ob->type != OB_MESH) { | if (ob == NULL || ob->type != OB_MESH) { | ||||
| BKE_report(op->reports, RPT_ERROR, "No active mesh object"); | BKE_report(op->reports, RPT_ERROR, "No active mesh object"); | ||||
| return OPERATOR_CANCELLED; | return OPERATOR_CANCELLED; | ||||
| } | } | ||||
| if (!BKE_paint_proj_mesh_data_check(scene, ob, &uvs, &mat, &tex, NULL)) { | paint_proj_mesh_data_ensure(C, ob, op); | ||||
| BKE_paint_data_warning(op->reports, uvs, mat, tex, true); | |||||
| WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL); | |||||
| return OPERATOR_CANCELLED; | |||||
| } | |||||
| project_state_init(C, ob, &ps, BRUSH_STROKE_NORMAL); | project_state_init(C, ob, &ps, BRUSH_STROKE_NORMAL); | ||||
| Context not available. | |||||
| * Data generation for projective texturing * | * Data generation for projective texturing * | ||||
| * *******************************************/ | * *******************************************/ | ||||
| void BKE_paint_data_warning(struct ReportList *reports, bool uvs, bool mat, bool tex, bool stencil) | |||||
| { | |||||
| BKE_reportf(reports, RPT_WARNING, "Missing%s%s%s%s detected!", | |||||
| !uvs ? " UVs," : "", | |||||
| !mat ? " Materials," : "", | |||||
| !tex ? " Textures," : "", | |||||
| !stencil ? " Stencil," : "" | |||||
| ); | |||||
| } | |||||
| /* Make sure that active object has a material, and assign UVs and image layers if they do not exist */ | /* Make sure that active object has a material, and assign UVs and image layers if they do not exist */ | ||||
| bool BKE_paint_proj_mesh_data_check(Scene *scene, Object *ob, bool *uvs, bool *mat, bool *tex, bool *stencil) | void paint_proj_mesh_data_ensure(bContext *C, Object *ob, wmOperator *op) | ||||
| { | { | ||||
| Mesh *me; | Mesh *me; | ||||
| int layernum; | int layernum; | ||||
| ImagePaintSettings *imapaint = &scene->toolsettings->imapaint; | ImagePaintSettings *imapaint = &(CTX_data_tool_settings(C)->imapaint); | ||||
| bScreen *sc; | |||||
| Scene *scene = CTX_data_scene(C); | |||||
| Main *bmain = CTX_data_main(C); | |||||
| Brush *br = BKE_paint_brush(&imapaint->paint); | Brush *br = BKE_paint_brush(&imapaint->paint); | ||||
| bool hasmat = true; | |||||
| bool hastex = true; | |||||
| bool hasstencil = true; | |||||
| bool hasuvs = true; | |||||
| imapaint->missing_data = 0; | |||||
| BLI_assert(ob->type == OB_MESH); | BLI_assert(ob->type == OB_MESH); | ||||
| if (imapaint->mode == IMAGEPAINT_MODE_MATERIAL) { | /* no material, add one */ | ||||
| /* no material, add one */ | if (ob->totcol == 0) { | ||||
| if (ob->totcol == 0) { | Material *ma = BKE_material_add(CTX_data_main(C), "Material"); | ||||
| hasmat = false; | /* no material found, just assign to first slot */ | ||||
| hastex = false; | assign_material(ob, ma, 1, BKE_MAT_ASSIGN_USERPREF); | ||||
| } | proj_paint_add_slot(C, ma, NULL); | ||||
| else { | } | ||||
| /* there may be material slots but they may be empty, check */ | else { | ||||
| int i; | /* there may be material slots but they may be empty, check */ | ||||
| hasmat = false; | int i; | ||||
| hastex = false; | |||||
| for (i = 1; i < ob->totcol + 1; i++) { | |||||
| for (i = 1; i < ob->totcol + 1; i++) { | Material *ma = give_current_material(ob, i); | ||||
| Material *ma = give_current_material(ob, i); | |||||
| if (ma) { | |||||
| if (ma) { | if (imapaint->mode == IMAGEPAINT_MODE_MATERIAL) { | ||||
| hasmat = true; | |||||
| if (!ma->texpaintslot) { | if (!ma->texpaintslot) { | ||||
| /* refresh here just in case */ | /* refresh here just in case */ | ||||
| BKE_texpaint_slot_refresh_cache(scene, ma); | BKE_texpaint_slot_refresh_cache(scene, ma); | ||||
| /* if still no slots, we have to add */ | /* if still no slots, we have to add */ | ||||
| if (ma->texpaintslot) { | if (!ma->texpaintslot) { | ||||
| hastex = true; | proj_paint_add_slot(C, ma, NULL); | ||||
| break; | |||||
| if (ma->texpaintslot) { | |||||
| for (sc = bmain->screen.first; sc; sc = sc->id.next) { | |||||
| ScrArea *sa; | |||||
| for (sa = sc->areabase.first; sa; sa = sa->next) { | |||||
| SpaceLink *sl; | |||||
| for (sl = sa->spacedata.first; sl; sl = sl->next) { | |||||
| if (sl->spacetype == SPACE_IMAGE) { | |||||
| SpaceImage *sima = (SpaceImage *)sl; | |||||
| if (!sima->pin) | |||||
| ED_space_image_set(sima, scene, scene->obedit, ma->texpaintslot[0].ima); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| else { | |||||
| hastex = true; | |||||
| break; | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| else { | |||||
| Material *ma = BKE_material_add(CTX_data_main(C), "Material"); | |||||
| /* no material found, just assign to first slot */ | |||||
| assign_material(ob, ma, i, BKE_MAT_ASSIGN_USERPREF); | |||||
| proj_paint_add_slot(C, ma, NULL); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| else if (imapaint->mode == IMAGEPAINT_MODE_IMAGE) { | |||||
| if (imapaint->mode == IMAGEPAINT_MODE_IMAGE) { | |||||
| if (imapaint->canvas == NULL) { | if (imapaint->canvas == NULL) { | ||||
| hastex = false; | int width; | ||||
| int height; | |||||
| Main *bmain = CTX_data_main(C); | |||||
| float color[4] = {0.0, 0.0, 0.0, 1.0}; | |||||
| width = 1024; | |||||
| height = 1024; | |||||
| imapaint->canvas = BKE_image_add_generated(bmain, width, height, "Canvas", 32, false, IMA_GENTYPE_BLANK, color); | |||||
| GPU_drawobject_free(ob->derivedFinal); | |||||
| for (sc = bmain->screen.first; sc; sc = sc->id.next) { | |||||
| ScrArea *sa; | |||||
| for (sa = sc->areabase.first; sa; sa = sa->next) { | |||||
| SpaceLink *sl; | |||||
| for (sl = sa->spacedata.first; sl; sl = sl->next) { | |||||
| if (sl->spacetype == SPACE_IMAGE) { | |||||
| SpaceImage *sima = (SpaceImage *)sl; | |||||
| if (!sima->pin) | |||||
| ED_space_image_set(sima, scene, scene->obedit, imapaint->canvas); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| me = BKE_mesh_from_object(ob); | me = BKE_mesh_from_object(ob); | ||||
| layernum = CustomData_number_of_layers(&me->pdata, CD_MTEXPOLY); | layernum = CustomData_number_of_layers(&me->pdata, CD_MTEXPOLY); | ||||
| if (layernum == 0) { | if (layernum == 0) { | ||||
| hasuvs = false; | BKE_reportf(op->reports, RPT_WARNING, "Object did not have UV map, manual unwrap recommended"); | ||||
| ED_mesh_uv_texture_add(me, "UVMap", true); | |||||
| } | } | ||||
| /* Make sure we have a stencil to paint on! */ | /* Make sure we have a stencil to paint on! */ | ||||
| Context not available. | |||||
| imapaint->flag |= IMAGEPAINT_PROJECT_LAYER_STENCIL; | imapaint->flag |= IMAGEPAINT_PROJECT_LAYER_STENCIL; | ||||
| if (imapaint->stencil == NULL) { | if (imapaint->stencil == NULL) { | ||||
| hasstencil = false; | int width; | ||||
| int height; | |||||
| Main *bmain = CTX_data_main(C); | |||||
| float color[4] = {0.0, 0.0, 0.0, 1.0}; | |||||
| width = 1024; | |||||
| height = 1024; | |||||
| imapaint->stencil = BKE_image_add_generated(bmain, width, height, "Stencil", 32, false, IMA_GENTYPE_BLANK, color); | |||||
| } | } | ||||
| } | } | ||||
| if (!hasuvs) imapaint->missing_data |= IMAGEPAINT_MISSING_UVS; | |||||
| if (!hasmat) imapaint->missing_data |= IMAGEPAINT_MISSING_MATERIAL; | |||||
| if (!hastex) imapaint->missing_data |= IMAGEPAINT_MISSING_TEX; | |||||
| if (!hasstencil) imapaint->missing_data |= IMAGEPAINT_MISSING_STENCIL; | |||||
| if (uvs) { | |||||
| *uvs = hasuvs; | |||||
| } | |||||
| if (mat) { | |||||
| *mat = hasmat; | |||||
| } | |||||
| if (tex) { | |||||
| *tex = hastex; | |||||
| } | |||||
| if (stencil) { | |||||
| *stencil = hasstencil; | |||||
| } | |||||
| return hasuvs && hasmat && hastex && hasstencil; | |||||
| } | } | ||||
| /* Add layer operator */ | /* Add layer operator */ | ||||
| Context not available. | |||||
| {0, NULL, 0, NULL, NULL} | {0, NULL, 0, NULL, NULL} | ||||
| }; | }; | ||||
| static Image *proj_paint_image_create(wmOperator *op, Main *bmain) | bool proj_paint_add_slot(bContext *C, Material *ma, wmOperator *op) | ||||
| { | |||||
| Image *ima; | |||||
| float color[4] = {0.0f, 0.0f, 0.0f, 1.0f}; | |||||
| char imagename[MAX_ID_NAME - 2] = "Material Diffuse Color"; | |||||
| int width = 1024; | |||||
| int height = 1024; | |||||
| bool use_float = false; | |||||
| short gen_type = IMA_GENTYPE_BLANK; | |||||
| bool alpha = false; | |||||
| if (op) { | |||||
| width = RNA_int_get(op->ptr, "width"); | |||||
| height = RNA_int_get(op->ptr, "height"); | |||||
| use_float = RNA_boolean_get(op->ptr, "float"); | |||||
| gen_type = RNA_enum_get(op->ptr, "generated_type"); | |||||
| RNA_float_get_array(op->ptr, "color", color); | |||||
| alpha = RNA_boolean_get(op->ptr, "alpha"); | |||||
| RNA_string_get(op->ptr, "name", imagename); | |||||
| } | |||||
| ima = BKE_image_add_generated(bmain, width, height, imagename, alpha ? 32 : 24, use_float, | |||||
| gen_type, color); | |||||
| return ima; | |||||
| } | |||||
| static bool proj_paint_add_slot(bContext *C, wmOperator *op) | |||||
| { | { | ||||
| Object *ob = CTX_data_active_object(C); | Object *ob = CTX_data_active_object(C); | ||||
| Scene *scene = CTX_data_scene(C); | Scene *scene = CTX_data_scene(C); | ||||
| Material *ma; | |||||
| bool is_bi = BKE_scene_uses_blender_internal(scene); | bool is_bi = BKE_scene_uses_blender_internal(scene); | ||||
| Image *ima = NULL; | |||||
| if (!ob) | if (!ob) | ||||
| return false; | return false; | ||||
| ma = give_current_material(ob, ob->actcol); | if (!ma) | ||||
| ma = give_current_material(ob, ob->actcol); | |||||
| if (ma) { | if (ma) { | ||||
| Main *bmain = CTX_data_main(C); | |||||
| if (!is_bi && BKE_scene_use_new_shading_nodes(scene)) { | |||||
| bNode *imanode; | |||||
| bNodeTree *ntree = ma->nodetree; | |||||
| if (!ntree) { | if (!is_bi || ma->use_nodes) { | ||||
| ED_node_shader_default(C, &ma->id); | /* not supported for now */ | ||||
| ntree = ma->nodetree; | |||||
| } | |||||
| ma->use_nodes = true; | |||||
| /* try to add an image node */ | |||||
| imanode = nodeAddStaticNode(C, ntree, SH_NODE_TEX_IMAGE); | |||||
| ima = proj_paint_image_create(op, bmain); | |||||
| imanode->id = &ima->id; | |||||
| nodeSetActive(ntree, imanode); | |||||
| ntreeUpdateTree(CTX_data_main(C), ntree); | |||||
| } | } | ||||
| else { | else { | ||||
| MTex *mtex = add_mtex_id(&ma->id, -1); | MTex *mtex = add_mtex_id(&ma->id, -1); | ||||
| /* successful creation of mtex layer, now create set */ | /* successful creation of mtex layer, now create set */ | ||||
| if (mtex) { | if (mtex) { | ||||
| Main *bmain = CTX_data_main(C); | |||||
| Image *ima; | |||||
| int type = MAP_COL; | int type = MAP_COL; | ||||
| int type_id = 0; | int type_id = 0; | ||||
| Context not available. | |||||
| mtex->mapto = type; | mtex->mapto = type; | ||||
| if (mtex->tex) { | if (mtex->tex) { | ||||
| ima = mtex->tex->ima = proj_paint_image_create(op, bmain); | float color[4] = {0.0f, 0.0f, 0.0f, 1.0f}; | ||||
| char imagename[MAX_ID_NAME - 2] = "Material Diffuse Color"; | |||||
| int width = 1024; | |||||
| int height = 1024; | |||||
| bool use_float = false; | |||||
| short gen_type = IMA_GENTYPE_BLANK; | |||||
| bool alpha = false; | |||||
| if (op) { | |||||
| width = RNA_int_get(op->ptr, "width"); | |||||
| height = RNA_int_get(op->ptr, "height"); | |||||
| use_float = RNA_boolean_get(op->ptr, "float"); | |||||
| gen_type = RNA_enum_get(op->ptr, "generated_type"); | |||||
| RNA_float_get_array(op->ptr, "color", color); | |||||
| alpha = RNA_boolean_get(op->ptr, "alpha"); | |||||
| RNA_string_get(op->ptr, "name", imagename); | |||||
| } | |||||
| ima = mtex->tex->ima = BKE_image_add_generated(bmain, width, height, imagename, alpha ? 32 : 24, use_float, | |||||
| gen_type, color); | |||||
| BKE_texpaint_slot_refresh_cache(scene, ma); | |||||
| BKE_image_signal(ima, NULL, IMA_SIGNAL_USER_NEW_IMAGE); | |||||
| WM_event_add_notifier(C, NC_TEXTURE | NA_ADDED, mtex->tex); | |||||
| WM_event_add_notifier(C, NC_IMAGE | NA_ADDED, ima); | |||||
| DAG_id_tag_update(&ma->id, 0); | |||||
| ED_area_tag_redraw(CTX_wm_area(C)); | |||||
| } | } | ||||
| WM_event_add_notifier(C, NC_TEXTURE, CTX_data_scene(C)); | WM_event_add_notifier(C, NC_TEXTURE, CTX_data_scene(C)); | ||||
| return true; | |||||
| } | } | ||||
| WM_event_add_notifier(C, NC_TEXTURE | NA_ADDED, mtex->tex); | |||||
| } | |||||
| if (ima) { | |||||
| BKE_texpaint_slot_refresh_cache(scene, ma); | |||||
| BKE_image_signal(ima, NULL, IMA_SIGNAL_USER_NEW_IMAGE); | |||||
| WM_event_add_notifier(C, NC_IMAGE | NA_ADDED, ima); | |||||
| DAG_id_tag_update(&ma->id, 0); | |||||
| ED_area_tag_redraw(CTX_wm_area(C)); | |||||
| return true; | |||||
| } | } | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| static int texture_paint_add_texture_paint_slot_exec(bContext *C, wmOperator *op) | static int texture_paint_add_texture_paint_slot_exec(bContext *C, wmOperator *op) | ||||
| { | { | ||||
| if (proj_paint_add_slot(C, op)) { | return proj_paint_add_slot(C, NULL, op); | ||||
| return OPERATOR_FINISHED; | |||||
| } | |||||
| else { | |||||
| return OPERATOR_CANCELLED; | |||||
| } | |||||
| } | } | ||||
| Context not available. | |||||
| Material *ma = give_current_material(ob, ob->actcol); | Material *ma = give_current_material(ob, ob->actcol); | ||||
| int type = RNA_enum_get(op->ptr, "type"); | int type = RNA_enum_get(op->ptr, "type"); | ||||
| if (!ma) { | |||||
| ma = BKE_material_add(CTX_data_main(C), "Material"); | |||||
| /* no material found, just assign to first slot */ | |||||
| assign_material(ob, ma, ob->actcol, BKE_MAT_ASSIGN_USERPREF); | |||||
| } | |||||
| type = RNA_enum_from_value(layer_type_items, type); | type = RNA_enum_from_value(layer_type_items, type); | ||||
| /* get the name of the texture layer type */ | /* get the name of the texture layer type */ | ||||
| Context not available. | |||||
| { | { | ||||
| /* identifiers */ | /* identifiers */ | ||||
| ot->name = "Delete Texture Paint Slot"; | ot->name = "Delete Texture Paint Slot"; | ||||
| ot->description = "Delete selected texture paint slot"; | ot->description = "Add a texture paint slot"; | ||||
| ot->idname = "PAINT_OT_delete_texture_paint_slot"; | ot->idname = "PAINT_OT_delete_texture_paint_slot"; | ||||
| /* api callbacks */ | /* api callbacks */ | ||||
| Context not available. | |||||