diff options
author | Hans Goudey <h.goudey@me.com> | 2020-09-11 18:44:41 +0300 |
---|---|---|
committer | Hans Goudey <h.goudey@me.com> | 2020-09-11 18:44:41 +0300 |
commit | 537daa5dd47052abbc1fb8fabf218a0f43eabe16 (patch) | |
tree | facaac53d8a93bf7f77f0c3f785d8c424c8619c2 | |
parent | eabba50141477b9d35f00e5790052973a2f152d8 (diff) | |
parent | 5c5d02264979d2244c5da5af2c7c438f69a03a9e (diff) |
Merge branch 'property-search-button-label-pointer' into property-search-move-context-to-panel
81 files changed, 3141 insertions, 974 deletions
diff --git a/release/datafiles/userdef/userdef_default_theme.c b/release/datafiles/userdef/userdef_default_theme.c index 7604a06f7df..cd6be1903ec 100644 --- a/release/datafiles/userdef/userdef_default_theme.c +++ b/release/datafiles/userdef/userdef_default_theme.c @@ -714,6 +714,7 @@ const bTheme U_theme_default = { .paint_curve_pivot = RGBA(0xff7f7f7f), .paint_curve_handle = RGBA(0x7fff7f7f), .metadatatext = RGBA(0xffffffff), + .grid = RGBA(0x505050ff), }, .space_text = { .back = RGBA(0x30303000), diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py index a490208fd5e..0fde128a906 100644 --- a/release/scripts/startup/bl_ui/space_image.py +++ b/release/scripts/startup/bl_ui/space_image.py @@ -1019,7 +1019,8 @@ class IMAGE_PT_view_display_uv_edit_overlays(Panel): col.prop(uvedit, "show_faces", text="Faces") col = layout.column() - col.prop(uvedit, "show_smooth_edges", text="Smooth") + if context.preferences.experimental.use_image_editor_legacy_drawing: + col.prop(uvedit, "show_smooth_edges", text="Smooth") col.prop(uvedit, "show_modified_edges", text="Modified") col.prop(uvedit, "uv_opacity") diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index 506849fbee5..faea806c6cb 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -2194,6 +2194,7 @@ class USERPREF_PT_experimental_debugging(ExperimentalPanel, Panel): context, ( ({"property": "use_undo_legacy"}, "T60695"), ({"property": "use_cycles_debug"}, None), + ({"property": "use_image_editor_legacy_drawing"}, "T67530"), ), ) diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h index d21fe5afa7e..fea9bbe9bb5 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -570,9 +570,9 @@ void CustomData_data_transfer(const struct MeshPairRemap *me_remap, /* .blend file I/O */ void CustomData_blend_write_prepare(struct CustomData *data, - struct CustomDataLayer **r_write_layers, - struct CustomDataLayer *write_layers_buff, - size_t write_layers_size); + struct CustomDataLayer **r_write_layers, + struct CustomDataLayer *write_layers_buff, + size_t write_layers_size); void CustomData_blend_write(struct BlendWriter *writer, struct CustomData *data, diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h index 88eef40ebd2..f1912b14e8c 100644 --- a/source/blender/blenkernel/BKE_gpencil.h +++ b/source/blender/blenkernel/BKE_gpencil.h @@ -48,6 +48,7 @@ struct bGPDlayer_Mask; struct bGPDspoint; struct bGPDstroke; struct bGPdata; +struct BlendDataReader; #define GPENCIL_SIMPLIFY(scene) ((scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ENABLE)) #define GPENCIL_SIMPLIFY_ONPLAY(playing) \ @@ -281,6 +282,8 @@ void BKE_gpencil_parent_matrix_get(const struct Depsgraph *depsgraph, void BKE_gpencil_update_layer_parent(const struct Depsgraph *depsgraph, struct Object *ob); +void BKE_gpencil_blend_read_data(struct BlendDataReader *reader, struct bGPdata *gpd); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/intern/cachefile.c b/source/blender/blenkernel/intern/cachefile.c index f3386df03c8..9475ba7efcf 100644 --- a/source/blender/blenkernel/intern/cachefile.c +++ b/source/blender/blenkernel/intern/cachefile.c @@ -39,6 +39,7 @@ #include "BLT_translation.h" +#include "BKE_anim_data.h" #include "BKE_cachefile.h" #include "BKE_idtype.h" #include "BKE_lib_id.h" @@ -48,6 +49,8 @@ #include "DEG_depsgraph_query.h" +#include "BLO_read_write.h" + #ifdef WITH_ALEMBIC # include "ABC_alembic.h" #endif @@ -85,6 +88,37 @@ static void cache_file_free_data(ID *id) BLI_freelistN(&cache_file->object_paths); } +static void cache_file_blend_write(BlendWriter *writer, ID *id, const void *id_address) +{ + CacheFile *cache_file = (CacheFile *)id; + if (cache_file->id.us > 0 || BLO_write_is_undo(writer)) { + /* Clean up, important in undo case to reduce false detection of changed datablocks. */ + BLI_listbase_clear(&cache_file->object_paths); + cache_file->handle = NULL; + memset(cache_file->handle_filepath, 0, sizeof(cache_file->handle_filepath)); + cache_file->handle_readers = NULL; + + BLO_write_id_struct(writer, CacheFile, id_address, &cache_file->id); + + if (cache_file->adt) { + BKE_animdata_blend_write(writer, cache_file->adt); + } + } +} + +static void cache_file_blend_read_data(BlendDataReader *reader, ID *id) +{ + CacheFile *cache_file = (CacheFile *)id; + BLI_listbase_clear(&cache_file->object_paths); + cache_file->handle = NULL; + cache_file->handle_filepath[0] = '\0'; + cache_file->handle_readers = NULL; + + /* relink animdata */ + BLO_read_data_address(reader, &cache_file->adt); + BKE_animdata_blend_read_data(reader, cache_file->adt); +} + IDTypeInfo IDType_ID_CF = { .id_code = ID_CF, .id_filter = FILTER_ID_CF, @@ -102,8 +136,8 @@ IDTypeInfo IDType_ID_CF = { .foreach_id = NULL, .foreach_cache = NULL, - .blend_write = NULL, - .blend_read_data = NULL, + .blend_write = cache_file_blend_write, + .blend_read_data = cache_file_blend_read_data, .blend_read_lib = NULL, .blend_read_expand = NULL, }; diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index e7fe10cf19c..fc1b4d82c20 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -845,7 +845,8 @@ static void childof_new_data(void *cdata) bChildOfConstraint *data = (bChildOfConstraint *)cdata; data->flag = (CHILDOF_LOCX | CHILDOF_LOCY | CHILDOF_LOCZ | CHILDOF_ROTX | CHILDOF_ROTY | - CHILDOF_ROTZ | CHILDOF_SIZEX | CHILDOF_SIZEY | CHILDOF_SIZEZ); + CHILDOF_ROTZ | CHILDOF_SIZEX | CHILDOF_SIZEY | CHILDOF_SIZEZ | + CHILDOF_SET_INVERSE); unit_m4(data->invmat); } diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index 1e37ae3892b..03ac7e622e1 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -40,12 +40,16 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" +/* Allow using deprecated functionality for .blend file I/O. */ +#define DNA_DEPRECATED_ALLOW + #include "DNA_gpencil_types.h" #include "DNA_material_types.h" #include "DNA_meshdata_types.h" #include "DNA_space_types.h" #include "BKE_action.h" +#include "BKE_anim_data.h" #include "BKE_collection.h" #include "BKE_colortools.h" #include "BKE_deform.h" @@ -64,6 +68,10 @@ #include "DEG_depsgraph_query.h" +#include "BLO_read_write.h" + +#include "BKE_gpencil.h" + static CLG_LogRef LOG = {"bke.gpencil"}; static void greasepencil_copy_data(Main *UNUSED(bmain), @@ -111,6 +119,154 @@ static void greasepencil_foreach_id(ID *id, LibraryForeachIDData *data) } } +static void greasepencil_blend_write(BlendWriter *writer, ID *id, const void *id_address) +{ + bGPdata *gpd = (bGPdata *)id; + if (gpd->id.us > 0 || BLO_write_is_undo(writer)) { + /* Clean up, important in undo case to reduce false detection of changed data-blocks. */ + /* XXX not sure why the whole run-time data is not cleared in reading code, + * for now mimicking it here. */ + gpd->runtime.sbuffer = NULL; + gpd->runtime.sbuffer_used = 0; + gpd->runtime.sbuffer_size = 0; + gpd->runtime.tot_cp_points = 0; + + /* write gpd data block to file */ + BLO_write_id_struct(writer, bGPdata, id_address, &gpd->id); + BKE_id_blend_write(writer, &gpd->id); + + if (gpd->adt) { + BKE_animdata_blend_write(writer, gpd->adt); + } + + BLO_write_pointer_array(writer, gpd->totcol, gpd->mat); + + /* write grease-pencil layers to file */ + BLO_write_struct_list(writer, bGPDlayer, &gpd->layers); + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + /* Write mask list. */ + BLO_write_struct_list(writer, bGPDlayer_Mask, &gpl->mask_layers); + /* write this layer's frames to file */ + BLO_write_struct_list(writer, bGPDframe, &gpl->frames); + LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { + /* write strokes */ + BLO_write_struct_list(writer, bGPDstroke, &gpf->strokes); + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + BLO_write_struct_array(writer, bGPDspoint, gps->totpoints, gps->points); + BLO_write_struct_array(writer, bGPDtriangle, gps->tot_triangles, gps->triangles); + BKE_defvert_blend_write(writer, gps->totpoints, gps->dvert); + } + } + } + } +} + +void BKE_gpencil_blend_read_data(BlendDataReader *reader, bGPdata *gpd) +{ + /* we must firstly have some grease-pencil data to link! */ + if (gpd == NULL) { + return; + } + + /* relink animdata */ + BLO_read_data_address(reader, &gpd->adt); + BKE_animdata_blend_read_data(reader, gpd->adt); + + /* Ensure full objectmode for linked grease pencil. */ + if (gpd->id.lib != NULL) { + gpd->flag &= ~GP_DATA_STROKE_PAINTMODE; + gpd->flag &= ~GP_DATA_STROKE_EDITMODE; + gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE; + gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE; + gpd->flag &= ~GP_DATA_STROKE_VERTEXMODE; + } + + /* init stroke buffer */ + gpd->runtime.sbuffer = NULL; + gpd->runtime.sbuffer_used = 0; + gpd->runtime.sbuffer_size = 0; + gpd->runtime.tot_cp_points = 0; + + /* relink palettes (old palettes deprecated, only to convert old files) */ + BLO_read_list(reader, &gpd->palettes); + if (gpd->palettes.first != NULL) { + LISTBASE_FOREACH (Palette *, palette, &gpd->palettes) { + BLO_read_list(reader, &palette->colors); + } + } + + /* materials */ + BLO_read_pointer_array(reader, (void **)&gpd->mat); + + /* relink layers */ + BLO_read_list(reader, &gpd->layers); + + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + /* relink frames */ + BLO_read_list(reader, &gpl->frames); + + BLO_read_data_address(reader, &gpl->actframe); + + gpl->runtime.icon_id = 0; + + /* Relink masks. */ + BLO_read_list(reader, &gpl->mask_layers); + + LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { + /* relink strokes (and their points) */ + BLO_read_list(reader, &gpf->strokes); + + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + /* relink stroke points array */ + BLO_read_data_address(reader, &gps->points); + /* Relink geometry*/ + BLO_read_data_address(reader, &gps->triangles); + + /* relink weight data */ + if (gps->dvert) { + BLO_read_data_address(reader, &gps->dvert); + BKE_defvert_blend_read(reader, gps->totpoints, gps->dvert); + } + } + } + } +} + +static void greasepencil_blend_read_data(BlendDataReader *reader, ID *id) +{ + bGPdata *gpd = (bGPdata *)id; + BKE_gpencil_blend_read_data(reader, gpd); +} + +static void greasepencil_blend_read_lib(BlendLibReader *reader, ID *id) +{ + bGPdata *gpd = (bGPdata *)id; + + /* Relink all data-lock linked by GP data-lock */ + /* Layers */ + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + /* Layer -> Parent References */ + BLO_read_id_address(reader, gpd->id.lib, &gpl->parent); + } + + /* materials */ + for (int a = 0; a < gpd->totcol; a++) { + BLO_read_id_address(reader, gpd->id.lib, &gpd->mat[a]); + } +} + +static void greasepencil_blend_read_expand(BlendExpander *expander, ID *id) +{ + bGPdata *gpd = (bGPdata *)id; + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + BLO_expand(expander, gpl->parent); + } + + for (int a = 0; a < gpd->totcol; a++) { + BLO_expand(expander, gpd->mat[a]); + } +} + IDTypeInfo IDType_ID_GD = { .id_code = ID_GD, .id_filter = FILTER_ID_GD, @@ -128,10 +284,10 @@ IDTypeInfo IDType_ID_GD = { .foreach_id = greasepencil_foreach_id, .foreach_cache = NULL, - .blend_write = NULL, - .blend_read_data = NULL, - .blend_read_lib = NULL, - .blend_read_expand = NULL, + .blend_write = greasepencil_blend_write, + .blend_read_data = greasepencil_blend_read_data, + .blend_read_lib = greasepencil_blend_read_lib, + .blend_read_expand = greasepencil_blend_read_expand, }; /* ************************************************** */ diff --git a/source/blender/blenkernel/intern/gpencil_geom.c b/source/blender/blenkernel/intern/gpencil_geom.c index 83e3a3098e9..a9b0eede055 100644 --- a/source/blender/blenkernel/intern/gpencil_geom.c +++ b/source/blender/blenkernel/intern/gpencil_geom.c @@ -2264,17 +2264,16 @@ static int gpencil_material_find_index_by_name(Object *ob, const char *name) return -1; } -/* Create the name with the object name and a subfix. */ -static void make_element_name(char *obname, char *name, const int maxlen, char *r_name) +/** + * Create the name with the object name and a suffix. + */ +static void make_element_name(const char *obname, const char *name, const int maxlen, char *r_name) { char str[256]; - sprintf(str, "%s_%s", obname, name); + SNPRINTF(str, "%s_%s", obname, name); + /* Replace any point by underscore. */ - char *current_pos = strchr(str, '.'); - while (current_pos) { - *current_pos = '_'; - current_pos = strchr(current_pos, '.'); - } + BLI_str_replace_char(str, '.', '_'); BLI_strncpy_utf8(r_name, str, maxlen); } diff --git a/source/blender/blenkernel/intern/hair.c b/source/blender/blenkernel/intern/hair.c index 314b7228373..72e3d355ba5 100644 --- a/source/blender/blenkernel/intern/hair.c +++ b/source/blender/blenkernel/intern/hair.c @@ -47,6 +47,8 @@ #include "DEG_depsgraph_query.h" +#include "BLO_read_write.h" + const char *HAIR_ATTR_POSITION = "Position"; const char *HAIR_ATTR_RADIUS = "Radius"; @@ -109,6 +111,69 @@ static void hair_foreach_id(ID *id, LibraryForeachIDData *data) } } +static void hair_blend_write(BlendWriter *writer, ID *id, const void *id_address) +{ + Hair *hair = (Hair *)id; + if (hair->id.us > 0 || BLO_write_is_undo(writer)) { + CustomDataLayer *players = NULL, players_buff[CD_TEMP_CHUNK_SIZE]; + CustomDataLayer *clayers = NULL, clayers_buff[CD_TEMP_CHUNK_SIZE]; + CustomData_blend_write_prepare(&hair->pdata, &players, players_buff, ARRAY_SIZE(players_buff)); + CustomData_blend_write_prepare(&hair->cdata, &clayers, clayers_buff, ARRAY_SIZE(clayers_buff)); + + /* Write LibData */ + BLO_write_id_struct(writer, Hair, id_address, &hair->id); + BKE_id_blend_write(writer, &hair->id); + + /* Direct data */ + CustomData_blend_write(writer, &hair->pdata, players, hair->totpoint, CD_MASK_ALL, &hair->id); + CustomData_blend_write(writer, &hair->cdata, clayers, hair->totcurve, CD_MASK_ALL, &hair->id); + + BLO_write_pointer_array(writer, hair->totcol, hair->mat); + if (hair->adt) { + BKE_animdata_blend_write(writer, hair->adt); + } + + /* Remove temporary data. */ + if (players && players != players_buff) { + MEM_freeN(players); + } + if (clayers && clayers != clayers_buff) { + MEM_freeN(clayers); + } + } +} + +static void hair_blend_read_data(BlendDataReader *reader, ID *id) +{ + Hair *hair = (Hair *)id; + BLO_read_data_address(reader, &hair->adt); + BKE_animdata_blend_read_data(reader, hair->adt); + + /* Geometry */ + CustomData_blend_read(reader, &hair->pdata, hair->totpoint); + CustomData_blend_read(reader, &hair->cdata, hair->totcurve); + BKE_hair_update_customdata_pointers(hair); + + /* Materials */ + BLO_read_pointer_array(reader, (void **)&hair->mat); +} + +static void hair_blend_read_lib(BlendLibReader *reader, ID *id) +{ + Hair *hair = (Hair *)id; + for (int a = 0; a < hair->totcol; a++) { + BLO_read_id_address(reader, hair->id.lib, &hair->mat[a]); + } +} + +static void hair_blend_read_expand(BlendExpander *expander, ID *id) +{ + Hair *hair = (Hair *)id; + for (int a = 0; a < hair->totcol; a++) { + BLO_expand(expander, hair->mat[a]); + } +} + IDTypeInfo IDType_ID_HA = { .id_code = ID_HA, .id_filter = FILTER_ID_HA, @@ -126,10 +191,10 @@ IDTypeInfo IDType_ID_HA = { .foreach_id = hair_foreach_id, .foreach_cache = NULL, - .blend_write = NULL, - .blend_read_data = NULL, - .blend_read_lib = NULL, - .blend_read_expand = NULL, + .blend_write = hair_blend_write, + .blend_read_data = hair_blend_read_data, + .blend_read_lib = hair_blend_read_lib, + .blend_read_expand = hair_blend_read_expand, }; static void hair_random(Hair *hair) diff --git a/source/blender/blenkernel/intern/image_gpu.c b/source/blender/blenkernel/intern/image_gpu.c index d4a1c1e2c46..f37e038e69e 100644 --- a/source/blender/blenkernel/intern/image_gpu.c +++ b/source/blender/blenkernel/intern/image_gpu.c @@ -272,6 +272,13 @@ static GPUTexture *image_get_gpu_texture(Image *ima, * context and might as well ensure we have as much space free as possible. */ gpu_free_unused_buffers(); + /* Free GPU textures when requesting a different render pass/layer. */ + if (ima->gpu_pass != iuser->pass || ima->gpu_layer != iuser->layer) { + ima->gpu_pass = iuser->pass; + ima->gpu_layer = iuser->layer; + ima->gpuflag |= IMA_GPU_REFRESH; + } + /* currently, gpu refresh tagging is used by ima sequences */ if (ima->gpuflag & IMA_GPU_REFRESH) { image_free_gpu(ima, true); @@ -282,7 +289,10 @@ static GPUTexture *image_get_gpu_texture(Image *ima, BKE_image_tag_time(ima); /* Test if we already have a texture. */ - GPUTexture **tex = get_image_gpu_texture_ptr(ima, textarget, iuser ? iuser->multiview_eye : 0); + const int current_view = iuser ? ((iuser->flag & IMA_SHOW_STEREO) != 0 ? iuser->multiview_eye : + iuser->view) : + 0; + GPUTexture **tex = get_image_gpu_texture_ptr(ima, textarget, current_view); if (*tex) { return *tex; } diff --git a/source/blender/blenkernel/intern/pointcloud.c b/source/blender/blenkernel/intern/pointcloud.c index 087bf123575..2cdc717b793 100644 --- a/source/blender/blenkernel/intern/pointcloud.c +++ b/source/blender/blenkernel/intern/pointcloud.c @@ -47,6 +47,8 @@ #include "DEG_depsgraph_query.h" +#include "BLO_read_write.h" + /* PointCloud datablock */ static void pointcloud_random(PointCloud *pointcloud); @@ -111,6 +113,64 @@ static void pointcloud_foreach_id(ID *id, LibraryForeachIDData *data) } } +static void pointcloud_blend_write(BlendWriter *writer, ID *id, const void *id_address) +{ + PointCloud *pointcloud = (PointCloud *)id; + if (pointcloud->id.us > 0 || BLO_write_is_undo(writer)) { + CustomDataLayer *players = NULL, players_buff[CD_TEMP_CHUNK_SIZE]; + CustomData_blend_write_prepare( + &pointcloud->pdata, &players, players_buff, ARRAY_SIZE(players_buff)); + + /* Write LibData */ + BLO_write_id_struct(writer, PointCloud, id_address, &pointcloud->id); + BKE_id_blend_write(writer, &pointcloud->id); + + /* Direct data */ + CustomData_blend_write( + writer, &pointcloud->pdata, players, pointcloud->totpoint, CD_MASK_ALL, &pointcloud->id); + + BLO_write_pointer_array(writer, pointcloud->totcol, pointcloud->mat); + if (pointcloud->adt) { + BKE_animdata_blend_write(writer, pointcloud->adt); + } + + /* Remove temporary data. */ + if (players && players != players_buff) { + MEM_freeN(players); + } + } +} + +static void pointcloud_blend_read_data(BlendDataReader *reader, ID *id) +{ + PointCloud *pointcloud = (PointCloud *)id; + BLO_read_data_address(reader, &pointcloud->adt); + BKE_animdata_blend_read_data(reader, pointcloud->adt); + + /* Geometry */ + CustomData_blend_read(reader, &pointcloud->pdata, pointcloud->totpoint); + BKE_pointcloud_update_customdata_pointers(pointcloud); + + /* Materials */ + BLO_read_pointer_array(reader, (void **)&pointcloud->mat); +} + +static void pointcloud_blend_read_lib(BlendLibReader *reader, ID *id) +{ + PointCloud *pointcloud = (PointCloud *)id; + for (int a = 0; a < pointcloud->totcol; a++) { + BLO_read_id_address(reader, pointcloud->id.lib, &pointcloud->mat[a]); + } +} + +static void pointcloud_blend_read_expand(BlendExpander *expander, ID *id) +{ + PointCloud *pointcloud = (PointCloud *)id; + for (int a = 0; a < pointcloud->totcol; a++) { + BLO_expand(expander, pointcloud->mat[a]); + } +} + IDTypeInfo IDType_ID_PT = { .id_code = ID_PT, .id_filter = FILTER_ID_PT, @@ -128,10 +188,10 @@ IDTypeInfo IDType_ID_PT = { .foreach_id = pointcloud_foreach_id, .foreach_cache = NULL, - .blend_write = NULL, - .blend_read_data = NULL, - .blend_read_lib = NULL, - .blend_read_expand = NULL, + .blend_write = pointcloud_blend_write, + .blend_read_data = pointcloud_blend_read_data, + .blend_read_lib = pointcloud_blend_read_lib, + .blend_read_expand = pointcloud_blend_read_expand, }; static void pointcloud_random(PointCloud *pointcloud) diff --git a/source/blender/blenkernel/intern/simulation.cc b/source/blender/blenkernel/intern/simulation.cc index 9dc1f073e2a..f08051510db 100644 --- a/source/blender/blenkernel/intern/simulation.cc +++ b/source/blender/blenkernel/intern/simulation.cc @@ -63,6 +63,8 @@ #include "SIM_simulation_update.hh" +#include "BLO_read_write.h" + using StateInitFunction = void (*)(SimulationState *state); using StateResetFunction = void (*)(SimulationState *state); using StateRemoveFunction = void (*)(SimulationState *state); @@ -145,6 +147,94 @@ static void simulation_foreach_id(ID *id, LibraryForeachIDData *data) } } +static void simulation_blend_write(BlendWriter *writer, ID *id, const void *id_address) +{ + Simulation *simulation = (Simulation *)id; + if (simulation->id.us > 0 || BLO_write_is_undo(writer)) { + BLO_write_id_struct(writer, Simulation, id_address, &simulation->id); + BKE_id_blend_write(writer, &simulation->id); + + if (simulation->adt) { + BKE_animdata_blend_write(writer, simulation->adt); + } + + /* nodetree is integral part of simulation, no libdata */ + if (simulation->nodetree) { + BLO_write_struct(writer, bNodeTree, simulation->nodetree); + ntreeBlendWrite(writer, simulation->nodetree); + } + + LISTBASE_FOREACH (SimulationState *, state, &simulation->states) { + BLO_write_string(writer, state->name); + BLO_write_string(writer, state->type); + /* TODO: Decentralize this part. */ + if (STREQ(state->type, SIM_TYPE_NAME_PARTICLE_SIMULATION)) { + ParticleSimulationState *particle_state = (ParticleSimulationState *)state; + + CustomDataLayer *players = NULL, players_buff[CD_TEMP_CHUNK_SIZE]; + CustomData_blend_write_prepare( + &particle_state->attributes, &players, players_buff, ARRAY_SIZE(players_buff)); + + BLO_write_struct(writer, ParticleSimulationState, particle_state); + + CustomData_blend_write(writer, + &particle_state->attributes, + players, + particle_state->tot_particles, + CD_MASK_ALL, + &simulation->id); + + /* Remove temporary data. */ + if (players && players != players_buff) { + MEM_freeN(players); + } + } + else if (STREQ(state->type, SIM_TYPE_NAME_PARTICLE_MESH_EMITTER)) { + ParticleMeshEmitterSimulationState *emitter_state = (ParticleMeshEmitterSimulationState *) + state; + BLO_write_struct(writer, ParticleMeshEmitterSimulationState, emitter_state); + } + } + + BLO_write_struct_list(writer, SimulationDependency, &simulation->dependencies); + } +} + +static void simulation_blend_read_data(BlendDataReader *reader, ID *id) +{ + Simulation *simulation = (Simulation *)id; + BLO_read_data_address(reader, &simulation->adt); + BKE_animdata_blend_read_data(reader, simulation->adt); + + BLO_read_list(reader, &simulation->states); + LISTBASE_FOREACH (SimulationState *, state, &simulation->states) { + BLO_read_data_address(reader, &state->name); + BLO_read_data_address(reader, &state->type); + if (STREQ(state->type, SIM_TYPE_NAME_PARTICLE_SIMULATION)) { + ParticleSimulationState *particle_state = (ParticleSimulationState *)state; + CustomData_blend_read(reader, &particle_state->attributes, particle_state->tot_particles); + } + } + + BLO_read_list(reader, &simulation->dependencies); +} + +static void simulation_blend_read_lib(BlendLibReader *reader, ID *id) +{ + Simulation *simulation = (Simulation *)id; + LISTBASE_FOREACH (SimulationDependency *, dependency, &simulation->dependencies) { + BLO_read_id_address(reader, simulation->id.lib, &dependency->id); + } +} + +static void simulation_blend_read_expand(BlendExpander *expander, ID *id) +{ + Simulation *simulation = (Simulation *)id; + LISTBASE_FOREACH (SimulationDependency *, dependency, &simulation->dependencies) { + BLO_expand(expander, dependency->id); + } +} + IDTypeInfo IDType_ID_SIM = { /* id_code */ ID_SIM, /* id_filter */ FILTER_ID_SIM, @@ -162,10 +252,10 @@ IDTypeInfo IDType_ID_SIM = { /* foreach_id */ simulation_foreach_id, /* foreach_cache */ NULL, - /* blend_write */ NULL, - /* blend_read_data */ NULL, - /* blend_read_lib */ NULL, - /* blend_read_expand */ NULL, + /* blend_write */ simulation_blend_write, + /* blend_read_data */ simulation_blend_read_data, + /* blend_read_lib */ simulation_blend_read_lib, + /* blend_read_expand */ simulation_blend_read_expand, }; void *BKE_simulation_add(Main *bmain, const char *name) diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index 88b32e194cf..9cf5ef85850 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -3014,7 +3014,7 @@ static void curve_surf_to_softbody(Scene *scene, Object *ob) * * a: never ever make tangent handles (sub) and or (ob)ject to collision. * b: rather calculate them using some C2 - * (C2= continuous in second derivate -> no jump in bending ) condition. + * (C2= continuous in second derivative -> no jump in bending ) condition. * * Not too hard to do, but needs some more code to care for; * some one may want look at it (JOW 2010/06/12). */ diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index 8ee6a3627dc..c8a31b51500 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -33,6 +33,9 @@ #include "BLT_translation.h" +/* Allow using deprecated functionality for .blend file I/O. */ +#define DNA_DEPRECATED_ALLOW + #include "DNA_anim_types.h" #include "DNA_object_types.h" #include "DNA_packedFile_types.h" @@ -63,6 +66,8 @@ #include "DEG_depsgraph.h" #include "DEG_depsgraph_query.h" +#include "BLO_read_write.h" + static void sound_free_audio(bSound *sound); static void sound_copy_data(Main *UNUSED(bmain), @@ -126,6 +131,64 @@ static void sound_foreach_cache(ID *id, function_callback(id, &key, &sound->waveform, 0, user_data); } +static void sound_blend_write(BlendWriter *writer, ID *id, const void *id_address) +{ + bSound *sound = (bSound *)id; + if (sound->id.us > 0 || BLO_write_is_undo(writer)) { + /* Clean up, important in undo case to reduce false detection of changed datablocks. */ + sound->tags = 0; + sound->handle = NULL; + sound->playback_handle = NULL; + sound->spinlock = NULL; + + /* write LibData */ + BLO_write_id_struct(writer, bSound, id_address, &sound->id); + BKE_id_blend_write(writer, &sound->id); + + BKE_packedfile_blend_write(writer, sound->packedfile); + } +} + +static void sound_blend_read_data(BlendDataReader *reader, ID *id) +{ + bSound *sound = (bSound *)id; + sound->tags = 0; + sound->handle = NULL; + sound->playback_handle = NULL; + + /* versioning stuff, if there was a cache, then we enable caching: */ + if (sound->cache) { + sound->flags |= SOUND_FLAGS_CACHING; + sound->cache = NULL; + } + + if (BLO_read_data_is_undo(reader)) { + sound->tags |= SOUND_TAGS_WAVEFORM_NO_RELOAD; + } + + sound->spinlock = MEM_mallocN(sizeof(SpinLock), "sound_spinlock"); + BLI_spin_init(sound->spinlock); + + /* clear waveform loading flag */ + sound->tags &= ~SOUND_TAGS_WAVEFORM_LOADING; + + BKE_packedfile_blend_read(reader, &sound->packedfile); + BKE_packedfile_blend_read(reader, &sound->newpackedfile); +} + +static void sound_blend_read_lib(BlendLibReader *reader, ID *id) +{ + bSound *sound = (bSound *)id; + BLO_read_id_address( + reader, sound->id.lib, &sound->ipo); // XXX deprecated - old animation system +} + +static void sound_blend_read_expand(BlendExpander *expander, ID *id) +{ + bSound *snd = (bSound *)id; + BLO_expand(expander, snd->ipo); // XXX deprecated - old animation system +} + IDTypeInfo IDType_ID_SO = { .id_code = ID_SO, .id_filter = FILTER_ID_SO, @@ -144,10 +207,10 @@ IDTypeInfo IDType_ID_SO = { .foreach_id = NULL, .foreach_cache = sound_foreach_cache, - .blend_write = NULL, - .blend_read_data = NULL, - .blend_read_lib = NULL, - .blend_read_expand = NULL, + .blend_write = sound_blend_write, + .blend_read_data = sound_blend_read_data, + .blend_read_lib = sound_blend_read_lib, + .blend_read_expand = sound_blend_read_expand, }; #ifdef WITH_AUDASPACE diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index 9e176f355d3..698f6b8cffd 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -36,6 +36,9 @@ #include "BLT_translation.h" +/* Allow using deprecated functionality for .blend file I/O. */ +#define DNA_DEPRECATED_ALLOW + #include "DNA_brush_types.h" #include "DNA_color_types.h" #include "DNA_defaults.h" @@ -50,6 +53,7 @@ #include "BKE_main.h" +#include "BKE_anim_data.h" #include "BKE_colorband.h" #include "BKE_colortools.h" #include "BKE_icons.h" @@ -65,6 +69,8 @@ #include "RE_shader_ext.h" +#include "BLO_read_write.h" + static void texture_init_data(ID *id) { Tex *texture = (Tex *)id; @@ -134,6 +140,62 @@ static void texture_foreach_id(ID *id, LibraryForeachIDData *data) BKE_LIB_FOREACHID_PROCESS(data, texture->ima, IDWALK_CB_USER); } +static void texture_blend_write(BlendWriter *writer, ID *id, const void *id_address) +{ + Tex *tex = (Tex *)id; + if (tex->id.us > 0 || BLO_write_is_undo(writer)) { + /* write LibData */ + BLO_write_id_struct(writer, Tex, id_address, &tex->id); + BKE_id_blend_write(writer, &tex->id); + + if (tex->adt) { + BKE_animdata_blend_write(writer, tex->adt); + } + + /* direct data */ + if (tex->coba) { + BLO_write_struct(writer, ColorBand, tex->coba); + } + + /* nodetree is integral part of texture, no libdata */ + if (tex->nodetree) { + BLO_write_struct(writer, bNodeTree, tex->nodetree); + ntreeBlendWrite(writer, tex->nodetree); + } + + BKE_previewimg_blend_write(writer, tex->preview); + } +} + +static void texture_blend_read_data(BlendDataReader *reader, ID *id) +{ + Tex *tex = (Tex *)id; + BLO_read_data_address(reader, &tex->adt); + BKE_animdata_blend_read_data(reader, tex->adt); + + BLO_read_data_address(reader, &tex->coba); + + BLO_read_data_address(reader, &tex->preview); + BKE_previewimg_blend_read(reader, tex->preview); + + tex->iuser.ok = 1; + tex->iuser.scene = NULL; +} + +static void texture_blend_read_lib(BlendLibReader *reader, ID *id) +{ + Tex *tex = (Tex *)id; + BLO_read_id_address(reader, tex->id.lib, &tex->ima); + BLO_read_id_address(reader, tex->id.lib, &tex->ipo); // XXX deprecated - old animation system +} + +static void texture_blend_read_expand(BlendExpander *expander, ID *id) +{ + Tex *tex = (Tex *)id; + BLO_expand(expander, tex->ima); + BLO_expand(expander, tex->ipo); // XXX deprecated - old animation system +} + IDTypeInfo IDType_ID_TE = { .id_code = ID_TE, .id_filter = FILTER_ID_TE, @@ -151,10 +213,10 @@ IDTypeInfo IDType_ID_TE = { .foreach_id = texture_foreach_id, .foreach_cache = NULL, - .blend_write = NULL, - .blend_read_data = NULL, - .blend_read_lib = NULL, - .blend_read_expand = NULL, + .blend_write = texture_blend_write, + .blend_read_data = texture_blend_read_data, + .blend_read_lib = texture_blend_read_lib, + .blend_read_expand = texture_blend_read_expand, }; /* Utils for all IDs using those texture slots. */ diff --git a/source/blender/blenkernel/intern/volume.cc b/source/blender/blenkernel/intern/volume.cc index f99be2f6aee..eb871e41f8e 100644 --- a/source/blender/blenkernel/intern/volume.cc +++ b/source/blender/blenkernel/intern/volume.cc @@ -51,6 +51,8 @@ #include "DEG_depsgraph_query.h" +#include "BLO_read_write.h" + #include "CLG_log.h" #ifdef WITH_OPENVDB @@ -509,6 +511,61 @@ static void volume_foreach_cache(ID *id, function_callback(id, &key, (void **)&volume->runtime.grids, 0, user_data); } +static void volume_blend_write(BlendWriter *writer, ID *id, const void *id_address) +{ + Volume *volume = (Volume *)id; + if (volume->id.us > 0 || BLO_write_is_undo(writer)) { + /* Clean up, important in undo case to reduce false detection of changed datablocks. */ + volume->runtime.grids = 0; + + /* write LibData */ + BLO_write_id_struct(writer, Volume, id_address, &volume->id); + BKE_id_blend_write(writer, &volume->id); + + /* direct data */ + BLO_write_pointer_array(writer, volume->totcol, volume->mat); + if (volume->adt) { + BKE_animdata_blend_write(writer, volume->adt); + } + + BKE_packedfile_blend_write(writer, volume->packedfile); + } +} + +static void volume_blend_read_data(BlendDataReader *reader, ID *id) +{ + Volume *volume = (Volume *)id; + BLO_read_data_address(reader, &volume->adt); + BKE_animdata_blend_read_data(reader, volume->adt); + + BKE_packedfile_blend_read(reader, &volume->packedfile); + volume->runtime.frame = 0; + + /* materials */ + BLO_read_pointer_array(reader, (void **)&volume->mat); +} + +static void volume_blend_read_lib(BlendLibReader *reader, ID *id) +{ + Volume *volume = (Volume *)id; + /* Needs to be done *after* cache pointers are restored (call to + * `foreach_cache`/`blo_cache_storage_entry_restore_in_new`), easier for now to do it in + * lib_link... */ + BKE_volume_init_grids(volume); + + for (int a = 0; a < volume->totcol; a++) { + BLO_read_id_address(reader, volume->id.lib, &volume->mat[a]); + } +} + +static void volume_blend_read_expand(BlendExpander *expander, ID *id) +{ + Volume *volume = (Volume *)id; + for (int a = 0; a < volume->totcol; a++) { + BLO_expand(expander, volume->mat[a]); + } +} + IDTypeInfo IDType_ID_VO = { /* id_code */ ID_VO, /* id_filter */ FILTER_ID_VO, @@ -526,10 +583,10 @@ IDTypeInfo IDType_ID_VO = { /* foreach_id */ volume_foreach_id, /* foreach_cache */ volume_foreach_cache, - /* blend_write */ NULL, - /* blend_read_data */ NULL, - /* blend_read_lib */ NULL, - /* blend_read_expand */ NULL, + /* blend_write */ volume_blend_write, + /* blend_read_data */ volume_blend_read_data, + /* blend_read_lib */ volume_blend_read_lib, + /* blend_read_expand */ volume_blend_read_expand, }; void BKE_volume_init_grids(Volume *volume) diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c index 08c7d3b1e91..6727e6a337d 100644 --- a/source/blender/blenlib/intern/math_matrix.c +++ b/source/blender/blenlib/intern/math_matrix.c @@ -2616,9 +2616,9 @@ void print_m4(const char *str, const float m[4][4]) * * Compute the Single Value Decomposition of an arbitrary matrix A * That is compute the 3 matrices U,W,V with U column orthogonal (m,n) - * ,W a diagonal matrix and V an orthogonal square matrix s.t. - * A = U.W.Vt. From this decomposition it is trivial to compute the - * (pseudo-inverse) of A as Ainv = V.Winv.tranpose(U). + * ,W a diagonal matrix and V an orthogonal square matrix `s.t.A = U.W.Vt`. + * From this decomposition it is trivial to compute the (pseudo-inverse) + * of `A` as `Ainv = V.Winv.transpose(U)`. */ void svd_m4(float U[4][4], float s[4], float V[4][4], float A_[4][4]) diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index 18a6e8a3525..6328c887063 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -1300,7 +1300,7 @@ void BLI_setenv_if_new(const char *env, const char *val) /** * Get an env var, result has to be used immediately. * -* On windows getenv gets its variables from a static copy of the environment variables taken at + * On windows getenv gets its variables from a static copy of the environment variables taken at * process start-up, causing it to not pick up on environment variables created during runtime. * This function uses an alternative method to get environment variables that does pick up on * runtime environment variables. diff --git a/source/blender/blenloader/BLO_read_write.h b/source/blender/blenloader/BLO_read_write.h index e05c1046b95..8a6811444af 100644 --- a/source/blender/blenloader/BLO_read_write.h +++ b/source/blender/blenloader/BLO_read_write.h @@ -210,7 +210,7 @@ bool BLO_read_data_is_undo(BlendDataReader *reader); ID *BLO_read_get_new_id_address(BlendLibReader *reader, struct Library *lib, struct ID *id); #define BLO_read_id_address(reader, lib, id_ptr_p) \ - *(id_ptr_p) = (void *)BLO_read_get_new_id_address((reader), (lib), (ID *)*(id_ptr_p)) + *((void **)id_ptr_p) = (void *)BLO_read_get_new_id_address((reader), (lib), (ID *)*(id_ptr_p)) /* Misc. */ bool BLO_read_lib_is_undo(BlendLibReader *reader); diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 3d42330dd4f..b0f0a08651c 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -127,6 +127,7 @@ #include "BKE_fcurve_driver.h" #include "BKE_fluid.h" #include "BKE_global.h" // for G +#include "BKE_gpencil.h" #include "BKE_gpencil_modifier.h" #include "BKE_hair.h" #include "BKE_icons.h" @@ -2537,28 +2538,6 @@ static void lib_link_constraint_channels(BlendLibReader *reader, ID *id, ListBas /** \} */ /* -------------------------------------------------------------------- */ -/** \name Read ID: CacheFiles - * \{ */ - -static void lib_link_cachefiles(BlendLibReader *UNUSED(reader), CacheFile *UNUSED(cache_file)) -{ -} - -static void direct_link_cachefile(BlendDataReader *reader, CacheFile *cache_file) -{ - BLI_listbase_clear(&cache_file->object_paths); - cache_file->handle = NULL; - cache_file->handle_filepath[0] = '\0'; - cache_file->handle_readers = NULL; - - /* relink animdata */ - BLO_read_data_address(reader, &cache_file->adt); - BKE_animdata_blend_read_data(reader, cache_file->adt); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ /** \name Read ID: WorkSpace * \{ */ @@ -2804,32 +2783,6 @@ void blo_do_versions_key_uidgen(Key *key) /** \} */ /* -------------------------------------------------------------------- */ -/** \name Read ID: Texture - * \{ */ - -static void lib_link_texture(BlendLibReader *reader, Tex *tex) -{ - BLO_read_id_address(reader, tex->id.lib, &tex->ima); - BLO_read_id_address(reader, tex->id.lib, &tex->ipo); // XXX deprecated - old animation system -} - -static void direct_link_texture(BlendDataReader *reader, Tex *tex) -{ - BLO_read_data_address(reader, &tex->adt); - BKE_animdata_blend_read_data(reader, tex->adt); - - BLO_read_data_address(reader, &tex->coba); - - BLO_read_data_address(reader, &tex->preview); - BKE_previewimg_blend_read(reader, tex->preview); - - tex->iuser.ok = 1; - tex->iuser.scene = NULL; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ /** \name Read ID: Particle Settings * \{ */ @@ -4947,100 +4900,6 @@ static void direct_link_scene(BlendDataReader *reader, Scene *sce) /** \} */ /* -------------------------------------------------------------------- */ -/** \name Read ID: Grease Pencil - * \{ */ - -/* relink's grease pencil data's refs */ -static void lib_link_gpencil(BlendLibReader *reader, bGPdata *gpd) -{ - /* Relink all data-lock linked by GP data-lock */ - /* Layers */ - LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { - /* Layer -> Parent References */ - BLO_read_id_address(reader, gpd->id.lib, &gpl->parent); - } - - /* materials */ - for (int a = 0; a < gpd->totcol; a++) { - BLO_read_id_address(reader, gpd->id.lib, &gpd->mat[a]); - } -} - -/* relinks grease-pencil data - used for direct_link and old file linkage */ -static void direct_link_gpencil(BlendDataReader *reader, bGPdata *gpd) -{ - /* we must firstly have some grease-pencil data to link! */ - if (gpd == NULL) { - return; - } - - /* relink animdata */ - BLO_read_data_address(reader, &gpd->adt); - BKE_animdata_blend_read_data(reader, gpd->adt); - - /* Ensure full objectmode for linked grease pencil. */ - if (gpd->id.lib != NULL) { - gpd->flag &= ~GP_DATA_STROKE_PAINTMODE; - gpd->flag &= ~GP_DATA_STROKE_EDITMODE; - gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE; - gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE; - gpd->flag &= ~GP_DATA_STROKE_VERTEXMODE; - } - - /* init stroke buffer */ - gpd->runtime.sbuffer = NULL; - gpd->runtime.sbuffer_used = 0; - gpd->runtime.sbuffer_size = 0; - gpd->runtime.tot_cp_points = 0; - - /* relink palettes (old palettes deprecated, only to convert old files) */ - BLO_read_list(reader, &gpd->palettes); - if (gpd->palettes.first != NULL) { - LISTBASE_FOREACH (Palette *, palette, &gpd->palettes) { - BLO_read_list(reader, &palette->colors); - } - } - - /* materials */ - BLO_read_pointer_array(reader, (void **)&gpd->mat); - - /* relink layers */ - BLO_read_list(reader, &gpd->layers); - - LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { - /* relink frames */ - BLO_read_list(reader, &gpl->frames); - - BLO_read_data_address(reader, &gpl->actframe); - - gpl->runtime.icon_id = 0; - - /* Relink masks. */ - BLO_read_list(reader, &gpl->mask_layers); - - LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { - /* relink strokes (and their points) */ - BLO_read_list(reader, &gpf->strokes); - - LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { - /* relink stroke points array */ - BLO_read_data_address(reader, &gps->points); - /* Relink geometry*/ - BLO_read_data_address(reader, &gps->triangles); - - /* relink weight data */ - if (gps->dvert) { - BLO_read_data_address(reader, &gps->dvert); - BKE_defvert_blend_read(reader, gps->totpoints, gps->dvert); - } - } - } - } -} - -/** \} */ - -/* -------------------------------------------------------------------- */ /** \name Read Screen Area/Region (Screen Data) * \{ */ @@ -5182,7 +5041,7 @@ static void direct_link_area(BlendDataReader *reader, ScrArea *area) if (v3d->gpd) { BLO_read_data_address(reader, &v3d->gpd); - direct_link_gpencil(reader, v3d->gpd); + BKE_gpencil_blend_read_data(reader, v3d->gpd); } BLO_read_data_address(reader, &v3d->localvd); @@ -5254,7 +5113,7 @@ static void direct_link_area(BlendDataReader *reader, ScrArea *area) #if 0 sima->gpd = newdataadr(fd, sima->gpd); if (sima->gpd) { - direct_link_gpencil(fd, sima->gpd); + BKE_gpencil_blend_read_data(fd, sima->gpd); } #endif } @@ -5263,7 +5122,7 @@ static void direct_link_area(BlendDataReader *reader, ScrArea *area) if (snode->gpd) { BLO_read_data_address(reader, &snode->gpd); - direct_link_gpencil(reader, snode->gpd); + BKE_gpencil_blend_read_data(reader, snode->gpd); } BLO_read_list(reader, &snode->treepath); @@ -5288,7 +5147,7 @@ static void direct_link_area(BlendDataReader *reader, ScrArea *area) #if 0 if (sseq->gpd) { sseq->gpd = newdataadr(fd, sseq->gpd); - direct_link_gpencil(fd, sseq->gpd); + BKE_gpencil_blend_read_data(fd, sseq->gpd); } #endif sseq->scopes.reference_ibuf = NULL; @@ -6320,158 +6179,6 @@ static void fix_relpaths_library(const char *basepath, Main *main) /** \} */ /* -------------------------------------------------------------------- */ -/** \name Read ID: Sound - * \{ */ - -static void direct_link_sound(BlendDataReader *reader, bSound *sound) -{ - sound->tags = 0; - sound->handle = NULL; - sound->playback_handle = NULL; - - /* versioning stuff, if there was a cache, then we enable caching: */ - if (sound->cache) { - sound->flags |= SOUND_FLAGS_CACHING; - sound->cache = NULL; - } - - if (BLO_read_data_is_undo(reader)) { - sound->tags |= SOUND_TAGS_WAVEFORM_NO_RELOAD; - } - - sound->spinlock = MEM_mallocN(sizeof(SpinLock), "sound_spinlock"); - BLI_spin_init(sound->spinlock); - - /* clear waveform loading flag */ - sound->tags &= ~SOUND_TAGS_WAVEFORM_LOADING; - - BKE_packedfile_blend_read(reader, &sound->packedfile); - BKE_packedfile_blend_read(reader, &sound->newpackedfile); -} - -static void lib_link_sound(BlendLibReader *reader, bSound *sound) -{ - BLO_read_id_address( - reader, sound->id.lib, &sound->ipo); // XXX deprecated - old animation system -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Read ID: Hair - * \{ */ - -static void lib_link_hair(BlendLibReader *reader, Hair *hair) -{ - for (int a = 0; a < hair->totcol; a++) { - BLO_read_id_address(reader, hair->id.lib, &hair->mat[a]); - } -} - -static void direct_link_hair(BlendDataReader *reader, Hair *hair) -{ - BLO_read_data_address(reader, &hair->adt); - BKE_animdata_blend_read_data(reader, hair->adt); - - /* Geometry */ - CustomData_blend_read(reader, &hair->pdata, hair->totpoint); - CustomData_blend_read(reader, &hair->cdata, hair->totcurve); - BKE_hair_update_customdata_pointers(hair); - - /* Materials */ - BLO_read_pointer_array(reader, (void **)&hair->mat); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Read ID: Point Cloud - * \{ */ - -static void lib_link_pointcloud(BlendLibReader *reader, PointCloud *pointcloud) -{ - for (int a = 0; a < pointcloud->totcol; a++) { - BLO_read_id_address(reader, pointcloud->id.lib, &pointcloud->mat[a]); - } -} - -static void direct_link_pointcloud(BlendDataReader *reader, PointCloud *pointcloud) -{ - BLO_read_data_address(reader, &pointcloud->adt); - BKE_animdata_blend_read_data(reader, pointcloud->adt); - - /* Geometry */ - CustomData_blend_read(reader, &pointcloud->pdata, pointcloud->totpoint); - BKE_pointcloud_update_customdata_pointers(pointcloud); - - /* Materials */ - BLO_read_pointer_array(reader, (void **)&pointcloud->mat); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Read ID: Volume - * \{ */ - -static void lib_link_volume(BlendLibReader *reader, Volume *volume) -{ - /* Needs to be done *after* cache pointers are restored (call to - * `foreach_cache`/`blo_cache_storage_entry_restore_in_new`), easier for now to do it in - * lib_link... */ - BKE_volume_init_grids(volume); - - for (int a = 0; a < volume->totcol; a++) { - BLO_read_id_address(reader, volume->id.lib, &volume->mat[a]); - } -} - -static void direct_link_volume(BlendDataReader *reader, Volume *volume) -{ - BLO_read_data_address(reader, &volume->adt); - BKE_animdata_blend_read_data(reader, volume->adt); - - BKE_packedfile_blend_read(reader, &volume->packedfile); - volume->runtime.frame = 0; - - /* materials */ - BLO_read_pointer_array(reader, (void **)&volume->mat); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Read ID: Simulation - * \{ */ - -static void lib_link_simulation(BlendLibReader *reader, Simulation *simulation) -{ - LISTBASE_FOREACH (SimulationDependency *, dependency, &simulation->dependencies) { - BLO_read_id_address(reader, simulation->id.lib, &dependency->id); - } -} - -static void direct_link_simulation(BlendDataReader *reader, Simulation *simulation) -{ - BLO_read_data_address(reader, &simulation->adt); - BKE_animdata_blend_read_data(reader, simulation->adt); - - BLO_read_list(reader, &simulation->states); - LISTBASE_FOREACH (SimulationState *, state, &simulation->states) { - BLO_read_data_address(reader, &state->name); - BLO_read_data_address(reader, &state->type); - if (STREQ(state->type, SIM_TYPE_NAME_PARTICLE_SIMULATION)) { - ParticleSimulationState *particle_state = (ParticleSimulationState *)state; - CustomData_blend_read(reader, &particle_state->attributes, particle_state->tot_particles); - } - } - - BLO_read_list(reader, &simulation->dependencies); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ /** \name Read Library Data Block * \{ */ @@ -6630,45 +6337,21 @@ static bool direct_link_id(FileData *fd, Main *main, const int tag, ID *id, ID * case ID_OB: direct_link_object(&reader, (Object *)id); break; - case ID_TE: - direct_link_texture(&reader, (Tex *)id); - break; case ID_IP: direct_link_ipo(&reader, (Ipo *)id); break; case ID_LI: direct_link_library(fd, (Library *)id, main); break; - case ID_SO: - direct_link_sound(&reader, (bSound *)id); - break; case ID_GR: direct_link_collection(&reader, (Collection *)id); break; case ID_PA: direct_link_particlesettings(&reader, (ParticleSettings *)id); break; - case ID_GD: - direct_link_gpencil(&reader, (bGPdata *)id); - break; - case ID_CF: - direct_link_cachefile(&reader, (CacheFile *)id); - break; case ID_WS: direct_link_workspace(&reader, (WorkSpace *)id, main); break; - case ID_HA: - direct_link_hair(&reader, (Hair *)id); - break; - case ID_PT: - direct_link_pointcloud(&reader, (PointCloud *)id); - break; - case ID_VO: - direct_link_volume(&reader, (Volume *)id); - break; - case ID_SIM: - direct_link_simulation(&reader, (Simulation *)id); - break; case ID_ME: case ID_LT: case ID_AC: @@ -6692,6 +6375,14 @@ static bool direct_link_id(FileData *fd, Main *main, const int tag, ID *id, ID * case ID_AR: case ID_LP: case ID_KE: + case ID_TE: + case ID_GD: + case ID_HA: + case ID_PT: + case ID_VO: + case ID_SIM: + case ID_SO: + case ID_CF: /* Do nothing. Handled by IDTypeInfo callback. */ break; } @@ -7311,8 +7002,8 @@ static void lib_link_all(FileData *fd, Main *bmain) lib_link_object(&reader, (Object *)id); break; case ID_SCR: - /* DO NOT skip screens here, - * 3D viewport may contains pointers to other ID data (like bgpic)! See T41411. */ + /* DO NOT skip screens here, 3D viewport may contains pointers + * to other ID data (like #View3D.ob_center)! See T41411. */ lib_link_screen(&reader, (bScreen *)id); break; case ID_PA: @@ -7321,30 +7012,6 @@ static void lib_link_all(FileData *fd, Main *bmain) case ID_GR: lib_link_collection(&reader, (Collection *)id); break; - case ID_SO: - lib_link_sound(&reader, (bSound *)id); - break; - case ID_CF: - lib_link_cachefiles(&reader, (CacheFile *)id); - break; - case ID_HA: - lib_link_hair(&reader, (Hair *)id); - break; - case ID_PT: - lib_link_pointcloud(&reader, (PointCloud *)id); - break; - case ID_VO: - lib_link_volume(&reader, (Volume *)id); - break; - case ID_TE: - lib_link_texture(&reader, (Tex *)id); - break; - case ID_GD: - lib_link_gpencil(&reader, (bGPdata *)id); - break; - case ID_SIM: - lib_link_simulation(&reader, (Simulation *)id); - break; case ID_IP: /* XXX deprecated... still needs to be maintained for version patches still. */ lib_link_ipo(&reader, (Ipo *)id); @@ -7375,6 +7042,14 @@ static void lib_link_all(FileData *fd, Main *bmain) case ID_AR: case ID_LP: case ID_KE: + case ID_TE: + case ID_GD: + case ID_HA: + case ID_PT: + case ID_VO: + case ID_SIM: + case ID_SO: + case ID_CF: /* Do nothing. Handled by IDTypeInfo callback. */ break; } @@ -8060,12 +7735,6 @@ static void expand_collection(BlendExpander *expander, Collection *collection) #endif } -static void expand_texture(BlendExpander *expander, Tex *tex) -{ - BLO_expand(expander, tex->ima); - BLO_expand(expander, tex->ipo); // XXX deprecated - old animation system -} - /* callback function used to expand constraint ID-links */ static void expand_constraint_cb(bConstraint *UNUSED(con), ID **idpoin, @@ -8308,26 +7977,6 @@ static void expand_scene(BlendExpander *expander, Scene *sce) } } -static void expand_cachefile(BlendExpander *UNUSED(expander), CacheFile *UNUSED(cache_file)) -{ -} - -static void expand_sound(BlendExpander *expander, bSound *snd) -{ - BLO_expand(expander, snd->ipo); // XXX deprecated - old animation system -} - -static void expand_gpencil(BlendExpander *expander, bGPdata *gpd) -{ - LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { - BLO_expand(expander, gpl->parent); - } - - for (int a = 0; a < gpd->totcol; a++) { - BLO_expand(expander, gpd->mat[a]); - } -} - static void expand_workspace(BlendExpander *expander, WorkSpace *workspace) { LISTBASE_FOREACH (WorkSpaceLayout *, layout, &workspace->layouts) { @@ -8335,34 +7984,6 @@ static void expand_workspace(BlendExpander *expander, WorkSpace *workspace) } } -static void expand_hair(BlendExpander *expander, Hair *hair) -{ - for (int a = 0; a < hair->totcol; a++) { - BLO_expand(expander, hair->mat[a]); - } -} - -static void expand_pointcloud(BlendExpander *expander, PointCloud *pointcloud) -{ - for (int a = 0; a < pointcloud->totcol; a++) { - BLO_expand(expander, pointcloud->mat[a]); - } -} - -static void expand_volume(BlendExpander *expander, Volume *volume) -{ - for (int a = 0; a < volume->totcol; a++) { - BLO_expand(expander, volume->mat[a]); - } -} - -static void expand_simulation(BlendExpander *expander, Simulation *simulation) -{ - LISTBASE_FOREACH (SimulationDependency *, dependency, &simulation->dependencies) { - BLO_expand(expander, dependency->id); - } -} - /** * Set the callback func used over all ID data found by \a BLO_expand_main func. * @@ -8412,12 +8033,6 @@ void BLO_expand_main(void *fdhandle, Main *mainvar) case ID_SCE: expand_scene(&expander, (Scene *)id); break; - case ID_TE: - expand_texture(&expander, (Tex *)id); - break; - case ID_SO: - expand_sound(&expander, (bSound *)id); - break; case ID_GR: expand_collection(&expander, (Collection *)id); break; @@ -8427,27 +8042,9 @@ void BLO_expand_main(void *fdhandle, Main *mainvar) case ID_PA: expand_particlesettings(&expander, (ParticleSettings *)id); break; - case ID_GD: - expand_gpencil(&expander, (bGPdata *)id); - break; - case ID_CF: - expand_cachefile(&expander, (CacheFile *)id); - break; case ID_WS: expand_workspace(&expander, (WorkSpace *)id); break; - case ID_HA: - expand_hair(&expander, (Hair *)id); - break; - case ID_PT: - expand_pointcloud(&expander, (PointCloud *)id); - break; - case ID_VO: - expand_volume(&expander, (Volume *)id); - break; - case ID_SIM: - expand_simulation(&expander, (Simulation *)id); - break; default: break; } diff --git a/source/blender/blenloader/intern/versioning_userdef.c b/source/blender/blenloader/intern/versioning_userdef.c index d04907872b7..de4cff0101d 100644 --- a/source/blender/blenloader/intern/versioning_userdef.c +++ b/source/blender/blenloader/intern/versioning_userdef.c @@ -233,6 +233,8 @@ static void do_versions_theme(const UserDef *userdef, bTheme *btheme) * the outliner's, and it's less disruptive to just copy them. */ copy_v4_v4_uchar(btheme->space_file.back, btheme->space_outliner.back); copy_v4_v4_uchar(btheme->space_file.row_alternate, btheme->space_outliner.row_alternate); + + FROM_DEFAULT_V4_UCHAR(space_image.grid); } #undef FROM_DEFAULT_V4_UCHAR diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index d4e3f4646d6..b3e937a29b2 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -95,9 +95,7 @@ #include "DNA_anim_types.h" #include "DNA_armature_types.h" -#include "DNA_brush_types.h" #include "DNA_cachefile_types.h" -#include "DNA_camera_types.h" #include "DNA_cloth_types.h" #include "DNA_collection_types.h" #include "DNA_constraint_types.h" @@ -106,45 +104,23 @@ #include "DNA_fileglobal_types.h" #include "DNA_fluid_types.h" #include "DNA_genfile.h" -#include "DNA_gpencil_modifier_types.h" -#include "DNA_gpencil_types.h" -#include "DNA_hair_types.h" -#include "DNA_key_types.h" -#include "DNA_lattice_types.h" -#include "DNA_layer_types.h" -#include "DNA_light_types.h" #include "DNA_lightprobe_types.h" -#include "DNA_linestyle_types.h" -#include "DNA_mask_types.h" -#include "DNA_material_types.h" -#include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" -#include "DNA_meta_types.h" #include "DNA_movieclip_types.h" -#include "DNA_node_types.h" #include "DNA_object_force_types.h" #include "DNA_object_types.h" -#include "DNA_packedFile_types.h" #include "DNA_particle_types.h" #include "DNA_pointcache_types.h" -#include "DNA_pointcloud_types.h" #include "DNA_rigidbody_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_sdna_types.h" #include "DNA_sequence_types.h" #include "DNA_shader_fx_types.h" -#include "DNA_simulation_types.h" -#include "DNA_sound_types.h" #include "DNA_space_types.h" -#include "DNA_speaker_types.h" -#include "DNA_text_types.h" -#include "DNA_vfont_types.h" #include "DNA_view3d_types.h" -#include "DNA_volume_types.h" #include "DNA_windowmanager_types.h" #include "DNA_workspace_types.h" -#include "DNA_world_types.h" #include "BLI_bitmap.h" #include "BLI_blenlib.h" @@ -160,7 +136,6 @@ #include "BKE_collection.h" #include "BKE_colortools.h" #include "BKE_constraint.h" -#include "BKE_curve.h" #include "BKE_curveprofile.h" #include "BKE_deform.h" #include "BKE_fcurve.h" @@ -1393,32 +1368,6 @@ static void write_object(BlendWriter *writer, Object *ob, const void *id_address } } -static void write_texture(BlendWriter *writer, Tex *tex, const void *id_address) -{ - if (tex->id.us > 0 || BLO_write_is_undo(writer)) { - /* write LibData */ - BLO_write_id_struct(writer, Tex, id_address, &tex->id); - BKE_id_blend_write(writer, &tex->id); - - if (tex->adt) { - BKE_animdata_blend_write(writer, tex->adt); - } - - /* direct data */ - if (tex->coba) { - BLO_write_struct(writer, ColorBand, tex->coba); - } - - /* nodetree is integral part of texture, no libdata */ - if (tex->nodetree) { - BLO_write_struct(writer, bNodeTree, tex->nodetree); - ntreeBlendWrite(writer, tex->nodetree); - } - - BKE_previewimg_blend_write(writer, tex->preview); - } -} - static void write_collection_nolib(BlendWriter *writer, Collection *collection) { /* Shared function for collection data-blocks and scene master collection. */ @@ -1791,47 +1740,6 @@ static void write_scene(BlendWriter *writer, Scene *sce, const void *id_address) BLI_assert(sce->layer_properties == NULL); } -static void write_gpencil(BlendWriter *writer, bGPdata *gpd, const void *id_address) -{ - if (gpd->id.us > 0 || BLO_write_is_undo(writer)) { - /* Clean up, important in undo case to reduce false detection of changed data-blocks. */ - /* XXX not sure why the whole run-time data is not cleared in reading code, - * for now mimicking it here. */ - gpd->runtime.sbuffer = NULL; - gpd->runtime.sbuffer_used = 0; - gpd->runtime.sbuffer_size = 0; - gpd->runtime.tot_cp_points = 0; - - /* write gpd data block to file */ - BLO_write_id_struct(writer, bGPdata, id_address, &gpd->id); - BKE_id_blend_write(writer, &gpd->id); - - if (gpd->adt) { - BKE_animdata_blend_write(writer, gpd->adt); - } - - BLO_write_pointer_array(writer, gpd->totcol, gpd->mat); - - /* write grease-pencil layers to file */ - BLO_write_struct_list(writer, bGPDlayer, &gpd->layers); - LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { - /* Write mask list. */ - BLO_write_struct_list(writer, bGPDlayer_Mask, &gpl->mask_layers); - /* write this layer's frames to file */ - BLO_write_struct_list(writer, bGPDframe, &gpl->frames); - LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { - /* write strokes */ - BLO_write_struct_list(writer, bGPDstroke, &gpf->strokes); - LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { - BLO_write_struct_array(writer, bGPDspoint, gps->totpoints, gps->points); - BLO_write_struct_array(writer, bGPDtriangle, gps->tot_triangles, gps->triangles); - BKE_defvert_blend_write(writer, gps->totpoints, gps->dvert); - } - } - } - } -} - static void write_wm_xr_data(BlendWriter *writer, wmXrData *xr_data) { write_view3dshading(writer, &xr_data->session_settings.shading); @@ -2122,40 +2030,6 @@ static void write_screen(BlendWriter *writer, bScreen *screen, const void *id_ad } } -static void write_sound(BlendWriter *writer, bSound *sound, const void *id_address) -{ - if (sound->id.us > 0 || BLO_write_is_undo(writer)) { - /* Clean up, important in undo case to reduce false detection of changed datablocks. */ - sound->tags = 0; - sound->handle = NULL; - sound->playback_handle = NULL; - sound->spinlock = NULL; - - /* write LibData */ - BLO_write_id_struct(writer, bSound, id_address, &sound->id); - BKE_id_blend_write(writer, &sound->id); - - BKE_packedfile_blend_write(writer, sound->packedfile); - } -} - -static void write_cachefile(BlendWriter *writer, CacheFile *cache_file, const void *id_address) -{ - if (cache_file->id.us > 0 || BLO_write_is_undo(writer)) { - /* Clean up, important in undo case to reduce false detection of changed datablocks. */ - BLI_listbase_clear(&cache_file->object_paths); - cache_file->handle = NULL; - memset(cache_file->handle_filepath, 0, sizeof(cache_file->handle_filepath)); - cache_file->handle_readers = NULL; - - BLO_write_id_struct(writer, CacheFile, id_address, &cache_file->id); - - if (cache_file->adt) { - BKE_animdata_blend_write(writer, cache_file->adt); - } - } -} - static void write_workspace(BlendWriter *writer, WorkSpace *workspace, const void *id_address) { BLO_write_id_struct(writer, WorkSpace, id_address, &workspace->id); @@ -2171,136 +2045,6 @@ static void write_workspace(BlendWriter *writer, WorkSpace *workspace, const voi } } -static void write_hair(BlendWriter *writer, Hair *hair, const void *id_address) -{ - if (hair->id.us > 0 || BLO_write_is_undo(writer)) { - CustomDataLayer *players = NULL, players_buff[CD_TEMP_CHUNK_SIZE]; - CustomDataLayer *clayers = NULL, clayers_buff[CD_TEMP_CHUNK_SIZE]; - CustomData_blend_write_prepare(&hair->pdata, &players, players_buff, ARRAY_SIZE(players_buff)); - CustomData_blend_write_prepare(&hair->cdata, &clayers, clayers_buff, ARRAY_SIZE(clayers_buff)); - - /* Write LibData */ - BLO_write_id_struct(writer, Hair, id_address, &hair->id); - BKE_id_blend_write(writer, &hair->id); - - /* Direct data */ - CustomData_blend_write(writer, &hair->pdata, players, hair->totpoint, CD_MASK_ALL, &hair->id); - CustomData_blend_write(writer, &hair->cdata, clayers, hair->totcurve, CD_MASK_ALL, &hair->id); - - BLO_write_pointer_array(writer, hair->totcol, hair->mat); - if (hair->adt) { - BKE_animdata_blend_write(writer, hair->adt); - } - - /* Remove temporary data. */ - if (players && players != players_buff) { - MEM_freeN(players); - } - if (clayers && clayers != clayers_buff) { - MEM_freeN(clayers); - } - } -} - -static void write_pointcloud(BlendWriter *writer, PointCloud *pointcloud, const void *id_address) -{ - if (pointcloud->id.us > 0 || BLO_write_is_undo(writer)) { - CustomDataLayer *players = NULL, players_buff[CD_TEMP_CHUNK_SIZE]; - CustomData_blend_write_prepare( - &pointcloud->pdata, &players, players_buff, ARRAY_SIZE(players_buff)); - - /* Write LibData */ - BLO_write_id_struct(writer, PointCloud, id_address, &pointcloud->id); - BKE_id_blend_write(writer, &pointcloud->id); - - /* Direct data */ - CustomData_blend_write( - writer, &pointcloud->pdata, players, pointcloud->totpoint, CD_MASK_ALL, &pointcloud->id); - - BLO_write_pointer_array(writer, pointcloud->totcol, pointcloud->mat); - if (pointcloud->adt) { - BKE_animdata_blend_write(writer, pointcloud->adt); - } - - /* Remove temporary data. */ - if (players && players != players_buff) { - MEM_freeN(players); - } - } -} - -static void write_volume(BlendWriter *writer, Volume *volume, const void *id_address) -{ - if (volume->id.us > 0 || BLO_write_is_undo(writer)) { - /* Clean up, important in undo case to reduce false detection of changed datablocks. */ - volume->runtime.grids = 0; - - /* write LibData */ - BLO_write_id_struct(writer, Volume, id_address, &volume->id); - BKE_id_blend_write(writer, &volume->id); - - /* direct data */ - BLO_write_pointer_array(writer, volume->totcol, volume->mat); - if (volume->adt) { - BKE_animdata_blend_write(writer, volume->adt); - } - - BKE_packedfile_blend_write(writer, volume->packedfile); - } -} - -static void write_simulation(BlendWriter *writer, Simulation *simulation, const void *id_address) -{ - if (simulation->id.us > 0 || BLO_write_is_undo(writer)) { - BLO_write_id_struct(writer, Simulation, id_address, &simulation->id); - BKE_id_blend_write(writer, &simulation->id); - - if (simulation->adt) { - BKE_animdata_blend_write(writer, simulation->adt); - } - - /* nodetree is integral part of simulation, no libdata */ - if (simulation->nodetree) { - BLO_write_struct(writer, bNodeTree, simulation->nodetree); - ntreeBlendWrite(writer, simulation->nodetree); - } - - LISTBASE_FOREACH (SimulationState *, state, &simulation->states) { - BLO_write_string(writer, state->name); - BLO_write_string(writer, state->type); - /* TODO: Decentralize this part. */ - if (STREQ(state->type, SIM_TYPE_NAME_PARTICLE_SIMULATION)) { - ParticleSimulationState *particle_state = (ParticleSimulationState *)state; - - CustomDataLayer *players = NULL, players_buff[CD_TEMP_CHUNK_SIZE]; - CustomData_blend_write_prepare( - &particle_state->attributes, &players, players_buff, ARRAY_SIZE(players_buff)); - - BLO_write_struct(writer, ParticleSimulationState, particle_state); - - CustomData_blend_write(writer, - &particle_state->attributes, - players, - particle_state->tot_particles, - CD_MASK_ALL, - &simulation->id); - - /* Remove temporary data. */ - if (players && players != players_buff) { - MEM_freeN(players); - } - } - else if (STREQ(state->type, SIM_TYPE_NAME_PARTICLE_MESH_EMITTER)) { - ParticleMeshEmitterSimulationState *emitter_state = (ParticleMeshEmitterSimulationState *) - state; - BLO_write_struct(writer, ParticleMeshEmitterSimulationState, emitter_state); - } - } - - BLO_write_struct_list(writer, SimulationDependency, &simulation->dependencies); - } -} - /* Keep it last of write_foodata functions. */ static void write_libraries(WriteData *wd, Main *main) { @@ -2571,39 +2315,15 @@ static bool write_file_handle(Main *mainvar, case ID_SCE: write_scene(&writer, (Scene *)id_buffer, id); break; - case ID_SO: - write_sound(&writer, (bSound *)id_buffer, id); - break; case ID_GR: write_collection(&writer, (Collection *)id_buffer, id); break; case ID_OB: write_object(&writer, (Object *)id_buffer, id); break; - case ID_TE: - write_texture(&writer, (Tex *)id_buffer, id); - break; case ID_PA: write_particlesettings(&writer, (ParticleSettings *)id_buffer, id); break; - case ID_GD: - write_gpencil(&writer, (bGPdata *)id_buffer, id); - break; - case ID_CF: - write_cachefile(&writer, (CacheFile *)id_buffer, id); - break; - case ID_HA: - write_hair(&writer, (Hair *)id_buffer, id); - break; - case ID_PT: - write_pointcloud(&writer, (PointCloud *)id_buffer, id); - break; - case ID_VO: - write_volume(&writer, (Volume *)id_buffer, id); - break; - case ID_SIM: - write_simulation(&writer, (Simulation *)id_buffer, id); - break; case ID_ME: case ID_LT: case ID_AC: @@ -2627,6 +2347,14 @@ static bool write_file_handle(Main *mainvar, case ID_AR: case ID_LP: case ID_KE: + case ID_TE: + case ID_GD: + case ID_HA: + case ID_PT: + case ID_VO: + case ID_SIM: + case ID_SO: + case ID_CF: /* Do nothing, handled in IDTypeInfo callback. */ break; case ID_LI: diff --git a/source/blender/bmesh/bmesh.h b/source/blender/bmesh/bmesh.h index 5f5d6baaba2..9199801d1a1 100644 --- a/source/blender/bmesh/bmesh.h +++ b/source/blender/bmesh/bmesh.h @@ -41,7 +41,7 @@ * \subsection bm_faces Faces * * Faces in BMesh are stored as a circular linked list of loops. Loops store per-face-vertex data - * (amongst other things outlined later in this document), and define the face boundary. + * (among other things outlined later in this document), and define the face boundary. * \subsection bm_loop The Loop * * Loops can be thought of as a *face-corner*, since faces don't reference verts or edges directly. diff --git a/source/blender/compositor/operations/COM_ViewerOperation.cpp b/source/blender/compositor/operations/COM_ViewerOperation.cpp index 3d5d50e1c7f..e1d891559a7 100644 --- a/source/blender/compositor/operations/COM_ViewerOperation.cpp +++ b/source/blender/compositor/operations/COM_ViewerOperation.cpp @@ -190,7 +190,7 @@ void ViewerOperation::updateImage(rcti *rect) rect->ymin, rect->xmax, rect->ymax); - + this->m_image->gpuflag |= IMA_GPU_REFRESH; this->updateDraw(); } diff --git a/source/blender/depsgraph/intern/depsgraph_physics.cc b/source/blender/depsgraph/intern/depsgraph_physics.cc index bc73700e1ba..0b8203ab05f 100644 --- a/source/blender/depsgraph/intern/depsgraph_physics.cc +++ b/source/blender/depsgraph/intern/depsgraph_physics.cc @@ -96,7 +96,7 @@ ListBase *DEG_get_collision_relations(const Depsgraph *graph, if (hash == nullptr) { return nullptr; } - /* Note: nullptr is a valid loolup key here as it means that the relation is not bound to a + /* Note: nullptr is a valid lookup key here as it means that the relation is not bound to a * specific collection. */ ID *collection_orig = DEG_get_original_id(object_id_safe(collection)); return hash->lookup_default(collection_orig, nullptr); diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 8aea2f8e969..8fbf30507a5 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -77,6 +77,8 @@ set(SRC intern/draw_select_buffer.c intern/draw_view.c engines/basic/basic_engine.c + engines/image/image_engine.c + engines/image/image_shader.c engines/eevee/eevee_bloom.c engines/eevee/eevee_data.c engines/eevee/eevee_depth_of_field.c @@ -132,6 +134,7 @@ set(SRC engines/overlay/overlay_edit_curve.c engines/overlay/overlay_edit_mesh.c engines/overlay/overlay_edit_text.c + engines/overlay/overlay_edit_uv.c engines/overlay/overlay_engine.c engines/overlay/overlay_extra.c engines/overlay/overlay_facing.c @@ -319,6 +322,7 @@ data_to_c_simple(engines/basic/shaders/conservative_depth_geom.glsl SRC) data_to_c_simple(engines/basic/shaders/depth_vert.glsl SRC) data_to_c_simple(engines/basic/shaders/depth_frag.glsl SRC) +data_to_c_simple(engines/overlay/shaders/common_overlay_lib.glsl SRC) data_to_c_simple(engines/overlay/shaders/antialiasing_frag.glsl SRC) data_to_c_simple(engines/overlay/shaders/antialiasing_vert.glsl SRC) data_to_c_simple(engines/overlay/shaders/armature_dof_vert.glsl SRC) @@ -362,6 +366,15 @@ data_to_c_simple(engines/overlay/shaders/edit_mesh_skin_root_vert.glsl SRC) data_to_c_simple(engines/overlay/shaders/edit_mesh_vert.glsl SRC) data_to_c_simple(engines/overlay/shaders/edit_particle_strand_vert.glsl SRC) data_to_c_simple(engines/overlay/shaders/edit_particle_point_vert.glsl SRC) +data_to_c_simple(engines/overlay/shaders/edit_uv_edges_vert.glsl SRC) +data_to_c_simple(engines/overlay/shaders/edit_uv_edges_geom.glsl SRC) +data_to_c_simple(engines/overlay/shaders/edit_uv_edges_frag.glsl SRC) +data_to_c_simple(engines/overlay/shaders/edit_uv_verts_vert.glsl SRC) +data_to_c_simple(engines/overlay/shaders/edit_uv_verts_frag.glsl SRC) +data_to_c_simple(engines/overlay/shaders/edit_uv_faces_vert.glsl SRC) +data_to_c_simple(engines/overlay/shaders/edit_uv_face_dots_vert.glsl SRC) +data_to_c_simple(engines/overlay/shaders/edit_uv_stretching_vert.glsl SRC) +data_to_c_simple(engines/overlay/shaders/edit_uv_tiled_image_borders_vert.glsl SRC) data_to_c_simple(engines/overlay/shaders/extra_frag.glsl SRC) data_to_c_simple(engines/overlay/shaders/extra_vert.glsl SRC) data_to_c_simple(engines/overlay/shaders/extra_groundline_vert.glsl SRC) @@ -402,6 +415,9 @@ data_to_c_simple(engines/overlay/shaders/wireframe_vert.glsl SRC) data_to_c_simple(engines/overlay/shaders/wireframe_frag.glsl SRC) data_to_c_simple(engines/overlay/shaders/xray_fade_frag.glsl SRC) +data_to_c_simple(engines/image/shaders/engine_image_frag.glsl SRC) +data_to_c_simple(engines/image/shaders/engine_image_vert.glsl SRC) + list(APPEND INC ) diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h index 6db3bb39643..ca5c2c94b40 100644 --- a/source/blender/draw/DRW_engine.h +++ b/source/blender/draw/DRW_engine.h @@ -99,6 +99,10 @@ void DRW_draw_render_loop_offscreen(struct Depsgraph *depsgraph, const bool do_color_management, struct GPUOffScreen *ofs, struct GPUViewport *viewport); +void DRW_draw_render_loop_2d_ex(struct Depsgraph *depsgraph, + struct ARegion *region, + struct GPUViewport *viewport, + const struct bContext *evil_C); void DRW_draw_select_loop(struct Depsgraph *depsgraph, struct ARegion *region, struct View3D *v3d, diff --git a/source/blender/draw/engines/image/image_engine.c b/source/blender/draw/engines/image/image_engine.c new file mode 100644 index 00000000000..9f1278b473b --- /dev/null +++ b/source/blender/draw/engines/image/image_engine.c @@ -0,0 +1,304 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2020, Blender Foundation. + */ + +/** \file + * \ingroup draw_editors + * + * Draw engine to draw the Image/UV editor + */ + +#include "DRW_render.h" + +#include "BKE_image.h" +#include "BKE_object.h" + +#include "DNA_camera_types.h" + +#include "IMB_imbuf_types.h" + +#include "ED_image.h" + +#include "GPU_batch.h" + +#include "image_engine.h" +#include "image_private.h" + +#define SIMA_DRAW_FLAG_SHOW_ALPHA (1 << 0) +#define SIMA_DRAW_FLAG_APPLY_ALPHA (1 << 1) +#define SIMA_DRAW_FLAG_SHUFFLING (1 << 2) +#define SIMA_DRAW_FLAG_DEPTH (1 << 3) +#define SIMA_DRAW_FLAG_TILED (1 << 4) +#define SIMA_DRAW_FLAG_DO_REPEAT (1 << 5) + +static void image_cache_image_add(DRWShadingGroup *grp, Image *image) +{ + const bool is_tiled_texture = image && image->source == IMA_SRC_TILED; + float obmat[4][4]; + unit_m4(obmat); + + GPUBatch *geom = DRW_cache_quad_get(); + + if (is_tiled_texture) { + LISTBASE_FOREACH (ImageTile *, tile, &image->tiles) { + const int tile_x = ((tile->tile_number - 1001) % 10); + const int tile_y = ((tile->tile_number - 1001) / 10); + obmat[3][1] = (float)tile_y; + obmat[3][0] = (float)tile_x; + DRW_shgroup_call_obmat(grp, geom, obmat); + } + } + else { + DRW_shgroup_call_obmat(grp, geom, obmat); + } +} + +static void image_gpu_texture_get(Image *image, + ImageUser *iuser, + ImBuf *ibuf, + GPUTexture **r_gpu_texture, + bool *r_owns_texture, + GPUTexture **r_tex_tile_data) +{ + + const DRWContextState *draw_ctx = DRW_context_state_get(); + SpaceImage *sima = (SpaceImage *)draw_ctx->space_data; + + if (image) { + if (BKE_image_is_multilayer(image)) { + /* update multiindex and pass for the current eye */ + BKE_image_multilayer_index(image->rr, &sima->iuser); + } + else { + BKE_image_multiview_index(image, &sima->iuser); + } + + if (ibuf) { + if (sima->flag & SI_SHOW_ZBUF && (ibuf->zbuf || ibuf->zbuf_float || (ibuf->channels == 1))) { + if (ibuf->zbuf) { + BLI_assert(!"Integer based depth buffers not supported"); + } + else if (ibuf->zbuf_float) { + *r_gpu_texture = GPU_texture_create_2d( + __func__, ibuf->x, ibuf->y, 0, GPU_R16F, ibuf->zbuf_float); + *r_owns_texture = true; + } + else if (ibuf->rect_float && ibuf->channels == 1) { + *r_gpu_texture = GPU_texture_create_2d( + __func__, ibuf->x, ibuf->y, 0, GPU_R16F, ibuf->rect_float); + *r_owns_texture = true; + } + } + else if (image->source == IMA_SRC_TILED) { + *r_gpu_texture = BKE_image_get_gpu_tiles(image, iuser, ibuf); + *r_tex_tile_data = BKE_image_get_gpu_tilemap(image, iuser, NULL); + *r_owns_texture = false; + } + else { + *r_gpu_texture = BKE_image_get_gpu_texture(image, iuser, ibuf); + *r_owns_texture = false; + } + } + } +} + +static void image_cache_image(IMAGE_Data *vedata, Image *image, ImageUser *iuser, ImBuf *ibuf) +{ + IMAGE_PassList *psl = vedata->psl; + IMAGE_StorageList *stl = vedata->stl; + IMAGE_PrivateData *pd = stl->pd; + + const DRWContextState *draw_ctx = DRW_context_state_get(); + const Scene *scene = draw_ctx->scene; + SpaceImage *sima = (SpaceImage *)draw_ctx->space_data; + + GPUTexture *tex_tile_data = NULL; + image_gpu_texture_get(image, iuser, ibuf, &pd->texture, &pd->owns_texture, &tex_tile_data); + + if (pd->texture) { + static float color[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + static float shuffle[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + static float far_near[2] = {100.0f, 0.0f}; + + if (scene->camera && scene->camera->type == OB_CAMERA) { + far_near[1] = ((Camera *)scene->camera->data)->clip_start; + far_near[0] = ((Camera *)scene->camera->data)->clip_end; + } + + const bool use_premul_alpha = image->alpha_mode == IMA_ALPHA_PREMUL; + const bool is_tiled_texture = tex_tile_data != NULL; + const bool do_repeat = (!is_tiled_texture) && ((sima->flag & SI_DRAW_TILE) != 0); + const bool is_zoom_out = sima->zoom < 1.0f; + + /* use interpolation filtering when zooming out */ + eGPUSamplerState state = 0; + SET_FLAG_FROM_TEST(state, is_zoom_out, GPU_SAMPLER_FILTER); + + int draw_flags = 0; + SET_FLAG_FROM_TEST(draw_flags, do_repeat, SIMA_DRAW_FLAG_DO_REPEAT); + + if ((sima->flag & SI_USE_ALPHA) != 0) { + /* Show RGBA */ + draw_flags |= SIMA_DRAW_FLAG_SHOW_ALPHA | SIMA_DRAW_FLAG_APPLY_ALPHA; + } + else if ((sima->flag & SI_SHOW_ALPHA) != 0) { + draw_flags |= SIMA_DRAW_FLAG_SHUFFLING; + copy_v4_fl4(shuffle, 0.0f, 0.0f, 0.0f, 1.0f); + } + else if ((sima->flag & SI_SHOW_ZBUF) != 0) { + draw_flags |= SIMA_DRAW_FLAG_DEPTH | SIMA_DRAW_FLAG_SHUFFLING; + copy_v4_fl4(shuffle, 1.0f, 0.0f, 0.0f, 0.0f); + } + else if ((sima->flag & SI_SHOW_R) != 0) { + draw_flags |= SIMA_DRAW_FLAG_APPLY_ALPHA | SIMA_DRAW_FLAG_SHUFFLING; + copy_v4_fl4(shuffle, 1.0f, 0.0f, 0.0f, 0.0f); + } + else if ((sima->flag & SI_SHOW_G) != 0) { + draw_flags |= SIMA_DRAW_FLAG_APPLY_ALPHA | SIMA_DRAW_FLAG_SHUFFLING; + copy_v4_fl4(shuffle, 0.0f, 1.0f, 0.0f, 0.0f); + } + else if ((sima->flag & SI_SHOW_B) != 0) { + draw_flags |= SIMA_DRAW_FLAG_APPLY_ALPHA | SIMA_DRAW_FLAG_SHUFFLING; + copy_v4_fl4(shuffle, 0.0f, 0.0f, 1.0f, 0.0f); + } + else /* RGB */ { + draw_flags |= SIMA_DRAW_FLAG_APPLY_ALPHA; + } + + GPUShader *shader = IMAGE_shader_image_get(); + DRWShadingGroup *shgrp = DRW_shgroup_create(shader, psl->image_pass); + if (tex_tile_data != NULL) { + draw_flags |= SIMA_DRAW_FLAG_TILED; + DRW_shgroup_uniform_texture_ex(shgrp, "imageTileArray", pd->texture, state); + DRW_shgroup_uniform_texture(shgrp, "imageTileData", tex_tile_data); + } + else { + DRW_shgroup_uniform_texture_ex(shgrp, "imageTexture", pd->texture, state); + } + DRW_shgroup_uniform_vec2_copy(shgrp, "farNearDistances", far_near); + DRW_shgroup_uniform_vec4_copy(shgrp, "color", color); + DRW_shgroup_uniform_vec4_copy(shgrp, "shuffle", shuffle); + DRW_shgroup_uniform_int_copy(shgrp, "drawFlags", draw_flags); + DRW_shgroup_uniform_bool_copy(shgrp, "imgPremultiplied", use_premul_alpha); + image_cache_image_add(shgrp, image); + } +} + +/* -------------------------------------------------------------------- */ +/** \name Engine Callbacks + * \{ */ +static void IMAGE_engine_init(void *ved) +{ + IMAGE_shader_library_ensure(); + IMAGE_Data *vedata = (IMAGE_Data *)ved; + IMAGE_StorageList *stl = vedata->stl; + if (!stl->pd) { + stl->pd = MEM_callocN(sizeof(IMAGE_PrivateData), __func__); + } + IMAGE_PrivateData *pd = stl->pd; + + pd->ibuf = NULL; + pd->lock = NULL; + pd->texture = NULL; +} + +static void IMAGE_cache_init(void *ved) +{ + IMAGE_Data *vedata = (IMAGE_Data *)ved; + IMAGE_StorageList *stl = vedata->stl; + IMAGE_PrivateData *pd = stl->pd; + IMAGE_PassList *psl = vedata->psl; + + const DRWContextState *draw_ctx = DRW_context_state_get(); + SpaceImage *sima = (SpaceImage *)draw_ctx->space_data; + + { + /* Write depth is needed for background overlay rendering. Near depth is used for + * transparency checker and Far depth is used for indicating the image size. */ + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS | + DRW_STATE_BLEND_ALPHA_PREMUL; + psl->image_pass = DRW_pass_create("Image", state); + } + + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + GPU_framebuffer_bind(dfbl->default_fb); + static float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + GPU_framebuffer_clear_color_depth(dfbl->default_fb, clear_col, 1.0); + + { + Image *image = ED_space_image(sima); + ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &pd->lock, 0); + image_cache_image(vedata, image, &sima->iuser, ibuf); + pd->ibuf = ibuf; + } +} + +static void IMAGE_cache_populate(void *UNUSED(vedata), Object *UNUSED(ob)) +{ + /* Function intentional left empty. `cache_populate` is required to be implemented. */ +} + +static void image_draw_finish(IMAGE_Data *ved) +{ + IMAGE_Data *vedata = (IMAGE_Data *)ved; + IMAGE_StorageList *stl = vedata->stl; + IMAGE_PrivateData *pd = stl->pd; + const DRWContextState *draw_ctx = DRW_context_state_get(); + SpaceImage *sima = (SpaceImage *)draw_ctx->space_data; + + ED_space_image_release_buffer(sima, pd->ibuf, pd->lock); + + if (pd->texture && pd->owns_texture) { + GPU_texture_free(pd->texture); + pd->owns_texture = false; + } + pd->texture = NULL; +} + +static void IMAGE_draw_scene(void *ved) +{ + IMAGE_Data *vedata = (IMAGE_Data *)ved; + IMAGE_PassList *psl = vedata->psl; + + DRW_draw_pass(psl->image_pass); + + image_draw_finish(vedata); +} + +static void IMAGE_engine_free(void) +{ + IMAGE_shader_free(); +} + +/* \} */ +static const DrawEngineDataSize IMAGE_data_size = DRW_VIEWPORT_DATA_SIZE(IMAGE_Data); + +DrawEngineType draw_engine_image_type = { + NULL, /* next */ + NULL, /* prev */ + N_("UV/Image"), /* idname */ + &IMAGE_data_size, /* vedata_size */ + &IMAGE_engine_init, /* engine_init */ + &IMAGE_engine_free, /* engine_free */ + &IMAGE_cache_init, /* cache_init */ + &IMAGE_cache_populate, /* cache_populate */ + NULL, /* cache_finish */ + &IMAGE_draw_scene, /* draw_scene */ + NULL, /* view_update */ + NULL, /* id_update */ + NULL, /* render_to_image */ +}; diff --git a/source/blender/draw/engines/image/image_engine.h b/source/blender/draw/engines/image/image_engine.h new file mode 100644 index 00000000000..0098d863ef9 --- /dev/null +++ b/source/blender/draw/engines/image/image_engine.h @@ -0,0 +1,25 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2020, Blender Foundation. + */ + +/** \file + * \ingroup draw_editors + */ + +#pragma once + +extern DrawEngineType draw_engine_image_type; diff --git a/source/blender/draw/engines/image/image_private.h b/source/blender/draw/engines/image/image_private.h new file mode 100644 index 00000000000..d11d868d4d2 --- /dev/null +++ b/source/blender/draw/engines/image/image_private.h @@ -0,0 +1,69 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2020, Blender Foundation. + */ + +/** \file + * \ingroup draw_engine + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Forward declarations */ +struct rcti; +struct GPUBatch; +struct Image; +struct ImBuf; +struct GPUTexture; + +/* *********** LISTS *********** */ + +/* GPUViewport.storage + * Is freed everytime the viewport engine changes */ +typedef struct IMAGE_PassList { + DRWPass *image_pass; +} IMAGE_PassList; + +typedef struct IMAGE_PrivateData { + void *lock; + struct ImBuf *ibuf; + + struct GPUTexture *texture; + bool owns_texture; +} IMAGE_PrivateData; + +typedef struct IMAGE_StorageList { + IMAGE_PrivateData *pd; +} IMAGE_StorageList; + +typedef struct IMAGE_Data { + void *engine_type; + DRWViewportEmptyList *fbl; + DRWViewportEmptyList *txl; + IMAGE_PassList *psl; + IMAGE_StorageList *stl; +} IMAGE_Data; + +/* image_shader.c */ +GPUShader *IMAGE_shader_image_get(void); +void IMAGE_shader_library_ensure(void); +void IMAGE_shader_free(void); + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/draw/engines/image/image_shader.c b/source/blender/draw/engines/image/image_shader.c new file mode 100644 index 00000000000..433c79e20cf --- /dev/null +++ b/source/blender/draw/engines/image/image_shader.c @@ -0,0 +1,77 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2020, Blender Foundation. + */ + +/** \file + * \ingroup draw_engine + */ + +#include "DRW_render.h" + +#include "BLI_dynstr.h" + +#include "GPU_batch.h" + +#include "image_engine.h" +#include "image_private.h" + +extern char datatoc_common_colormanagement_lib_glsl[]; +extern char datatoc_common_globals_lib_glsl[]; +extern char datatoc_common_view_lib_glsl[]; + +extern char datatoc_engine_image_frag_glsl[]; +extern char datatoc_engine_image_vert_glsl[]; + +typedef struct IMAGE_Shaders { + GPUShader *image_sh; +} IMAGE_Shaders; + +static struct { + IMAGE_Shaders shaders; + DRWShaderLibrary *lib; +} e_data = {0}; /* Engine data */ + +void IMAGE_shader_library_ensure(void) +{ + if (e_data.lib == NULL) { + e_data.lib = DRW_shader_library_create(); + /* NOTE: Theses needs to be ordered by dependencies. */ + DRW_SHADER_LIB_ADD(e_data.lib, common_colormanagement_lib); + DRW_SHADER_LIB_ADD(e_data.lib, common_globals_lib); + DRW_SHADER_LIB_ADD(e_data.lib, common_view_lib); + } +} + +GPUShader *IMAGE_shader_image_get(void) +{ + IMAGE_Shaders *sh_data = &e_data.shaders; + if (!sh_data->image_sh) { + sh_data->image_sh = DRW_shader_create_with_shaderlib( + datatoc_engine_image_vert_glsl, NULL, datatoc_engine_image_frag_glsl, e_data.lib, NULL); + } + return sh_data->image_sh; +} + +void IMAGE_shader_free(void) +{ + GPUShader **sh_data_as_array = (GPUShader **)&e_data.shaders; + for (int i = 0; i < (sizeof(IMAGE_Shaders) / sizeof(GPUShader *)); i++) { + DRW_SHADER_FREE_SAFE(sh_data_as_array[i]); + } + + DRW_SHADER_LIB_FREE_SAFE(e_data.lib); +}
\ No newline at end of file diff --git a/source/blender/draw/engines/image/shaders/engine_image_frag.glsl b/source/blender/draw/engines/image/shaders/engine_image_frag.glsl new file mode 100644 index 00000000000..5c5d9362dfc --- /dev/null +++ b/source/blender/draw/engines/image/shaders/engine_image_frag.glsl @@ -0,0 +1,91 @@ +#pragma BLENDER_REQUIRE(common_colormanagement_lib.glsl) + +/* Keep in sync with image_engine.c */ +#define SIMA_DRAW_FLAG_SHOW_ALPHA (1 << 0) +#define SIMA_DRAW_FLAG_APPLY_ALPHA (1 << 1) +#define SIMA_DRAW_FLAG_SHUFFLING (1 << 2) +#define SIMA_DRAW_FLAG_DEPTH (1 << 3) +#define SIMA_DRAW_FLAG_TILED (1 << 4) +#define SIMA_DRAW_FLAG_DO_REPEAT (1 << 5) + +uniform sampler2DArray imageTileArray; +uniform sampler1DArray imageTileData; +uniform sampler2D imageTexture; + +uniform bool imgPremultiplied; +uniform int drawFlags; +uniform vec2 farNearDistances; +uniform vec4 color; +uniform vec4 shuffle; + +#define FAR_DISTANCE farNearDistances.x +#define NEAR_DISTANCE farNearDistances.y + +in vec2 uvs; + +out vec4 fragColor; + +/* TODO(fclem) deduplicate code. */ +bool node_tex_tile_lookup(inout vec3 co, sampler2DArray ima, sampler1DArray map) +{ + vec2 tile_pos = floor(co.xy); + + if (tile_pos.x < 0 || tile_pos.y < 0 || tile_pos.x >= 10) { + return false; + } + + float tile = 10.0 * tile_pos.y + tile_pos.x; + if (tile >= textureSize(map, 0).x) { + return false; + } + + /* Fetch tile information. */ + float tile_layer = texelFetch(map, ivec2(tile, 0), 0).x; + if (tile_layer < 0.0) { + return false; + } + + vec4 tile_info = texelFetch(map, ivec2(tile, 1), 0); + + co = vec3(((co.xy - tile_pos) * tile_info.zw) + tile_info.xy, tile_layer); + return true; +} + +void main() +{ + vec4 tex_color; + /* Read texture */ + if ((drawFlags & SIMA_DRAW_FLAG_TILED) != 0) { + vec3 co = vec3(uvs, 0.0); + if (node_tex_tile_lookup(co, imageTileArray, imageTileData)) { + tex_color = texture(imageTileArray, co); + } + else { + tex_color = vec4(1.0, 0.0, 1.0, 1.0); + } + } + else { + vec2 uvs_clamped = ((drawFlags & SIMA_DRAW_FLAG_DO_REPEAT) != 0) ? + fract(uvs) : + clamp(uvs, vec2(0.0), vec2(1.0)); + tex_color = texture(imageTexture, uvs_clamped); + } + + if ((drawFlags & SIMA_DRAW_FLAG_APPLY_ALPHA) != 0) { + if (!imgPremultiplied && tex_color.a != 0.0 && tex_color.a != 1.0) { + tex_color.rgb *= tex_color.a; + } + } + if ((drawFlags & SIMA_DRAW_FLAG_DEPTH) != 0) { + tex_color = smoothstep(FAR_DISTANCE, NEAR_DISTANCE, tex_color); + } + + if ((drawFlags & SIMA_DRAW_FLAG_SHUFFLING) != 0) { + tex_color = color * dot(tex_color, shuffle); + } + if ((drawFlags & SIMA_DRAW_FLAG_SHOW_ALPHA) == 0) { + tex_color.a = 1.0; + } + + fragColor = tex_color; +} diff --git a/source/blender/draw/engines/image/shaders/engine_image_vert.glsl b/source/blender/draw/engines/image/shaders/engine_image_vert.glsl new file mode 100644 index 00000000000..3f1fb154d44 --- /dev/null +++ b/source/blender/draw/engines/image/shaders/engine_image_vert.glsl @@ -0,0 +1,31 @@ +#pragma BLENDER_REQUIRE(common_view_lib.glsl) + +#define SIMA_DRAW_FLAG_DO_REPEAT (1 << 5) + +uniform int drawFlags; + +in vec3 pos; +out vec2 uvs; + +void main() +{ + /* `pos` contains the coordinates of a quad (-1..1). but we need the coordinates of an image + * plane (0..1) */ + vec3 image_pos = pos * 0.5 + 0.5; + + if ((drawFlags & SIMA_DRAW_FLAG_DO_REPEAT) != 0) { + gl_Position = vec4(pos.xy, 0.0, 1.0); + uvs = point_view_to_object(image_pos).xy; + } + else { + vec3 world_pos = point_object_to_world(image_pos); + vec4 position = point_world_to_ndc(world_pos); + /* Move drawn pixels to the front. In the overlay engine the depth is used + * to detect if a transparency texture or the background color should be drawn. + * Vertices are between 0.0 and 0.2, Edges between 0.2 and 0.4 + * actual pixels are at 0.75, 1.0 is used for the background. */ + position.z = 0.75; + gl_Position = position; + uvs = world_pos.xy; + } +} diff --git a/source/blender/draw/engines/overlay/overlay_background.c b/source/blender/draw/engines/overlay/overlay_background.c index f52ae691a35..cb09d916a0f 100644 --- a/source/blender/draw/engines/overlay/overlay_background.c +++ b/source/blender/draw/engines/overlay/overlay_background.c @@ -31,6 +31,7 @@ #define BG_GRADIENT 1 #define BG_CHECKER 2 #define BG_RADIAL 3 +#define BG_SOLID_CHECKER 4 void OVERLAY_background_cache_init(OVERLAY_Data *vedata) { @@ -40,7 +41,7 @@ void OVERLAY_background_cache_init(OVERLAY_Data *vedata) const DRWContextState *draw_ctx = DRW_context_state_get(); const Scene *scene = draw_ctx->scene; const RegionView3D *rv3d = draw_ctx->rv3d; - const BoundBox *bb = rv3d->clipbb; + const BoundBox *bb = rv3d ? rv3d->clipbb : NULL; const View3D *v3d = draw_ctx->v3d; bool draw_clipping_bounds = (pd->clipping_state != 0); @@ -50,9 +51,11 @@ void OVERLAY_background_cache_init(OVERLAY_Data *vedata) if (DRW_state_is_opengl_render() && !DRW_state_draw_background()) { background_type = BG_SOLID; - zero_v3(color_override); color_override[3] = 1.0f; } + else if (pd->is_image_editor) { + background_type = BG_SOLID_CHECKER; + } else if (!DRW_state_draw_background()) { background_type = BG_CHECKER; } diff --git a/source/blender/draw/engines/overlay/overlay_edit_uv.c b/source/blender/draw/engines/overlay/overlay_edit_uv.c new file mode 100644 index 00000000000..109db6433e0 --- /dev/null +++ b/source/blender/draw/engines/overlay/overlay_edit_uv.c @@ -0,0 +1,394 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2019, Blender Foundation. + */ + +/** \file + * \ingroup draw_engine + */ +#include "DRW_render.h" + +#include "draw_cache_impl.h" +#include "draw_manager_text.h" + +#include "BKE_image.h" + +#include "DNA_mesh_types.h" + +#include "ED_image.h" + +#include "GPU_batch.h" + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "overlay_private.h" + +typedef struct OVERLAY_StretchingAreaTotals { + void *next, *prev; + float *total_area; + float *total_area_uv; +} OVERLAY_StretchingAreaTotals; + +static OVERLAY_UVLineStyle edit_uv_line_style_from_space_image(const SpaceImage *sima) +{ + const bool is_uv_editor = sima->mode == SI_MODE_UV; + if (is_uv_editor) { + switch (sima->dt_uv) { + case SI_UVDT_OUTLINE: + return OVERLAY_UV_LINE_STYLE_OUTLINE; + case SI_UVDT_BLACK: + return OVERLAY_UV_LINE_STYLE_BLACK; + case SI_UVDT_WHITE: + return OVERLAY_UV_LINE_STYLE_WHITE; + case SI_UVDT_DASH: + return OVERLAY_UV_LINE_STYLE_DASH; + default: + return OVERLAY_UV_LINE_STYLE_BLACK; + } + } + else { + return OVERLAY_UV_LINE_STYLE_SHADOW; + } +} + +/* -------------------------------------------------------------------- */ +/** \name Internal API + * \{ */ + +void OVERLAY_edit_uv_init(OVERLAY_Data *vedata) +{ + OVERLAY_StorageList *stl = vedata->stl; + OVERLAY_PrivateData *pd = stl->pd; + const DRWContextState *draw_ctx = DRW_context_state_get(); + SpaceImage *sima = (SpaceImage *)draw_ctx->space_data; + const Scene *scene = draw_ctx->scene; + const ToolSettings *ts = scene->toolsettings; + + Image *image = sima->image; + /* By design no image is an image type. This so editor shows UV's by default. */ + const bool is_image_type = + (image == NULL) || ELEM(image->type, IMA_TYPE_IMAGE, IMA_TYPE_MULTILAYER, IMA_TYPE_UV_TEST); + const bool is_uv_editor = sima->mode == SI_MODE_UV; + const bool has_edit_object = (draw_ctx->object_edit) != NULL; + const bool is_paint_mode = sima->mode == SI_MODE_PAINT; + const bool is_view_mode = sima->mode == SI_MODE_VIEW; + const bool is_edit_mode = draw_ctx->object_mode == OB_MODE_EDIT; + const bool do_uv_overlay = is_image_type && is_uv_editor && has_edit_object; + const bool show_modified_uvs = sima->flag & SI_DRAWSHADOW; + const bool is_tiled_image = image && (image->source == IMA_SRC_TILED); + const bool do_faces = ((sima->flag & SI_NO_DRAWFACES) == 0); + const bool do_face_dots = (ts->uv_flag & UV_SYNC_SELECTION) ? + (ts->selectmode & SCE_SELECT_FACE) != 0 : + (ts->uv_selectmode == UV_SELECT_FACE); + const bool do_uvstretching_overlay = is_image_type && is_uv_editor && is_edit_mode && + ((sima->flag & SI_DRAW_STRETCH) != 0); + pd->edit_uv.do_faces = do_faces && !do_uvstretching_overlay; + pd->edit_uv.do_face_dots = do_faces && do_face_dots; + + pd->edit_uv.do_uv_overlay = do_uv_overlay; + pd->edit_uv.do_uv_shadow_overlay = + is_image_type && + ((is_paint_mode && + ((draw_ctx->object_mode & (OB_MODE_TEXTURE_PAINT | OB_MODE_EDIT)) != 0)) || + (is_view_mode && ((draw_ctx->object_mode & (OB_MODE_TEXTURE_PAINT)) != 0)) || + (do_uv_overlay && (show_modified_uvs))); + pd->edit_uv.do_uv_stretching_overlay = do_uvstretching_overlay; + pd->edit_uv.uv_opacity = sima->uv_opacity; + pd->edit_uv.do_tiled_image_overlay = is_image_type && is_tiled_image; + + pd->edit_uv.dash_length = 4.0f * UI_DPI_FAC; + pd->edit_uv.line_style = edit_uv_line_style_from_space_image(sima); + pd->edit_uv.do_smooth_wire = ((U.gpu_flag & USER_GPU_FLAG_OVERLAY_SMOOTH_WIRE) > 0); + + pd->edit_uv.draw_type = sima->dt_uvstretch; + BLI_listbase_clear(&pd->edit_uv.totals); + pd->edit_uv.total_area_ratio = 0.0f; + pd->edit_uv.total_area_ratio_inv = 0.0f; + + ED_space_image_get_uv_aspect(sima, &pd->edit_uv.aspect[0], &pd->edit_uv.aspect[1]); +} + +void OVERLAY_edit_uv_cache_init(OVERLAY_Data *vedata) +{ + OVERLAY_StorageList *stl = vedata->stl; + OVERLAY_PassList *psl = vedata->psl; + OVERLAY_PrivateData *pd = stl->pd; + + if (pd->edit_uv.do_uv_overlay || pd->edit_uv.do_uv_shadow_overlay) { + /* uv edges */ + { + DRW_PASS_CREATE(psl->edit_uv_edges_ps, + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | + DRW_STATE_BLEND_ALPHA); + GPUShader *sh = OVERLAY_shader_edit_uv_edges_get(); + if (pd->edit_uv.do_uv_shadow_overlay) { + pd->edit_uv_shadow_edges_grp = DRW_shgroup_create(sh, psl->edit_uv_edges_ps); + DRW_shgroup_uniform_block(pd->edit_uv_shadow_edges_grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_int_copy( + pd->edit_uv_shadow_edges_grp, "lineStyle", OVERLAY_UV_LINE_STYLE_SHADOW); + DRW_shgroup_uniform_float_copy( + pd->edit_uv_shadow_edges_grp, "alpha", pd->edit_uv.uv_opacity); + DRW_shgroup_uniform_float( + pd->edit_uv_shadow_edges_grp, "dashLength", &pd->edit_uv.dash_length, 1); + DRW_shgroup_uniform_bool( + pd->edit_uv_shadow_edges_grp, "doSmoothWire", &pd->edit_uv.do_smooth_wire, 1); + } + + if (pd->edit_uv.do_uv_overlay) { + pd->edit_uv_edges_grp = DRW_shgroup_create(sh, psl->edit_uv_edges_ps); + DRW_shgroup_uniform_block(pd->edit_uv_edges_grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_int_copy(pd->edit_uv_edges_grp, "lineStyle", pd->edit_uv.line_style); + DRW_shgroup_uniform_float_copy(pd->edit_uv_edges_grp, "alpha", pd->edit_uv.uv_opacity); + DRW_shgroup_uniform_float( + pd->edit_uv_edges_grp, "dashLength", &pd->edit_uv.dash_length, 1); + DRW_shgroup_uniform_bool( + pd->edit_uv_edges_grp, "doSmoothWire", &pd->edit_uv.do_smooth_wire, 1); + } + } + } + + if (pd->edit_uv.do_uv_overlay) { + /* uv verts */ + { + DRW_PASS_CREATE(psl->edit_uv_verts_ps, + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | + DRW_STATE_BLEND_ALPHA); + GPUShader *sh = OVERLAY_shader_edit_uv_verts_get(); + pd->edit_uv_verts_grp = DRW_shgroup_create(sh, psl->edit_uv_verts_ps); + + const float point_size = UI_GetThemeValuef(TH_FACEDOT_SIZE); + + DRW_shgroup_uniform_block(pd->edit_uv_verts_grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_float_copy( + pd->edit_uv_verts_grp, "pointSize", (point_size + 1.5f) * M_SQRT2); + DRW_shgroup_uniform_float_copy(pd->edit_uv_verts_grp, "outlineWidth", 0.75f); + } + + /* uv faces */ + if (pd->edit_uv.do_faces) { + DRW_PASS_CREATE(psl->edit_uv_faces_ps, + DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_ALWAYS | DRW_STATE_BLEND_ALPHA); + GPUShader *sh = OVERLAY_shader_edit_uv_face_get(); + pd->edit_uv_faces_grp = DRW_shgroup_create(sh, psl->edit_uv_faces_ps); + DRW_shgroup_uniform_block(pd->edit_uv_faces_grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_float(pd->edit_uv_faces_grp, "uvOpacity", &pd->edit_uv.uv_opacity, 1); + } + + /* uv face dots */ + if (pd->edit_uv.do_face_dots) { + const float point_size = UI_GetThemeValuef(TH_FACEDOT_SIZE); + GPUShader *sh = OVERLAY_shader_edit_uv_face_dots_get(); + pd->edit_uv_face_dots_grp = DRW_shgroup_create(sh, psl->edit_uv_verts_ps); + DRW_shgroup_uniform_block(pd->edit_uv_face_dots_grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_float_copy(pd->edit_uv_face_dots_grp, "pointSize", point_size); + } + } + + /* uv stretching */ + if (pd->edit_uv.do_uv_stretching_overlay) { + DRW_PASS_CREATE(psl->edit_uv_stretching_ps, + DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_ALWAYS | DRW_STATE_BLEND_ALPHA); + if (pd->edit_uv.draw_type == SI_UVDT_STRETCH_ANGLE) { + GPUShader *sh = OVERLAY_shader_edit_uv_stretching_angle_get(); + pd->edit_uv_stretching_grp = DRW_shgroup_create(sh, psl->edit_uv_stretching_ps); + DRW_shgroup_uniform_block(pd->edit_uv_stretching_grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_vec2_copy(pd->edit_uv_stretching_grp, "aspect", pd->edit_uv.aspect); + } + else /* SI_UVDT_STRETCH_AREA */ { + GPUShader *sh = OVERLAY_shader_edit_uv_stretching_area_get(); + pd->edit_uv_stretching_grp = DRW_shgroup_create(sh, psl->edit_uv_stretching_ps); + DRW_shgroup_uniform_block(pd->edit_uv_stretching_grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_float( + pd->edit_uv_stretching_grp, "totalAreaRatio", &pd->edit_uv.total_area_ratio, 1); + DRW_shgroup_uniform_float( + pd->edit_uv_stretching_grp, "totalAreaRatioInv", &pd->edit_uv.total_area_ratio_inv, 1); + } + } + + if (pd->edit_uv.do_tiled_image_overlay) { + const DRWContextState *draw_ctx = DRW_context_state_get(); + SpaceImage *sima = (SpaceImage *)draw_ctx->space_data; + Image *image = sima->image; + GPUBatch *geom = DRW_cache_quad_wires_get(); + float obmat[4][4]; + unit_m4(obmat); + + DRW_PASS_CREATE(psl->edit_uv_tiled_image_borders_ps, + DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_ALWAYS); + GPUShader *sh = OVERLAY_shader_edit_uv_tiled_image_borders_get(); + + float theme_color[4], selected_color[4]; + UI_GetThemeColorShade4fv(TH_BACK, 60, theme_color); + UI_GetThemeColor4fv(TH_FACE_SELECT, selected_color); + srgb_to_linearrgb_v4(theme_color, theme_color); + srgb_to_linearrgb_v4(selected_color, selected_color); + + DRWShadingGroup *grp = DRW_shgroup_create(sh, psl->edit_uv_tiled_image_borders_ps); + DRW_shgroup_uniform_vec4_copy(grp, "color", theme_color); + DRW_shgroup_uniform_vec3_copy(grp, "offset", (float[3]){0.0f, 0.0f, 0.0f}); + + LISTBASE_FOREACH (ImageTile *, tile, &image->tiles) { + const int tile_x = ((tile->tile_number - 1001) % 10); + const int tile_y = ((tile->tile_number - 1001) / 10); + obmat[3][1] = (float)tile_y; + obmat[3][0] = (float)tile_x; + DRW_shgroup_call_obmat(grp, geom, obmat); + } + + /* Active tile border */ + ImageTile *active_tile = BLI_findlink(&image->tiles, image->active_tile_index); + obmat[3][0] = (float)((active_tile->tile_number - 1001) % 10); + obmat[3][1] = (float)((active_tile->tile_number - 1001) / 10); + grp = DRW_shgroup_create(sh, psl->edit_uv_tiled_image_borders_ps); + DRW_shgroup_uniform_vec4_copy(grp, "color", selected_color); + DRW_shgroup_call_obmat(grp, geom, obmat); + + struct DRWTextStore *dt = DRW_text_cache_ensure(); + uchar color[4]; + /* Color Management: Exception here as texts are drawn in sRGB space directly. */ + UI_GetThemeColorShade4ubv(TH_BACK, 60, color); + char text[16]; + LISTBASE_FOREACH (ImageTile *, tile, &image->tiles) { + BLI_snprintf(text, 5, "%d", tile->tile_number); + float tile_location[3] = { + ((tile->tile_number - 1001) % 10), ((tile->tile_number - 1001) / 10), 0.0f}; + DRW_text_cache_add(dt, + tile_location, + text, + strlen(text), + 10, + 10, + DRW_TEXT_CACHE_GLOBALSPACE | DRW_TEXT_CACHE_ASCII, + color); + } + } +} + +void OVERLAY_edit_uv_cache_populate(OVERLAY_Data *vedata, Object *ob) +{ + OVERLAY_StorageList *stl = vedata->stl; + OVERLAY_PrivateData *pd = stl->pd; + GPUBatch *geom; + const bool is_edit_object = DRW_object_is_in_edit_mode(ob); + + const DRWContextState *draw_ctx = DRW_context_state_get(); + const bool draw_shadows = (draw_ctx->object_mode != OB_MODE_OBJECT) && + (ob->mode == draw_ctx->object_mode); + if (is_edit_object) { + if (pd->edit_uv.do_uv_overlay) { + geom = DRW_mesh_batch_cache_get_edituv_edges(ob->data); + if (geom) { + DRW_shgroup_call_obmat(pd->edit_uv_edges_grp, geom, NULL); + } + geom = DRW_mesh_batch_cache_get_edituv_verts(ob->data); + if (geom) { + DRW_shgroup_call_obmat(pd->edit_uv_verts_grp, geom, NULL); + } + if (pd->edit_uv.do_faces) { + geom = DRW_mesh_batch_cache_get_edituv_faces(ob->data); + if (geom) { + DRW_shgroup_call_obmat(pd->edit_uv_faces_grp, geom, NULL); + } + } + if (pd->edit_uv.do_face_dots) { + geom = DRW_mesh_batch_cache_get_edituv_facedots(ob->data); + if (geom) { + DRW_shgroup_call_obmat(pd->edit_uv_face_dots_grp, geom, NULL); + } + } + } + + if (pd->edit_uv.do_uv_stretching_overlay) { + Mesh *me = ob->data; + + if (pd->edit_uv.draw_type == SI_UVDT_STRETCH_ANGLE) { + geom = DRW_mesh_batch_cache_get_edituv_faces_stretch_angle(me); + } + else /* SI_UVDT_STRETCH_AREA */ { + OVERLAY_StretchingAreaTotals *totals = MEM_mallocN(sizeof(OVERLAY_StretchingAreaTotals), + __func__); + BLI_addtail(&pd->edit_uv.totals, totals); + geom = DRW_mesh_batch_cache_get_edituv_faces_stretch_area( + me, &totals->total_area, &totals->total_area_uv); + } + + if (geom) { + DRW_shgroup_call_obmat(pd->edit_uv_stretching_grp, geom, NULL); + } + } + } + + if (draw_shadows) { + if (pd->edit_uv.do_uv_shadow_overlay) { + geom = DRW_mesh_batch_cache_get_uv_edges(ob->data); + if (geom) { + DRW_shgroup_call_obmat(pd->edit_uv_shadow_edges_grp, geom, NULL); + } + } + } +} + +static void edit_uv_stretching_update_ratios(OVERLAY_Data *vedata) +{ + OVERLAY_StorageList *stl = vedata->stl; + OVERLAY_PrivateData *pd = stl->pd; + + if (pd->edit_uv.draw_type == SI_UVDT_STRETCH_AREA) { + float total_area = 0.0f; + float total_area_uv = 0.0f; + + LISTBASE_FOREACH (OVERLAY_StretchingAreaTotals *, totals, &pd->edit_uv.totals) { + total_area += *totals->total_area; + total_area_uv += *totals->total_area_uv; + } + + if (total_area > FLT_EPSILON && total_area_uv > FLT_EPSILON) { + pd->edit_uv.total_area_ratio = total_area / total_area_uv; + pd->edit_uv.total_area_ratio_inv = total_area_uv / total_area; + } + } + BLI_freelistN(&pd->edit_uv.totals); +} + +void OVERLAY_edit_uv_draw(OVERLAY_Data *vedata) +{ + OVERLAY_PassList *psl = vedata->psl; + OVERLAY_StorageList *stl = vedata->stl; + OVERLAY_PrivateData *pd = stl->pd; + + if (pd->edit_uv.do_tiled_image_overlay) { + DRW_draw_pass(psl->edit_uv_tiled_image_borders_ps); + } + + if (pd->edit_uv.do_uv_stretching_overlay) { + edit_uv_stretching_update_ratios(vedata); + DRW_draw_pass(psl->edit_uv_stretching_ps); + } + if (pd->edit_uv.do_uv_overlay) { + if (pd->edit_uv.do_faces) { + DRW_draw_pass(psl->edit_uv_faces_ps); + } + DRW_draw_pass(psl->edit_uv_edges_ps); + + DRW_draw_pass(psl->edit_uv_verts_ps); + } + else if (pd->edit_uv.do_uv_shadow_overlay) { + DRW_draw_pass(psl->edit_uv_edges_ps); + } +} + +/* \{ */ diff --git a/source/blender/draw/engines/overlay/overlay_engine.c b/source/blender/draw/engines/overlay/overlay_engine.c index 1312408498a..9cdd371ec4e 100644 --- a/source/blender/draw/engines/overlay/overlay_engine.c +++ b/source/blender/draw/engines/overlay/overlay_engine.c @@ -29,9 +29,13 @@ #include "ED_view3d.h" +#include "UI_interface.h" + #include "BKE_object.h" #include "BKE_paint.h" +#include "DNA_space_types.h" + #include "overlay_engine.h" #include "overlay_private.h" @@ -48,6 +52,10 @@ static void OVERLAY_engine_init(void *vedata) const View3D *v3d = draw_ctx->v3d; const Scene *scene = draw_ctx->scene; const ToolSettings *ts = scene->toolsettings; + const SpaceImage *sima = (SpaceImage *)draw_ctx->space_data; + BLI_assert(v3d || sima); + + OVERLAY_shader_library_ensure(); if (!stl->pd) { /* Alloc transient pointers */ @@ -55,6 +63,14 @@ static void OVERLAY_engine_init(void *vedata) } OVERLAY_PrivateData *pd = stl->pd; + pd->is_image_editor = sima != NULL; + + if (pd->is_image_editor) { + pd->clipping_state = 0; + OVERLAY_grid_init(data); + OVERLAY_edit_uv_init(data); + return; + } pd->hide_overlays = (v3d->flag2 & V3D_HIDE_OVERLAYS) != 0; pd->ctx_mode = CTX_data_mode_enum_ex( @@ -122,6 +138,13 @@ static void OVERLAY_cache_init(void *vedata) OVERLAY_StorageList *stl = data->stl; OVERLAY_PrivateData *pd = stl->pd; + if (pd->is_image_editor) { + OVERLAY_background_cache_init(vedata); + OVERLAY_grid_cache_init(vedata); + OVERLAY_edit_uv_cache_init(vedata); + return; + } + switch (pd->ctx_mode) { case CTX_MODE_EDIT_MESH: OVERLAY_edit_mesh_cache_init(vedata); @@ -240,6 +263,14 @@ static void OVERLAY_cache_populate(void *vedata, Object *ob) { OVERLAY_Data *data = vedata; OVERLAY_PrivateData *pd = data->stl->pd; + + if (pd->is_image_editor) { + if (ob->type == OB_MESH) { + OVERLAY_edit_uv_cache_populate(vedata, ob); + } + return; + } + const DRWContextState *draw_ctx = DRW_context_state_get(); const bool is_select = DRW_state_is_select(); const bool renderable = DRW_object_is_renderable(ob); @@ -414,6 +445,12 @@ static void OVERLAY_cache_populate(void *vedata, Object *ob) static void OVERLAY_cache_finish(void *vedata) { + OVERLAY_Data *data = vedata; + OVERLAY_PrivateData *pd = data->stl->pd; + if (pd->is_image_editor) { + return; + } + /* TODO(fclem) Only do this when really needed. */ { /* HACK we allocate the in front depth here to avoid the overhead when if is not needed. */ @@ -445,6 +482,16 @@ static void OVERLAY_draw_scene(void *vedata) GPU_framebuffer_clear_color(dfbl->overlay_only_fb, clear_col); } + if (pd->is_image_editor) { + OVERLAY_background_draw(data); + OVERLAY_grid_draw(data); + if (DRW_state_is_fbo()) { + GPU_framebuffer_bind(dfbl->overlay_fb); + } + OVERLAY_edit_uv_draw(data); + return; + } + OVERLAY_image_background_draw(vedata); OVERLAY_background_draw(vedata); diff --git a/source/blender/draw/engines/overlay/overlay_grid.c b/source/blender/draw/engines/overlay/overlay_grid.c index e3079870d8f..7445dfc2e3d 100644 --- a/source/blender/draw/engines/overlay/overlay_grid.c +++ b/source/blender/draw/engines/overlay/overlay_grid.c @@ -26,6 +26,7 @@ #include "DEG_depsgraph_query.h" +#include "ED_image.h" #include "ED_view3d.h" #include "overlay_private.h" @@ -42,14 +43,31 @@ enum { CLIP_ZNEG = (1 << 8), GRID_BACK = (1 << 9), GRID_CAMERA = (1 << 10), + PLANE_IMAGE = (1 << 11), }; void OVERLAY_grid_init(OVERLAY_Data *vedata) { OVERLAY_PrivateData *pd = vedata->stl->pd; OVERLAY_ShadingData *shd = &pd->shdata; - const DRWContextState *draw_ctx = DRW_context_state_get(); + + shd->grid_flag = 0; + shd->zneg_flag = 0; + shd->zpos_flag = 0; + shd->grid_line_size = max_ff(0.0f, U.pixelsize - 1.0f) * 0.5f; + + if (pd->is_image_editor) { + SpaceImage *sima = (SpaceImage *)draw_ctx->space_data; + shd->grid_flag = ED_space_image_has_buffer(sima) ? 0 : PLANE_IMAGE | SHOW_GRID; + shd->grid_distance = 1.0f; + shd->grid_mesh_size = 1.0f; + for (int step = 0; step < 8; step++) { + shd->grid_steps[step] = powf(4, step) * (1.0f / 16.0f); + } + return; + } + View3D *v3d = draw_ctx->v3d; Scene *scene = draw_ctx->scene; RegionView3D *rv3d = draw_ctx->rv3d; @@ -60,10 +78,6 @@ void OVERLAY_grid_init(OVERLAY_Data *vedata) const bool show_floor = (pd->v3d_gridflag & V3D_SHOW_FLOOR) != 0; const bool show_ortho_grid = (pd->v3d_gridflag & V3D_SHOW_ORTHO_GRID) != 0; - shd->grid_flag = 0; - shd->zneg_flag = 0; - shd->zpos_flag = 0; - if (pd->hide_overlays || !(pd->v3d_gridflag & (V3D_SHOW_X | V3D_SHOW_Y | V3D_SHOW_Z | V3D_SHOW_FLOOR | V3D_SHOW_ORTHO_GRID))) { return; @@ -163,14 +177,16 @@ void OVERLAY_grid_init(OVERLAY_Data *vedata) } shd->grid_distance = dist / 2.0f; - shd->grid_line_size = max_ff(0.0f, U.pixelsize - 1.0f) * 0.5f; ED_view3d_grid_steps(scene, v3d, rv3d, shd->grid_steps); } void OVERLAY_grid_cache_init(OVERLAY_Data *vedata) { - OVERLAY_ShadingData *shd = &vedata->stl->pd->shdata; + OVERLAY_StorageList *stl = vedata->stl; + OVERLAY_PrivateData *pd = stl->pd; + OVERLAY_ShadingData *shd = &pd->shdata; + OVERLAY_PassList *psl = vedata->psl; DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); @@ -182,12 +198,29 @@ void OVERLAY_grid_cache_init(OVERLAY_Data *vedata) DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA; DRW_PASS_CREATE(psl->grid_ps, state); - - GPUShader *sh = OVERLAY_shader_grid(); + DRWShadingGroup *grp; + GPUShader *sh; struct GPUBatch *geom = DRW_cache_grid_get(); + if (pd->is_image_editor) { + /* add quad background */ + sh = OVERLAY_shader_grid_image(); + grp = DRW_shgroup_create(sh, psl->grid_ps); + DRW_shgroup_call(grp, DRW_cache_quad_get(), NULL); + float color_back[4]; + interp_v4_v4v4(color_back, G_draw.block.colorBackground, G_draw.block.colorGrid, 0.5); + DRW_shgroup_uniform_vec4_copy(grp, "color", color_back); + + /* add wire border */ + grp = DRW_shgroup_create(sh, psl->grid_ps); + DRW_shgroup_call(grp, DRW_cache_quad_wires_get(), NULL); + DRW_shgroup_uniform_vec4_copy(grp, "color", G_draw.block.colorGrid); + } + + sh = OVERLAY_shader_grid(); + /* Create 3 quads to render ordered transparency Z axis */ - DRWShadingGroup *grp = DRW_shgroup_create(sh, psl->grid_ps); + grp = DRW_shgroup_create(sh, psl->grid_ps); DRW_shgroup_uniform_int(grp, "gridFlag", &shd->zneg_flag, 1); DRW_shgroup_uniform_vec3(grp, "planeAxes", shd->zplane_axes, 1); DRW_shgroup_uniform_float(grp, "gridDistance", &shd->grid_distance, 1); diff --git a/source/blender/draw/engines/overlay/overlay_private.h b/source/blender/draw/engines/overlay/overlay_private.h index c9d29af91e6..c8b29c6bbbb 100644 --- a/source/blender/draw/engines/overlay/overlay_private.h +++ b/source/blender/draw/engines/overlay/overlay_private.h @@ -34,6 +34,9 @@ extern "C" { # define USE_GEOM_SHADER_WORKAROUND 0 #endif +/* Needed for eSpaceImage_UVDT_Stretch */ +#include "DNA_space_types.h" + typedef struct OVERLAY_FramebufferList { struct GPUFrameBuffer *overlay_default_fb; struct GPUFrameBuffer *overlay_line_fb; @@ -55,6 +58,14 @@ typedef struct OVERLAY_TextureList { #define NOT_IN_FRONT 0 #define IN_FRONT 1 +typedef enum OVERLAY_UVLineStyle { + OVERLAY_UV_LINE_STYLE_OUTLINE = 0, + OVERLAY_UV_LINE_STYLE_DASH = 1, + OVERLAY_UV_LINE_STYLE_BLACK = 2, + OVERLAY_UV_LINE_STYLE_WHITE = 3, + OVERLAY_UV_LINE_STYLE_SHADOW = 4, +} OVERLAY_UVLineStyle; + typedef struct OVERLAY_PassList { DRWPass *antialiasing_ps; DRWPass *armature_ps[2]; @@ -78,6 +89,11 @@ typedef struct OVERLAY_PassList { DRWPass *edit_text_overlay_ps; DRWPass *edit_text_darken_ps; DRWPass *edit_text_wire_ps[2]; + DRWPass *edit_uv_edges_ps; + DRWPass *edit_uv_verts_ps; + DRWPass *edit_uv_faces_ps; + DRWPass *edit_uv_stretching_ps; + DRWPass *edit_uv_tiled_image_borders_ps; DRWPass *extra_ps[2]; DRWPass *extra_blend_ps; DRWPass *extra_centers_ps; @@ -244,6 +260,12 @@ typedef struct OVERLAY_PrivateData { DRWShadingGroup *edit_particle_point_grp; DRWShadingGroup *edit_text_overlay_grp; DRWShadingGroup *edit_text_wire_grp[2]; + DRWShadingGroup *edit_uv_verts_grp; + DRWShadingGroup *edit_uv_edges_grp; + DRWShadingGroup *edit_uv_shadow_edges_grp; + DRWShadingGroup *edit_uv_faces_grp; + DRWShadingGroup *edit_uv_face_dots_grp; + DRWShadingGroup *edit_uv_stretching_grp; DRWShadingGroup *extra_grid_grp; DRWShadingGroup *facing_grp[2]; DRWShadingGroup *motion_path_lines_grp; @@ -286,6 +308,7 @@ typedef struct OVERLAY_PrivateData { View3DOverlay overlay; enum eContextObjectMode ctx_mode; + bool is_image_editor; bool clear_in_front; bool use_in_front; bool wireframe_mode; @@ -325,6 +348,29 @@ typedef struct OVERLAY_PrivateData { int select_mode; } edit_particle; struct { + bool do_uv_overlay; + bool do_uv_shadow_overlay; + bool do_uv_stretching_overlay; + bool do_tiled_image_overlay; + + bool do_faces; + bool do_face_dots; + + float uv_opacity; + /* edge drawing */ + OVERLAY_UVLineStyle line_style; + float dash_length; + int do_smooth_wire; + + /* stretching overlay */ + float aspect[2]; + eSpaceImage_UVDT_Stretch draw_type; + ListBase totals; + float total_area_ratio; + float total_area_ratio_inv; + + } edit_uv; + struct { bool transparent; bool show_relations; bool do_pose_xray; @@ -472,6 +518,11 @@ void OVERLAY_edit_particle_cache_init(OVERLAY_Data *vedata); void OVERLAY_edit_particle_cache_populate(OVERLAY_Data *vedata, Object *ob); void OVERLAY_edit_particle_draw(OVERLAY_Data *vedata); +void OVERLAY_edit_uv_init(OVERLAY_Data *vedata); +void OVERLAY_edit_uv_cache_init(OVERLAY_Data *vedata); +void OVERLAY_edit_uv_cache_populate(OVERLAY_Data *vedata, Object *ob); +void OVERLAY_edit_uv_draw(OVERLAY_Data *vedata); + void OVERLAY_extra_cache_init(OVERLAY_Data *vedata); void OVERLAY_extra_cache_populate(OVERLAY_Data *vedata, Object *ob); void OVERLAY_extra_blend_draw(OVERLAY_Data *vedata); @@ -570,6 +621,7 @@ void OVERLAY_wireframe_cache_populate(OVERLAY_Data *vedata, void OVERLAY_wireframe_draw(OVERLAY_Data *vedata); void OVERLAY_wireframe_in_front_draw(OVERLAY_Data *vedata); +void OVERLAY_shader_library_ensure(void); GPUShader *OVERLAY_shader_antialiasing(void); GPUShader *OVERLAY_shader_armature_degrees_of_freedom_wire(void); GPUShader *OVERLAY_shader_armature_degrees_of_freedom_solid(void); @@ -599,6 +651,13 @@ GPUShader *OVERLAY_shader_edit_mesh_skin_root(void); GPUShader *OVERLAY_shader_edit_mesh_vert(void); GPUShader *OVERLAY_shader_edit_particle_strand(void); GPUShader *OVERLAY_shader_edit_particle_point(void); +GPUShader *OVERLAY_shader_edit_uv_edges_get(void); +GPUShader *OVERLAY_shader_edit_uv_face_get(void); +GPUShader *OVERLAY_shader_edit_uv_face_dots_get(void); +GPUShader *OVERLAY_shader_edit_uv_verts_get(void); +GPUShader *OVERLAY_shader_edit_uv_stretching_area_get(void); +GPUShader *OVERLAY_shader_edit_uv_stretching_angle_get(void); +GPUShader *OVERLAY_shader_edit_uv_tiled_image_borders_get(void); GPUShader *OVERLAY_shader_extra(bool is_select); GPUShader *OVERLAY_shader_extra_groundline(void); GPUShader *OVERLAY_shader_extra_wire(bool use_object, bool is_select); @@ -607,6 +666,7 @@ GPUShader *OVERLAY_shader_extra_point(void); GPUShader *OVERLAY_shader_facing(void); GPUShader *OVERLAY_shader_gpencil_canvas(void); GPUShader *OVERLAY_shader_grid(void); +GPUShader *OVERLAY_shader_grid_image(void); GPUShader *OVERLAY_shader_image(void); GPUShader *OVERLAY_shader_motion_path_line(void); GPUShader *OVERLAY_shader_motion_path_vert(void); diff --git a/source/blender/draw/engines/overlay/overlay_shader.c b/source/blender/draw/engines/overlay/overlay_shader.c index e3cb052890b..4530d6e8adf 100644 --- a/source/blender/draw/engines/overlay/overlay_shader.c +++ b/source/blender/draw/engines/overlay/overlay_shader.c @@ -70,6 +70,15 @@ extern char datatoc_edit_mesh_analysis_vert_glsl[]; extern char datatoc_edit_mesh_analysis_frag_glsl[]; extern char datatoc_edit_particle_strand_vert_glsl[]; extern char datatoc_edit_particle_point_vert_glsl[]; +extern char datatoc_edit_uv_verts_vert_glsl[]; +extern char datatoc_edit_uv_verts_frag_glsl[]; +extern char datatoc_edit_uv_edges_vert_glsl[]; +extern char datatoc_edit_uv_edges_geom_glsl[]; +extern char datatoc_edit_uv_edges_frag_glsl[]; +extern char datatoc_edit_uv_faces_vert_glsl[]; +extern char datatoc_edit_uv_face_dots_vert_glsl[]; +extern char datatoc_edit_uv_stretching_vert_glsl[]; +extern char datatoc_edit_uv_tiled_image_borders_vert_glsl[]; extern char datatoc_extra_frag_glsl[]; extern char datatoc_extra_vert_glsl[]; extern char datatoc_extra_groundline_vert_glsl[]; @@ -113,6 +122,7 @@ extern char datatoc_xray_fade_frag_glsl[]; extern char datatoc_gpu_shader_depth_only_frag_glsl[]; extern char datatoc_gpu_shader_point_varying_color_frag_glsl[]; extern char datatoc_gpu_shader_3D_smooth_color_frag_glsl[]; +extern char datatoc_gpu_shader_2D_smooth_color_frag_glsl[]; extern char datatoc_gpu_shader_uniform_color_frag_glsl[]; extern char datatoc_gpu_shader_flat_color_frag_glsl[]; extern char datatoc_gpu_shader_point_varying_color_varying_outline_aa_frag_glsl[]; @@ -120,6 +130,7 @@ extern char datatoc_gpu_shader_common_obinfos_lib_glsl[]; extern char datatoc_gpencil_common_lib_glsl[]; +extern char datatoc_common_overlay_lib_glsl[]; extern char datatoc_common_colormanagement_lib_glsl[]; extern char datatoc_common_fullscreen_vert_glsl[]; extern char datatoc_common_fxaa_lib_glsl[]; @@ -164,6 +175,13 @@ typedef struct OVERLAY_Shaders { GPUShader *edit_mesh_analysis; GPUShader *edit_particle_strand; GPUShader *edit_particle_point; + GPUShader *edit_uv_verts; + GPUShader *edit_uv_faces; + GPUShader *edit_uv_edges; + GPUShader *edit_uv_face_dots; + GPUShader *edit_uv_stretching_angle; + GPUShader *edit_uv_stretching_area; + GPUShader *edit_uv_tiled_image_borders; GPUShader *extra; GPUShader *extra_select; GPUShader *extra_groundline; @@ -175,6 +193,7 @@ typedef struct OVERLAY_Shaders { GPUShader *facing; GPUShader *gpencil_canvas; GPUShader *grid; + GPUShader *grid_image; GPUShader *image; GPUShader *motion_path_line; GPUShader *motion_path_vert; @@ -203,8 +222,20 @@ typedef struct OVERLAY_Shaders { static struct { OVERLAY_Shaders sh_data[GPU_SHADER_CFG_LEN]; + DRWShaderLibrary *lib; } e_data = {{{NULL}}}; +void OVERLAY_shader_library_ensure(void) +{ + if (e_data.lib == NULL) { + e_data.lib = DRW_shader_library_create(); + /* NOTE: Theses needs to be ordered by dependencies. */ + DRW_SHADER_LIB_ADD(e_data.lib, common_globals_lib); + DRW_SHADER_LIB_ADD(e_data.lib, common_overlay_lib); + DRW_SHADER_LIB_ADD(e_data.lib, common_view_lib); + } +} + GPUShader *OVERLAY_shader_antialiasing(void) { OVERLAY_Shaders *sh_data = &e_data.sh_data[0]; @@ -1012,6 +1043,20 @@ GPUShader *OVERLAY_shader_grid(void) return sh_data->grid; } +GPUShader *OVERLAY_shader_grid_image(void) +{ + OVERLAY_Shaders *sh_data = &e_data.sh_data[0]; + if (!sh_data->grid_image) { + sh_data->grid_image = DRW_shader_create_with_shaderlib( + datatoc_edit_uv_tiled_image_borders_vert_glsl, + NULL, + datatoc_gpu_shader_uniform_color_frag_glsl, + e_data.lib, + "#define blender_srgb_to_framebuffer_space(a) a\n"); + } + return sh_data->grid_image; +} + GPUShader *OVERLAY_shader_image(void) { const DRWContextState *draw_ctx = DRW_context_state_get(); @@ -1449,6 +1494,108 @@ GPUShader *OVERLAY_shader_xray_fade(void) return sh_data->xray_fade; } +/* -------------------------------------------------------------------- */ +/** \name Edit UV shaders + * \{ */ + +GPUShader *OVERLAY_shader_edit_uv_edges_get(void) +{ + OVERLAY_Shaders *sh_data = &e_data.sh_data[0]; + if (!sh_data->edit_uv_edges) { + sh_data->edit_uv_edges = DRW_shader_create_with_shaderlib(datatoc_edit_uv_edges_vert_glsl, + datatoc_edit_uv_edges_geom_glsl, + datatoc_edit_uv_edges_frag_glsl, + e_data.lib, + NULL); + } + return sh_data->edit_uv_edges; +} + +GPUShader *OVERLAY_shader_edit_uv_face_get(void) +{ + OVERLAY_Shaders *sh_data = &e_data.sh_data[0]; + if (!sh_data->edit_uv_faces) { + sh_data->edit_uv_faces = DRW_shader_create_with_shaderlib( + datatoc_edit_uv_faces_vert_glsl, + NULL, + datatoc_gpu_shader_flat_color_frag_glsl, + e_data.lib, + "#define blender_srgb_to_framebuffer_space(a) a\n"); + } + return sh_data->edit_uv_faces; +} + +GPUShader *OVERLAY_shader_edit_uv_face_dots_get(void) +{ + OVERLAY_Shaders *sh_data = &e_data.sh_data[0]; + if (!sh_data->edit_uv_face_dots) { + sh_data->edit_uv_face_dots = DRW_shader_create_with_shaderlib( + datatoc_edit_uv_face_dots_vert_glsl, + NULL, + datatoc_gpu_shader_flat_color_frag_glsl, + e_data.lib, + "#define blender_srgb_to_framebuffer_space(a) a\n"); + } + return sh_data->edit_uv_face_dots; +} + +GPUShader *OVERLAY_shader_edit_uv_verts_get(void) +{ + OVERLAY_Shaders *sh_data = &e_data.sh_data[0]; + if (!sh_data->edit_uv_verts) { + sh_data->edit_uv_verts = DRW_shader_create_with_shaderlib( + datatoc_edit_uv_verts_vert_glsl, NULL, datatoc_edit_uv_verts_frag_glsl, e_data.lib, NULL); + } + + return sh_data->edit_uv_verts; +} + +GPUShader *OVERLAY_shader_edit_uv_stretching_area_get(void) +{ + OVERLAY_Shaders *sh_data = &e_data.sh_data[0]; + if (!sh_data->edit_uv_stretching_area) { + sh_data->edit_uv_stretching_area = DRW_shader_create_with_shaderlib( + datatoc_edit_uv_stretching_vert_glsl, + NULL, + datatoc_gpu_shader_2D_smooth_color_frag_glsl, + e_data.lib, + "#define blender_srgb_to_framebuffer_space(a) a\n"); + } + + return sh_data->edit_uv_stretching_area; +} + +GPUShader *OVERLAY_shader_edit_uv_stretching_angle_get(void) +{ + OVERLAY_Shaders *sh_data = &e_data.sh_data[0]; + if (!sh_data->edit_uv_stretching_angle) { + sh_data->edit_uv_stretching_angle = DRW_shader_create_with_shaderlib( + datatoc_edit_uv_stretching_vert_glsl, + NULL, + datatoc_gpu_shader_2D_smooth_color_frag_glsl, + e_data.lib, + "#define blender_srgb_to_framebuffer_space(a) a\n#define STRETCH_ANGLE\n"); + } + + return sh_data->edit_uv_stretching_angle; +} + +GPUShader *OVERLAY_shader_edit_uv_tiled_image_borders_get(void) +{ + OVERLAY_Shaders *sh_data = &e_data.sh_data[0]; + if (!sh_data->edit_uv_tiled_image_borders) { + sh_data->edit_uv_tiled_image_borders = DRW_shader_create_with_shaderlib( + datatoc_edit_uv_tiled_image_borders_vert_glsl, + NULL, + datatoc_gpu_shader_uniform_color_frag_glsl, + e_data.lib, + "#define blender_srgb_to_framebuffer_space(a) a\n"); + } + return sh_data->edit_uv_tiled_image_borders; +} + +/* \} */ + static OVERLAY_InstanceFormats g_formats = {NULL}; OVERLAY_InstanceFormats *OVERLAY_shader_instance_formats_get(void) @@ -1521,6 +1668,8 @@ OVERLAY_InstanceFormats *OVERLAY_shader_instance_formats_get(void) void OVERLAY_shader_free(void) { + DRW_SHADER_LIB_FREE_SAFE(e_data.lib); + for (int sh_data_index = 0; sh_data_index < ARRAY_SIZE(e_data.sh_data); sh_data_index++) { OVERLAY_Shaders *sh_data = &e_data.sh_data[sh_data_index]; GPUShader **sh_data_as_array = (GPUShader **)sh_data; diff --git a/source/blender/draw/engines/overlay/shaders/background_frag.glsl b/source/blender/draw/engines/overlay/shaders/background_frag.glsl index d5aaaf75b79..71bfd2f8e73 100644 --- a/source/blender/draw/engines/overlay/shaders/background_frag.glsl +++ b/source/blender/draw/engines/overlay/shaders/background_frag.glsl @@ -13,6 +13,7 @@ out vec4 fragColor; #define BG_GRADIENT 1 #define BG_CHECKER 2 #define BG_RADIAL 3 +#define BG_SOLID_CHECKER 4 #define SQRT2 1.4142135623730950488 /* 4x4 bayer matrix prepared for 8bit UNORM precision error. */ @@ -43,7 +44,11 @@ void main() vec3 col_high; vec3 col_low; - switch (bgType) { + /* BG_SOLID_CHECKER selects BG_SOLID when no pixel has been drawn otherwise use the BG_CHERKER. + */ + int bg_type = bgType == BG_SOLID_CHECKER ? (depth == 1.0 ? BG_SOLID : BG_CHECKER) : bgType; + + switch (bg_type) { case BG_SOLID: bg_col = colorBackground.rgb; break; diff --git a/source/blender/draw/engines/overlay/shaders/common_overlay_lib.glsl b/source/blender/draw/engines/overlay/shaders/common_overlay_lib.glsl new file mode 100644 index 00000000000..65aeb81a4ef --- /dev/null +++ b/source/blender/draw/engines/overlay/shaders/common_overlay_lib.glsl @@ -0,0 +1,5 @@ +#define OVERLAY_UV_LINE_STYLE_OUTLINE 0 +#define OVERLAY_UV_LINE_STYLE_DASH 1 +#define OVERLAY_UV_LINE_STYLE_BLACK 2 +#define OVERLAY_UV_LINE_STYLE_WHITE 3 +#define OVERLAY_UV_LINE_STYLE_SHADOW 4 diff --git a/source/blender/draw/engines/overlay/shaders/edit_uv_edges_frag.glsl b/source/blender/draw/engines/overlay/shaders/edit_uv_edges_frag.glsl new file mode 100644 index 00000000000..b81fdd2c712 --- /dev/null +++ b/source/blender/draw/engines/overlay/shaders/edit_uv_edges_frag.glsl @@ -0,0 +1,77 @@ +#pragma BLENDER_REQUIRE(common_globals_lib.glsl) +#pragma BLENDER_REQUIRE(common_overlay_lib.glsl) + +uniform int lineStyle; +uniform bool doSmoothWire; +uniform float alpha; +uniform float dashLength; + +in float selectionFac_f; +noperspective in float edgeCoord_f; +noperspective in vec2 stipplePos_f; +flat in vec2 stippleStart_f; + +layout(location = 0) out vec4 fragColor; + +#define M_1_SQRTPI 0.5641895835477563 /* 1/sqrt(pi) */ + +/** + * We want to know how much a pixel is covered by a line. + * We replace the square pixel with acircle of the same area and try to find the intersection area. + * The area we search is the circular segment. https://en.wikipedia.org/wiki/Circular_segment + * The formula for the area uses inverse trig function and is quite complexe. Instead, + * we approximate it by using the smoothstep function and a 1.05 factor to the disc radius. + */ +#define DISC_RADIUS (M_1_SQRTPI * 1.05) +#define GRID_LINE_SMOOTH_START (0.5 - DISC_RADIUS) +#define GRID_LINE_SMOOTH_END (0.5 + DISC_RADIUS) + +void main() +{ + vec4 inner_color = vec4(vec3(0.0), 1.0); + vec4 outer_color = vec4(0.0); + + vec2 dd = fwidth(stipplePos_f); + float line_distance = distance(stipplePos_f, stippleStart_f) / max(dd.x, dd.y); + + if (lineStyle == OVERLAY_UV_LINE_STYLE_OUTLINE) { + inner_color = mix(colorWireEdit, colorEdgeSelect, selectionFac_f); + outer_color = vec4(vec3(0.0), 1.0); + } + else if (lineStyle == OVERLAY_UV_LINE_STYLE_DASH) { + if (fract(line_distance / dashLength) < 0.5) { + inner_color = mix(vec4(1.0), colorEdgeSelect, selectionFac_f); + } + } + else if (lineStyle == OVERLAY_UV_LINE_STYLE_BLACK) { + vec4 base_color = vec4(vec3(0.0), 1.0); + inner_color = mix(base_color, colorEdgeSelect, selectionFac_f); + } + else if (lineStyle == OVERLAY_UV_LINE_STYLE_WHITE) { + vec4 base_color = vec4(1.0); + inner_color = mix(base_color, colorEdgeSelect, selectionFac_f); + } + else if (lineStyle == OVERLAY_UV_LINE_STYLE_SHADOW) { + inner_color = colorUVShadow; + } + + float dist = abs(edgeCoord_f) - max(sizeEdge - 0.5, 0.0); + float dist_outer = dist - max(sizeEdge, 1.0); + float mix_w; + float mix_w_outer; + + if (doSmoothWire) { + mix_w = smoothstep(GRID_LINE_SMOOTH_START, GRID_LINE_SMOOTH_END, dist); + mix_w_outer = smoothstep(GRID_LINE_SMOOTH_START, GRID_LINE_SMOOTH_END, dist_outer); + } + else { + mix_w = step(0.5, dist); + mix_w_outer = step(0.5, dist_outer); + } + + vec4 final_color = mix(outer_color, inner_color, 1.0 - mix_w * outer_color.a); + final_color.a *= 1.0 - (outer_color.a > 0.0 ? mix_w_outer : mix_w); + final_color.a *= alpha; + + fragColor = final_color; +}
\ No newline at end of file diff --git a/source/blender/draw/engines/overlay/shaders/edit_uv_edges_geom.glsl b/source/blender/draw/engines/overlay/shaders/edit_uv_edges_geom.glsl new file mode 100644 index 00000000000..4f8d553a220 --- /dev/null +++ b/source/blender/draw/engines/overlay/shaders/edit_uv_edges_geom.glsl @@ -0,0 +1,63 @@ +#pragma BLENDER_REQUIRE(common_globals_lib.glsl) +#pragma BLENDER_REQUIRE(common_overlay_lib.glsl) + +layout(lines) in; +layout(triangle_strip, max_vertices = 4) out; + +in float selectionFac[2]; +flat in vec2 stippleStart[2]; +noperspective in vec2 stipplePos[2]; + +uniform int lineStyle; +uniform bool doSmoothWire; + +out float selectionFac_f; +noperspective out float edgeCoord_f; +noperspective out vec2 stipplePos_f; +flat out vec2 stippleStart_f; + +void do_vertex( + vec4 pos, float selection_fac, vec2 stipple_start, vec2 stipple_pos, float coord, vec2 offset) +{ + selectionFac_f = selection_fac; + edgeCoord_f = coord; + stippleStart_f = stipple_start; + stipplePos_f = stipple_pos; + + gl_Position = pos; + /* Multiply offset by 2 because gl_Position range is [-1..1]. */ + gl_Position.xy += offset * 2.0; + EmitVertex(); +} + +void main() +{ + vec2 ss_pos[2]; + vec4 pos0 = gl_in[0].gl_Position; + vec4 pos1 = gl_in[1].gl_Position; + ss_pos[0] = pos0.xy / pos0.w; + ss_pos[1] = pos1.xy / pos1.w; + + float half_size = sizeEdge; + /* Enlarge edge for outline drawing. */ + /* Factor of 3.0 out of nowhere! Seems to fix issues with float imprecision. */ + half_size += (lineStyle == OVERLAY_UV_LINE_STYLE_OUTLINE) ? + max(sizeEdge * (doSmoothWire ? 1.0 : 3.0), 1.0) : + 0.0; + /* Add 1 px for AA */ + if (doSmoothWire) { + half_size += 0.5; + } + + vec2 line = ss_pos[0] - ss_pos[1]; + vec2 line_dir = normalize(line); + vec2 line_perp = vec2(-line_dir.y, line_dir.x); + vec2 edge_ofs = line_perp * sizeViewportInv * ceil(half_size); + + do_vertex(pos0, selectionFac[0], stippleStart[0], stipplePos[0], half_size, edge_ofs.xy); + do_vertex(pos0, selectionFac[0], stippleStart[0], stipplePos[0], -half_size, -edge_ofs.xy); + do_vertex(pos1, selectionFac[1], stippleStart[1], stipplePos[1], half_size, edge_ofs.xy); + do_vertex(pos1, selectionFac[1], stippleStart[1], stipplePos[1], -half_size, -edge_ofs.xy); + + EndPrimitive(); +} diff --git a/source/blender/draw/engines/overlay/shaders/edit_uv_edges_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_uv_edges_vert.glsl new file mode 100644 index 00000000000..4661cf248e6 --- /dev/null +++ b/source/blender/draw/engines/overlay/shaders/edit_uv_edges_vert.glsl @@ -0,0 +1,32 @@ +#pragma BLENDER_REQUIRE(common_globals_lib.glsl) +#pragma BLENDER_REQUIRE(common_view_lib.glsl) + +in vec3 pos; +in vec2 u; +in int flag; + +out float selectionFac; +noperspective out vec2 stipplePos; +flat out vec2 stippleStart; + +void main() +{ + vec3 world_pos = point_object_to_world(vec3(u, 0.0)); + gl_Position = point_world_to_ndc(world_pos); + /* Snap vertices to the pixel grid to reduce artifacts. */ + vec2 half_viewport_res = sizeViewport.xy * 0.5; + vec2 half_pixel_offset = sizeViewportInv * 0.5; + gl_Position.xy = floor(gl_Position.xy * half_viewport_res) / half_viewport_res + + half_pixel_offset; + + bool is_select = (flag & VERT_UV_SELECT) != 0; + selectionFac = is_select ? 1.0 : 0.0; + /* Move selected edges to the top + * Vertices are between 0.0 and 0.2, Edges between 0.2 and 0.4 + * actual pixels are at 0.75, 1.0 is used for the background. */ + float depth = is_select ? 0.25 : 0.35; + gl_Position.z = depth; + + /* Avoid precision loss. */ + stippleStart = stipplePos = 500.0 + 500.0 * (gl_Position.xy / gl_Position.w); +} diff --git a/source/blender/draw/engines/overlay/shaders/edit_uv_face_dots_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_uv_face_dots_vert.glsl new file mode 100644 index 00000000000..61152c83a29 --- /dev/null +++ b/source/blender/draw/engines/overlay/shaders/edit_uv_face_dots_vert.glsl @@ -0,0 +1,18 @@ +#pragma BLENDER_REQUIRE(common_globals_lib.glsl) +#pragma BLENDER_REQUIRE(common_view_lib.glsl) + +uniform float pointSize; + +in vec2 u; +in int flag; + +flat out vec4 finalColor; + +void main() +{ + vec3 world_pos = point_object_to_world(vec3(u, 0.0)); + gl_Position = point_world_to_ndc(world_pos); + + finalColor = ((flag & FACE_UV_SELECT) != 0) ? colorVertexSelect : vec4(colorWire.rgb, 1.0); + gl_PointSize = pointSize; +} diff --git a/source/blender/draw/engines/overlay/shaders/edit_uv_faces_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_uv_faces_vert.glsl new file mode 100644 index 00000000000..cf1018ae5f9 --- /dev/null +++ b/source/blender/draw/engines/overlay/shaders/edit_uv_faces_vert.glsl @@ -0,0 +1,22 @@ +#pragma BLENDER_REQUIRE(common_globals_lib.glsl) +#pragma BLENDER_REQUIRE(common_view_lib.glsl) + +uniform float uvOpacity; + +in vec2 u; +in int flag; + +flat out vec4 finalColor; + +void main() +{ + vec3 world_pos = point_object_to_world(vec3(u, 0.0)); + gl_Position = point_world_to_ndc(world_pos); + + bool is_selected = (flag & FACE_UV_SELECT) != 0; + bool is_active = (flag & FACE_UV_ACTIVE) != 0; + + finalColor = (is_selected) ? colorFaceSelect : colorFace; + finalColor = (is_active) ? colorEditMeshActive : finalColor; + finalColor.a *= uvOpacity; +} diff --git a/source/blender/draw/engines/overlay/shaders/edit_uv_stretching_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_uv_stretching_vert.glsl new file mode 100644 index 00000000000..ce97f1e27ac --- /dev/null +++ b/source/blender/draw/engines/overlay/shaders/edit_uv_stretching_vert.glsl @@ -0,0 +1,98 @@ +#pragma BLENDER_REQUIRE(common_view_lib.glsl) + +uniform vec2 aspect; +in vec2 pos; + +#ifdef STRETCH_ANGLE +in vec2 uv_angles; +in float angle; + +#else +in float ratio; +uniform float totalAreaRatio; +uniform float totalAreaRatioInv; + +#endif + +noperspective out vec4 finalColor; + +vec3 weight_to_rgb(float weight) +{ + vec3 r_rgb; + float blend = ((weight / 2.0) + 0.5); + + if (weight <= 0.25) { /* blue->cyan */ + r_rgb[0] = 0.0; + r_rgb[1] = blend * weight * 4.0; + r_rgb[2] = blend; + } + else if (weight <= 0.50) { /* cyan->green */ + r_rgb[0] = 0.0; + r_rgb[1] = blend; + r_rgb[2] = blend * (1.0 - ((weight - 0.25) * 4.0)); + } + else if (weight <= 0.75) { /* green->yellow */ + r_rgb[0] = blend * ((weight - 0.50) * 4.0); + r_rgb[1] = blend; + r_rgb[2] = 0.0; + } + else if (weight <= 1.0) { /* yellow->red */ + r_rgb[0] = blend; + r_rgb[1] = blend * (1.0 - ((weight - 0.75) * 4.0)); + r_rgb[2] = 0.0; + } + else { + /* exceptional value, unclamped or nan, + * avoid uninitialized memory use */ + r_rgb[0] = 1.0; + r_rgb[1] = 0.0; + r_rgb[2] = 1.0; + } + + return r_rgb; +} + +#define M_PI 3.1415926535897932 + +vec2 angle_to_v2(float angle) +{ + return vec2(cos(angle), sin(angle)); +} + +/* Adapted from BLI_math_vector.h */ +float angle_normalized_v2v2(vec2 v1, vec2 v2) +{ + v1 = normalize(v1 * aspect); + v2 = normalize(v2 * aspect); + /* this is the same as acos(dot_v3v3(v1, v2)), but more accurate */ + bool q = (dot(v1, v2) >= 0.0); + vec2 v = (q) ? (v1 - v2) : (v1 + v2); + float a = 2.0 * asin(length(v) / 2.0); + return (q) ? a : M_PI - a; +} + +float area_ratio_to_stretch(float ratio, float tot_ratio, float inv_tot_ratio) +{ + ratio *= (ratio > 0.0f) ? tot_ratio : -inv_tot_ratio; + return (ratio > 1.0f) ? (1.0f / ratio) : ratio; +} + +void main() +{ + vec3 world_pos = point_object_to_world(vec3(pos, 0.0)); + gl_Position = point_world_to_ndc(world_pos); + +#ifdef STRETCH_ANGLE + vec2 v1 = angle_to_v2(uv_angles.x * M_PI); + vec2 v2 = angle_to_v2(uv_angles.y * M_PI); + float uv_angle = angle_normalized_v2v2(v1, v2) / M_PI; + float stretch = 1.0 - abs(uv_angle - angle); + stretch = stretch; + stretch = 1.0 - stretch * stretch; +#else + float stretch = 1.0 - area_ratio_to_stretch(ratio, totalAreaRatio, totalAreaRatioInv); + +#endif + + finalColor = vec4(weight_to_rgb(stretch), 1.0); +} diff --git a/source/blender/draw/engines/overlay/shaders/edit_uv_tiled_image_borders_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_uv_tiled_image_borders_vert.glsl new file mode 100644 index 00000000000..c762858a910 --- /dev/null +++ b/source/blender/draw/engines/overlay/shaders/edit_uv_tiled_image_borders_vert.glsl @@ -0,0 +1,12 @@ +#pragma BLENDER_REQUIRE(common_view_lib.glsl) + +in vec3 pos; + +void main() +{ + /* `pos` contains the coordinates of a quad (-1..1). but we need the coordinates of an image + * plane (0..1) */ + vec3 image_pos = pos * 0.5 + 0.5; + vec4 position = point_object_to_ndc(image_pos); + gl_Position = position; +} diff --git a/source/blender/draw/engines/overlay/shaders/edit_uv_verts_frag.glsl b/source/blender/draw/engines/overlay/shaders/edit_uv_verts_frag.glsl new file mode 100644 index 00000000000..11694de38ca --- /dev/null +++ b/source/blender/draw/engines/overlay/shaders/edit_uv_verts_frag.glsl @@ -0,0 +1,33 @@ + +uniform vec4 outlineColor; + +in vec4 radii; +in vec4 fillColor; +out vec4 fragColor; + +void main() +{ + float dist = length(gl_PointCoord - vec2(0.5)); + + // transparent outside of point + // --- 0 --- + // smooth transition + // --- 1 --- + // pure outline color + // --- 2 --- + // smooth transition + // --- 3 --- + // pure fill color + // ... + // dist = 0 at center of point + + float midStroke = 0.5 * (radii[1] + radii[2]); + + if (dist > midStroke) { + fragColor.rgb = outlineColor.rgb; + fragColor.a = mix(outlineColor.a, 0.0, smoothstep(radii[1], radii[0], dist)); + } + else { + fragColor = mix(fillColor, outlineColor, smoothstep(radii[3], radii[2], dist)); + } +} diff --git a/source/blender/draw/engines/overlay/shaders/edit_uv_verts_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_uv_verts_vert.glsl new file mode 100644 index 00000000000..327a35ce6b2 --- /dev/null +++ b/source/blender/draw/engines/overlay/shaders/edit_uv_verts_vert.glsl @@ -0,0 +1,44 @@ +#pragma BLENDER_REQUIRE(common_globals_lib.glsl) +#pragma BLENDER_REQUIRE(common_view_lib.glsl) + +uniform float pointSize; +uniform float outlineWidth; + +in vec2 u; +in int flag; + +out vec4 fillColor; +out vec4 outlineColor; +out vec4 radii; + +/* TODO Theme? */ +const vec4 pinned_col = vec4(1.0, 0.0, 0.0, 1.0); + +void main() +{ + bool is_selected = (flag & (VERT_UV_SELECT | FACE_UV_SELECT)) != 0; + bool is_pinned = (flag & VERT_UV_PINNED) != 0; + vec4 deselect_col = (is_pinned) ? pinned_col : vec4(colorWire.rgb, 1.0); + fillColor = (is_selected) ? colorVertexSelect : deselect_col; + outlineColor = (is_pinned) ? pinned_col : vec4(fillColor.rgb, 0.0); + + vec3 world_pos = point_object_to_world(vec3(u, 0.0)); + /* Move selected vertices to the top + * Vertices are between 0.0 and 0.2, Edges between 0.2 and 0.4 + * actual pixels are at 0.75, 1.0 is used for the background. */ + float depth = is_selected ? 0.05 : 0.15; + gl_Position = vec4(point_world_to_ndc(world_pos).xy, depth, 1.0); + gl_PointSize = pointSize; + + // calculate concentric radii in pixels + float radius = 0.5 * pointSize; + + // start at the outside and progress toward the center + radii[0] = radius; + radii[1] = radius - 1.0; + radii[2] = radius - outlineWidth; + radii[3] = radius - outlineWidth - 1.0; + + // convert to PointCoord units + radii /= pointSize; +} diff --git a/source/blender/draw/engines/overlay/shaders/grid_vert.glsl b/source/blender/draw/engines/overlay/shaders/grid_vert.glsl index dd0e771ad93..6df4ead9f2a 100644 --- a/source/blender/draw/engines/overlay/shaders/grid_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/grid_vert.glsl @@ -12,7 +12,7 @@ uniform int gridFlag; #define PLANE_YZ (1 << 6) #define CLIP_Z_POS (1 << 7) #define CLIP_Z_NEG (1 << 8) - +#define PLANE_IMAGE (1 << 11) in vec3 pos; out vec3 local_pos; @@ -28,9 +28,12 @@ void main() else if ((gridFlag & PLANE_XZ) != 0) { vert_pos = vec3(pos.x, 0.0, pos.y); } - else { + else if ((gridFlag & PLANE_YZ) != 0) { vert_pos = vec3(0.0, pos.x, pos.y); } + else /* PLANE_IMAGE */ { + vert_pos = vec3(pos.xy * 0.5 + 0.5, 0.0); + } local_pos = vert_pos; diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h index e154a52b32f..8e3562216e9 100644 --- a/source/blender/draw/intern/DRW_render.h +++ b/source/blender/draw/intern/DRW_render.h @@ -736,9 +736,11 @@ bool DRW_state_draw_background(void); /* Avoid too many lookups while drawing */ typedef struct DRWContextState { - struct ARegion *region; /* 'CTX_wm_region(C)' */ - struct RegionView3D *rv3d; /* 'CTX_wm_region_view3d(C)' */ - struct View3D *v3d; /* 'CTX_wm_view3d(C)' */ + + struct ARegion *region; /* 'CTX_wm_region(C)' */ + struct RegionView3D *rv3d; /* 'CTX_wm_region_view3d(C)' */ + struct View3D *v3d; /* 'CTX_wm_view3d(C)' */ + struct SpaceLink *space_data; /* 'CTX_wm_space_data(C)' */ struct Scene *scene; /* 'CTX_data_scene(C)' */ struct ViewLayer *view_layer; /* 'CTX_data_view_layer(C)' */ diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c index ea5421f3965..56f31a69396 100644 --- a/source/blender/draw/intern/draw_common.c +++ b/source/blender/draw/intern/draw_common.c @@ -178,6 +178,9 @@ void DRW_globals_update(void) UI_GetThemeColorShadeAlpha4fv(TH_WIRE, 0, -30, gb->colorOutline); UI_GetThemeColorShadeAlpha4fv(TH_LIGHT, 0, 255, gb->colorLightNoAlpha); + /* UV colors */ + UI_GetThemeColor4fv(TH_UV_SHADOW, gb->colorUVShadow); + gb->sizePixel = U.pixelsize; gb->sizeObjectCenter = (UI_GetThemeValuef(TH_OBCENTER_DIA) + 1.0f) * U.pixelsize; gb->sizeLightCenter = (UI_GetThemeValuef(TH_OBCENTER_DIA) + 1.5f) * U.pixelsize; @@ -210,7 +213,7 @@ void DRW_globals_update(void) /* TODO more accurate transform. */ srgb_to_linearrgb_v4(color, color); color += 4; - } while (color != gb->UBO_LAST_COLOR); + } while (color <= gb->UBO_LAST_COLOR); } if (G_draw.block_ubo == NULL) { diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h index 645848e7fe0..e3967678319 100644 --- a/source/blender/draw/intern/draw_common.h +++ b/source/blender/draw/intern/draw_common.h @@ -33,7 +33,7 @@ struct RegionView3D; struct ViewLayer; #define UBO_FIRST_COLOR colorWire -#define UBO_LAST_COLOR colorFaceFront +#define UBO_LAST_COLOR colorUVShadow /* Used as ubo but colors can be directly referenced as well */ /* Keep in sync with: common_globals_lib.glsl (globalsBlock) */ @@ -141,6 +141,8 @@ typedef struct GlobalsUboStorage { float colorFaceBack[4]; float colorFaceFront[4]; + float colorUVShadow[4]; + /* NOTE! Put all color before UBO_LAST_COLOR */ float screenVecs[2][4]; /* padded as vec4 */ float sizeViewport[2], sizeViewportInv[2]; /* packed as vec4 in glsl */ diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index e6d51bce54e..203f8af130d 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -78,6 +78,7 @@ #include "RE_pipeline.h" #include "UI_resources.h" +#include "UI_view2d.h" #include "WM_api.h" #include "wm_window.h" @@ -94,6 +95,7 @@ #include "engines/eevee/eevee_engine.h" #include "engines/external/external_engine.h" #include "engines/gpencil/gpencil_engine.h" +#include "engines/image/image_engine.h" #include "engines/overlay/overlay_engine.h" #include "engines/select/select_engine.h" #include "engines/workbench/workbench_engine.h" @@ -126,6 +128,25 @@ static void drw_state_ensure_not_reused(DRWManager *dst) } #endif +static bool drw_draw_show_annotation(void) +{ + if (DST.draw_ctx.space_data == NULL) { + View3D *v3d = DST.draw_ctx.v3d; + return (v3d && ((v3d->flag2 & V3D_SHOW_ANNOTATION) != 0) && + ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0)); + } + + switch (DST.draw_ctx.space_data->spacetype) { + case SPACE_IMAGE: { + SpaceImage *sima = (SpaceImage *)DST.draw_ctx.space_data; + return (sima->flag & SI_SHOW_GPENCIL) != 0; + } + default: + BLI_assert(""); + return false; + } +} + /* -------------------------------------------------------------------- */ /** \name Threading * \{ */ @@ -287,6 +308,7 @@ struct DupliObject *DRW_object_get_dupli(const Object *UNUSED(ob)) /** \name Color Management * \{ */ +/* TODO(fclem) This should be a render engine callback to determine if we need CM or not. */ static void drw_viewport_colormanagement_set(void) { Scene *scene = DST.draw_ctx.scene; @@ -296,21 +318,43 @@ static void drw_viewport_colormanagement_set(void) ColorManagedViewSettings view_settings; float dither = 0.0f; - /* TODO(fclem) This should be a render engine callback to determine if we need CM or not. */ - bool use_workbench = BKE_scene_uses_blender_workbench(scene); - - bool use_scene_lights = (!v3d || - ((v3d->shading.type == OB_MATERIAL) && - (v3d->shading.flag & V3D_SHADING_SCENE_LIGHTS)) || - ((v3d->shading.type == OB_RENDER) && - (v3d->shading.flag & V3D_SHADING_SCENE_LIGHTS_RENDER))); - bool use_scene_world = - (!v3d || - ((v3d->shading.type == OB_MATERIAL) && (v3d->shading.flag & V3D_SHADING_SCENE_WORLD)) || - ((v3d->shading.type == OB_RENDER) && (v3d->shading.flag & V3D_SHADING_SCENE_WORLD_RENDER))); - bool use_view_transform = v3d && (v3d->shading.type >= OB_MATERIAL); - bool use_render_settings = v3d && ((use_workbench && use_view_transform) || use_scene_lights || - use_scene_world); + bool use_render_settings = false; + bool use_view_transform = false; + + if (v3d) { + bool use_workbench = BKE_scene_uses_blender_workbench(scene); + + bool use_scene_lights = (!v3d || + ((v3d->shading.type == OB_MATERIAL) && + (v3d->shading.flag & V3D_SHADING_SCENE_LIGHTS)) || + ((v3d->shading.type == OB_RENDER) && + (v3d->shading.flag & V3D_SHADING_SCENE_LIGHTS_RENDER))); + bool use_scene_world = (!v3d || + ((v3d->shading.type == OB_MATERIAL) && + (v3d->shading.flag & V3D_SHADING_SCENE_WORLD)) || + ((v3d->shading.type == OB_RENDER) && + (v3d->shading.flag & V3D_SHADING_SCENE_WORLD_RENDER))); + use_view_transform = v3d && (v3d->shading.type >= OB_MATERIAL); + use_render_settings = v3d && ((use_workbench && use_view_transform) || use_scene_lights || + use_scene_world); + } + else if (DST.draw_ctx.space_data && DST.draw_ctx.space_data->spacetype == SPACE_IMAGE) { + SpaceImage *sima = (SpaceImage *)DST.draw_ctx.space_data; + Image *image = sima->image; + + /* Use inverse logic as there isn't a setting for `Color And Alpha`. */ + const eSpaceImage_Flag display_channels_mode = sima->flag; + const bool display_color_channel = (display_channels_mode & (SI_SHOW_ALPHA | SI_SHOW_ZBUF)) == + 0; + if (display_color_channel && image && (image->source != IMA_SRC_GENERATED) && + ((image->flag & IMA_VIEW_AS_RENDER) != 0)) { + use_render_settings = true; + } + } + else { + use_render_settings = true; + use_view_transform = false; + } if (use_render_settings) { /* Use full render settings, for renders with scene lighting. */ @@ -495,6 +539,8 @@ static void draw_unit_state_create(void) static void drw_viewport_var_init(void) { RegionView3D *rv3d = DST.draw_ctx.rv3d; + ARegion *region = DST.draw_ctx.region; + /* Refresh DST.size */ if (DST.viewport) { int size[2]; @@ -585,6 +631,24 @@ static void drw_viewport_var_init(void) DST.view_active = DST.view_default; DST.view_previous = NULL; } + else if (region) { + View2D *v2d = ®ion->v2d; + float viewmat[4][4]; + float winmat[4][4]; + + rctf region_space = {0.0f, 1.0f, 0.0f, 1.0f}; + BLI_rctf_transform_calc_m4_pivot_min(&v2d->cur, ®ion_space, viewmat); + + unit_m4(winmat); + winmat[0][0] = 2.0f; + winmat[1][1] = 2.0f; + winmat[3][0] = -1.0f; + winmat[3][1] = -1.0f; + + DST.view_default = DRW_view_create(viewmat, winmat, NULL, NULL, NULL); + DST.view_active = DST.view_default; + DST.view_previous = NULL; + } else { zero_v3(DST.screenvecs[0]); zero_v3(DST.screenvecs[1]); @@ -596,7 +660,7 @@ static void drw_viewport_var_init(void) } /* fclem: Is this still needed ? */ - if (DST.draw_ctx.object_edit) { + if (DST.draw_ctx.object_edit && rv3d) { ED_view3d_init_mats_rv3d(DST.draw_ctx.object_edit, rv3d); } @@ -1163,6 +1227,19 @@ static void drw_engines_enable_basic(void) use_drw_engine(&draw_engine_basic_type); } +static void drw_engines_enable_editors(void) +{ + SpaceLink *space_data = DST.draw_ctx.space_data; + if (!space_data) { + return; + } + + if (space_data->spacetype == SPACE_IMAGE) { + use_drw_engine(&draw_engine_image_type); + use_drw_engine(&draw_engine_overlay_type); + } +} + static void drw_engines_enable(ViewLayer *UNUSED(view_layer), RenderEngineType *engine_type, bool gpencil_engine_needed) @@ -1299,8 +1376,7 @@ void DRW_draw_callbacks_post_scene(void) View3D *v3d = DST.draw_ctx.v3d; Depsgraph *depsgraph = DST.draw_ctx.depsgraph; - const bool do_annotations = (v3d && ((v3d->flag2 & V3D_SHOW_ANNOTATION) != 0) && - ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0)); + const bool do_annotations = drw_draw_show_annotation(); if (DST.draw_ctx.evil_C) { DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); @@ -1387,21 +1463,30 @@ struct DRWTextStore *DRW_text_cache_ensure(void) * for each relevant engine / mode engine. */ void DRW_draw_view(const bContext *C) { - Depsgraph *depsgraph = CTX_data_expect_evaluated_depsgraph(C); - ARegion *region = CTX_wm_region(C); View3D *v3d = CTX_wm_view3d(C); - Scene *scene = DEG_get_evaluated_scene(depsgraph); - RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->shading.type); - GPUViewport *viewport = WM_draw_region_get_bound_viewport(region); + if (v3d) { + Depsgraph *depsgraph = CTX_data_expect_evaluated_depsgraph(C); + ARegion *region = CTX_wm_region(C); + Scene *scene = DEG_get_evaluated_scene(depsgraph); + RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->shading.type); + GPUViewport *viewport = WM_draw_region_get_bound_viewport(region); - /* Reset before using it. */ - drw_state_prepare_clean_for_draw(&DST); - DST.options.draw_text = ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0 && - (v3d->overlay.flag & V3D_OVERLAY_HIDE_TEXT) != 0); - DST.options.draw_background = (scene->r.alphamode == R_ADDSKY) || - (v3d->shading.type != OB_RENDER); - DST.options.do_color_management = true; - DRW_draw_render_loop_ex(depsgraph, engine_type, region, v3d, viewport, C); + /* Reset before using it. */ + drw_state_prepare_clean_for_draw(&DST); + DST.options.draw_text = ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0 && + (v3d->overlay.flag & V3D_OVERLAY_HIDE_TEXT) != 0); + DST.options.draw_background = (scene->r.alphamode == R_ADDSKY) || + (v3d->shading.type != OB_RENDER); + DST.options.do_color_management = true; + DRW_draw_render_loop_ex(depsgraph, engine_type, region, v3d, viewport, C); + } + else { + Depsgraph *depsgraph = CTX_data_expect_evaluated_depsgraph(C); + ARegion *ar = CTX_wm_region(C); + GPUViewport *viewport = WM_draw_region_get_bound_viewport(ar); + drw_state_prepare_clean_for_draw(&DST); + DRW_draw_render_loop_2d_ex(depsgraph, ar, viewport, C); + } } /** @@ -1909,6 +1994,171 @@ void DRW_cache_restart(void) copy_v2_v2(DST.inv_size, inv_size); } +void DRW_draw_render_loop_2d_ex(struct Depsgraph *depsgraph, + ARegion *region, + GPUViewport *viewport, + const bContext *evil_C) +{ + Scene *scene = DEG_get_evaluated_scene(depsgraph); + ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); + + DST.draw_ctx.evil_C = evil_C; + DST.viewport = viewport; + + /* Setup viewport */ + DST.draw_ctx = (DRWContextState){ + .region = region, + .scene = scene, + .view_layer = view_layer, + .obact = OBACT(view_layer), + .depsgraph = depsgraph, + .space_data = CTX_wm_space_data(evil_C), + + /* reuse if caller sets */ + .evil_C = DST.draw_ctx.evil_C, + }; + + drw_context_state_init(); + drw_viewport_var_init(); + drw_viewport_colormanagement_set(); + + /* TODO(jbakker): Only populate when editor needs to draw object. + * for the image editor this is when showing UV's.*/ + const bool do_populate_loop = true; + const bool do_annotations = drw_draw_show_annotation(); + + /* Get list of enabled engines */ + drw_engines_enable_editors(); + drw_engines_data_validate(); + + /* Update ubos */ + DRW_globals_update(); + + drw_debug_init(); + + /* No framebuffer allowed before drawing. */ + BLI_assert(GPU_framebuffer_active_get() == GPU_framebuffer_back_get()); + GPU_framebuffer_bind(DST.default_framebuffer); + GPU_framebuffer_clear_depth_stencil(DST.default_framebuffer, 1.0f, 0xFF); + + /* Init engines */ + drw_engines_init(); + drw_task_graph_init(); + + /* Cache filling */ + { + PROFILE_START(stime); + drw_engines_cache_init(); + + /* Only iterate over objects when overlay uses object data. */ + if (do_populate_loop) { + DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN (depsgraph, ob) { + drw_engines_cache_populate(ob); + } + DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END; + } + + drw_engines_cache_finish(); + + DRW_render_instance_buffer_finish(); + +#ifdef USE_PROFILE + double *cache_time = GPU_viewport_cache_time_get(DST.viewport); + PROFILE_END_UPDATE(*cache_time, stime); +#endif + } + drw_task_graph_deinit(); + + DRW_stats_begin(); + + GPU_framebuffer_bind(DST.default_framebuffer); + + /* Start Drawing */ + DRW_state_reset(); + + if (DST.draw_ctx.evil_C) { + ED_region_draw_cb_draw(DST.draw_ctx.evil_C, DST.draw_ctx.region, REGION_DRAW_PRE_VIEW); + } + + drw_engines_draw_scene(); + + /* Fix 3D view being "laggy" on macos and win+nvidia. (See T56996, T61474) */ + GPU_flush(); + + if (DST.draw_ctx.evil_C) { + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + DRW_state_reset(); + + GPU_framebuffer_bind(dfbl->overlay_fb); + + if (do_annotations) { + GPU_depth_test(false); + GPU_matrix_push_projection(); + wmOrtho2( + region->v2d.cur.xmin, region->v2d.cur.xmax, region->v2d.cur.ymin, region->v2d.cur.ymax); + ED_annotation_draw_view2d(DST.draw_ctx.evil_C, true); + GPU_matrix_pop_projection(); + + GPU_depth_test(true); + } + + GPU_depth_test(false); + ED_region_draw_cb_draw(DST.draw_ctx.evil_C, DST.draw_ctx.region, REGION_DRAW_POST_VIEW); + GPU_depth_test(true); + /* Callback can be nasty and do whatever they want with the state. + * Don't trust them! */ + DRW_state_reset(); + + GPU_depth_test(false); + drw_engines_draw_text(); + GPU_depth_test(true); + + if (do_annotations) { + GPU_depth_test(false); + ED_annotation_draw_view2d(DST.draw_ctx.evil_C, false); + GPU_depth_test(true); + } + } + + DRW_draw_cursor_2d(); + ED_region_pixelspace(DST.draw_ctx.region); + + { + GPU_depth_test(false); + DRW_draw_gizmo_2d(); + GPU_depth_test(true); + } + + DRW_stats_reset(); + + if (G.debug_value > 20 && G.debug_value < 30) { + GPU_depth_test(false); + /* local coordinate visible rect inside region, to accommodate overlapping ui */ + const rcti *rect = ED_region_visible_rect(DST.draw_ctx.region); + DRW_stats_draw(rect); + GPU_depth_test(true); + } + + if (WM_draw_region_get_bound_viewport(region)) { + /* Don't unbind the framebuffer yet in this case and let + * GPU_viewport_unbind do it, so that we can still do further + * drawing of action zones on top. */ + } + else { + GPU_framebuffer_restore(); + } + + DRW_state_reset(); + drw_engines_disable(); + + drw_viewport_cache_resize(); + +#ifdef DEBUG + /* Avoid accidental reuse. */ + drw_state_ensure_not_reused(&DST); +#endif +} + static struct DRWSelectBuffer { struct GPUFrameBuffer *framebuffer_depth_only; struct GPUTexture *texture_depth; @@ -2637,6 +2887,8 @@ void DRW_engines_register(void) DRW_engine_register(&draw_engine_select_type); DRW_engine_register(&draw_engine_basic_type); + DRW_engine_register(&draw_engine_image_type); + /* setup callbacks */ { BKE_mball_batch_cache_dirty_tag_cb = DRW_mball_batch_cache_dirty_tag; diff --git a/source/blender/draw/intern/draw_manager_text.c b/source/blender/draw/intern/draw_manager_text.c index adcac15ab85..e3d0dab6767 100644 --- a/source/blender/draw/intern/draw_manager_text.c +++ b/source/blender/draw/intern/draw_manager_text.c @@ -24,6 +24,7 @@ #include "BLI_math.h" #include "BLI_memiter.h" +#include "BLI_rect.h" #include "BLI_string.h" #include "BKE_editmesh.h" @@ -122,76 +123,105 @@ void DRW_text_cache_add(DRWTextStore *dt, } } -void DRW_text_cache_draw(DRWTextStore *dt, ARegion *region, struct View3D *v3d) +static void drw_text_cache_draw_ex(DRWTextStore *dt, ARegion *region) { - RegionView3D *rv3d = region->regiondata; ViewCachedString *vos; - int tot = 0; - - /* project first and test */ BLI_memiter_handle it; - BLI_memiter_iter_init(dt->cache_strings, &it); - while ((vos = BLI_memiter_iter_step(&it))) { - if (ED_view3d_project_short_ex( - region, - (vos->flag & DRW_TEXT_CACHE_GLOBALSPACE) ? rv3d->persmat : rv3d->persmatob, - (vos->flag & DRW_TEXT_CACHE_LOCALCLIP) != 0, - vos->vec, - vos->sco, - V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == - V3D_PROJ_RET_OK) { - tot++; - } - else { - vos->sco[0] = IS_CLIPPED; - } - } + int col_pack_prev = 0; - if (tot) { - int col_pack_prev = 0; + float original_proj[4][4]; + GPU_matrix_projection_get(original_proj); + wmOrtho2_region_pixelspace(region); - /* Disable clipping for text */ - if (RV3D_CLIPPING_ENABLED(v3d, rv3d)) { - GPU_clip_distances(0); - } + GPU_matrix_push(); + GPU_matrix_identity_set(); - float original_proj[4][4]; - GPU_matrix_projection_get(original_proj); - wmOrtho2_region_pixelspace(region); + const int font_id = BLF_default(); - GPU_matrix_push(); - GPU_matrix_identity_set(); + const uiStyle *style = UI_style_get(); - const int font_id = BLF_default(); + BLF_size(font_id, style->widget.points * U.pixelsize, U.dpi); - const uiStyle *style = UI_style_get(); + BLI_memiter_iter_init(dt->cache_strings, &it); + while ((vos = BLI_memiter_iter_step(&it))) { + if (vos->sco[0] != IS_CLIPPED) { + if (col_pack_prev != vos->col.pack) { + BLF_color4ubv(font_id, vos->col.ub); + col_pack_prev = vos->col.pack; + } + + BLF_position( + font_id, (float)(vos->sco[0] + vos->xoffs), (float)(vos->sco[1] + vos->yoffs), 2.0f); + + ((vos->flag & DRW_TEXT_CACHE_ASCII) ? BLF_draw_ascii : BLF_draw)( + font_id, + (vos->flag & DRW_TEXT_CACHE_STRING_PTR) ? *((const char **)vos->str) : vos->str, + vos->str_len); + } + } - BLF_size(font_id, style->widget.points * U.pixelsize, U.dpi); + GPU_matrix_pop(); + GPU_matrix_projection_set(original_proj); +} +void DRW_text_cache_draw(DRWTextStore *dt, ARegion *region, struct View3D *v3d) +{ + ViewCachedString *vos; + if (v3d) { + RegionView3D *rv3d = region->regiondata; + int tot = 0; + /* project first and test */ + BLI_memiter_handle it; BLI_memiter_iter_init(dt->cache_strings, &it); while ((vos = BLI_memiter_iter_step(&it))) { - if (vos->sco[0] != IS_CLIPPED) { - if (col_pack_prev != vos->col.pack) { - BLF_color4ubv(font_id, vos->col.ub); - col_pack_prev = vos->col.pack; - } + if (ED_view3d_project_short_ex( + region, + (vos->flag & DRW_TEXT_CACHE_GLOBALSPACE) ? rv3d->persmat : rv3d->persmatob, + (vos->flag & DRW_TEXT_CACHE_LOCALCLIP) != 0, + vos->vec, + vos->sco, + V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == + V3D_PROJ_RET_OK) { + tot++; + } + else { + vos->sco[0] = IS_CLIPPED; + } + } - BLF_position( - font_id, (float)(vos->sco[0] + vos->xoffs), (float)(vos->sco[1] + vos->yoffs), 2.0f); + if (tot) { + /* Disable clipping for text */ + const bool rv3d_clipping_enabled = RV3D_CLIPPING_ENABLED(v3d, rv3d); + if (rv3d_clipping_enabled) { + GPU_clip_distances(0); + } + + drw_text_cache_draw_ex(dt, region); - ((vos->flag & DRW_TEXT_CACHE_ASCII) ? BLF_draw_ascii : BLF_draw)( - font_id, - (vos->flag & DRW_TEXT_CACHE_STRING_PTR) ? *((const char **)vos->str) : vos->str, - vos->str_len); + if (rv3d_clipping_enabled) { + GPU_clip_distances(6); } } + } + else { + /* project first */ + BLI_memiter_handle it; + BLI_memiter_iter_init(dt->cache_strings, &it); + View2D *v2d = ®ion->v2d; + float viewmat[4][4]; + rctf region_space = {0.0f, region->winx, 0.0f, region->winy}; + BLI_rctf_transform_calc_m4_pivot_min(&v2d->cur, ®ion_space, viewmat); - GPU_matrix_pop(); - GPU_matrix_projection_set(original_proj); + while ((vos = BLI_memiter_iter_step(&it))) { + float p[3]; + copy_v3_v3(p, vos->vec); + mul_m4_v3(viewmat, p); - if (RV3D_CLIPPING_ENABLED(v3d, rv3d)) { - GPU_clip_distances(6); + vos->sco[0] = p[0]; + vos->sco[1] = p[1]; } + + drw_text_cache_draw_ex(dt, region); } } diff --git a/source/blender/draw/intern/draw_view.c b/source/blender/draw/intern/draw_view.c index d01e1a51080..3033cf70b29 100644 --- a/source/blender/draw/intern/draw_view.c +++ b/source/blender/draw/intern/draw_view.c @@ -35,6 +35,7 @@ #include "GPU_shader.h" #include "UI_resources.h" +#include "UI_view2d.h" #include "WM_types.h" @@ -196,6 +197,65 @@ void DRW_draw_cursor(void) } } +/* -------------------------------------------------------------------- */ + +/** \name 2D Cursor + * \{ */ + +static bool is_cursor_visible_2d(const DRWContextState *draw_ctx) +{ + SpaceInfo *space_data = (SpaceInfo *)draw_ctx->space_data; + if (space_data == NULL) { + return false; + } + if (space_data->spacetype == SPACE_IMAGE) { + SpaceImage *sima = (SpaceImage *)draw_ctx->space_data; + return sima->mode == SI_MODE_UV; + } + return false; +} + +void DRW_draw_cursor_2d(void) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + ARegion *region = draw_ctx->region; + + GPU_color_mask(true, true, true, true); + GPU_depth_mask(false); + GPU_depth_test(GPU_DEPTH_NONE); + + if (is_cursor_visible_2d(draw_ctx)) { + SpaceImage *sima = (SpaceImage *)draw_ctx->space_data; + int co[2]; + UI_view2d_view_to_region(®ion->v2d, sima->cursor[0], sima->cursor[1], &co[0], &co[1]); + + /* Draw nice Anti Aliased cursor. */ + GPU_line_width(1.0f); + GPU_blend(true); + GPU_line_smooth(true); + + /* Draw lines */ + float original_proj[4][4]; + GPU_matrix_projection_get(original_proj); + GPU_matrix_push(); + ED_region_pixelspace(region); + GPU_matrix_translate_2f(co[0] + 0.5f, co[1] + 0.5f); + GPU_matrix_scale_2f(U.widget_unit, U.widget_unit); + + GPUBatch *cursor_batch = DRW_cache_cursor_get(true); + GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_FLAT_COLOR); + GPU_batch_set_shader(cursor_batch, shader); + + GPU_batch_draw(cursor_batch); + + GPU_blend(false); + GPU_line_smooth(false); + GPU_matrix_pop(); + GPU_matrix_projection_set(original_proj); + } +} +/* \} */ + /* **************************** 3D Gizmo ******************************** */ void DRW_draw_gizmo_3d(void) diff --git a/source/blender/draw/intern/draw_view.h b/source/blender/draw/intern/draw_view.h index a01a2d0dcce..24fabaae05e 100644 --- a/source/blender/draw/intern/draw_view.h +++ b/source/blender/draw/intern/draw_view.h @@ -25,5 +25,6 @@ void DRW_draw_region_info(void); void DRW_clear_background(void); void DRW_draw_cursor(void); +void DRW_draw_cursor_2d(void); void DRW_draw_gizmo_3d(void); void DRW_draw_gizmo_2d(void); diff --git a/source/blender/draw/intern/shaders/common_globals_lib.glsl b/source/blender/draw/intern/shaders/common_globals_lib.glsl index bd1b1fb6f3a..691f1d5e519 100644 --- a/source/blender/draw/intern/shaders/common_globals_lib.glsl +++ b/source/blender/draw/intern/shaders/common_globals_lib.glsl @@ -103,6 +103,8 @@ layout(std140) uniform globalsBlock vec4 colorFaceBack; vec4 colorFaceFront; + vec4 colorUVShadow; + vec4 screenVecs[2]; vec4 sizeViewport; /* Inverted size in zw. */ diff --git a/source/blender/draw/tests/shaders_test.cc b/source/blender/draw/tests/shaders_test.cc index b73c94208b5..8feccc9588e 100644 --- a/source/blender/draw/tests/shaders_test.cc +++ b/source/blender/draw/tests/shaders_test.cc @@ -11,6 +11,7 @@ #include "engines/eevee/eevee_private.h" #include "engines/gpencil/gpencil_engine.h" +#include "engines/image/image_private.h" #include "engines/overlay/overlay_private.h" #include "engines/workbench/workbench_private.h" @@ -151,8 +152,19 @@ TEST_F(DrawTest, gpencil_glsl_shaders) GPENCIL_shader_free(); } +TEST_F(DrawTest, image_glsl_shaders) +{ + IMAGE_shader_library_ensure(); + + EXPECT_NE(IMAGE_shader_image_get(), nullptr); + + IMAGE_shader_free(); +} + TEST_F(DrawTest, overlay_glsl_shaders) { + OVERLAY_shader_library_ensure(); + for (int i = 0; i < 2; i++) { eGPUShaderConfig sh_cfg = i == 0 ? GPU_SHADER_CFG_DEFAULT : GPU_SHADER_CFG_CLIPPED; DRW_draw_state_init_gtests(sh_cfg); @@ -189,6 +201,13 @@ TEST_F(DrawTest, overlay_glsl_shaders) EXPECT_NE(OVERLAY_shader_edit_mesh_vert(), nullptr); EXPECT_NE(OVERLAY_shader_edit_particle_strand(), nullptr); EXPECT_NE(OVERLAY_shader_edit_particle_point(), nullptr); + EXPECT_NE(OVERLAY_shader_edit_uv_edges_get(), nullptr); + EXPECT_NE(OVERLAY_shader_edit_uv_face_get(), nullptr); + EXPECT_NE(OVERLAY_shader_edit_uv_face_dots_get(), nullptr); + EXPECT_NE(OVERLAY_shader_edit_uv_verts_get(), nullptr); + EXPECT_NE(OVERLAY_shader_edit_uv_stretching_area_get(), nullptr); + EXPECT_NE(OVERLAY_shader_edit_uv_stretching_angle_get(), nullptr); + EXPECT_NE(OVERLAY_shader_edit_uv_tiled_image_borders_get(), nullptr); EXPECT_NE(OVERLAY_shader_extra(false), nullptr); EXPECT_NE(OVERLAY_shader_extra(true), nullptr); EXPECT_NE(OVERLAY_shader_extra_groundline(), nullptr); @@ -201,6 +220,7 @@ TEST_F(DrawTest, overlay_glsl_shaders) EXPECT_NE(OVERLAY_shader_facing(), nullptr); EXPECT_NE(OVERLAY_shader_gpencil_canvas(), nullptr); EXPECT_NE(OVERLAY_shader_grid(), nullptr); + EXPECT_NE(OVERLAY_shader_grid_image(), nullptr); EXPECT_NE(OVERLAY_shader_image(), nullptr); EXPECT_NE(OVERLAY_shader_motion_path_line(), nullptr); EXPECT_NE(OVERLAY_shader_motion_path_vert(), nullptr); diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 2b3df79476a..e6815582a04 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -3640,9 +3640,8 @@ static void subdividenurb(Object *obedit, View3D *v3d, int number_cuts) * degree of the functions used to build the NURB. The * expression * - * degree = #knots - #controlpoints + 1 (J Walter piece) - * degree = #knots - #controlpoints (Blender - * implementation) + * `degree = knots - controlpoints + 1` (J Walter piece) + * `degree = knots - controlpoints` (Blender implementation) * ( this is confusing.... what is true? Another concern * is that the JW piece allows the curve to become * explicitly 1st order derivative discontinuous, while @@ -3651,12 +3650,12 @@ static void subdividenurb(Object *obedit, View3D *v3d, int number_cuts) * is an invariant for a single NURB curve. Raising the degree * of the NURB is done elsewhere; the degree is assumed * constant during this operation. Degree is a property shared - * by all controlpoints in a curve (even though it is stored + * by all control-points in a curve (even though it is stored * per control point - this can be misleading). * Adding a knot is done by searching for the place in the * knot vector where a certain knot value must be inserted, or * by picking an appropriate knot value between two existing - * ones. The number of controlpoints that is influenced by the + * ones. The number of control-points that is influenced by the * insertion depends on the order of the curve. A certain * minimum number of knots is needed to form high-order * curves, as can be seen from the equation above. In Blender, diff --git a/source/blender/editors/curve/editcurve_add.c b/source/blender/editors/curve/editcurve_add.c index 19b05f0af0c..4d72e90b89b 100644 --- a/source/blender/editors/curve/editcurve_add.c +++ b/source/blender/editors/curve/editcurve_add.c @@ -508,7 +508,10 @@ Nurb *ED_curve_add_nurbs_primitive( static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf) { - Object *obedit = CTX_data_edit_object(C); + struct Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); ListBase *editnurb; Nurb *nu; bool newob = false; @@ -565,7 +568,7 @@ static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf) /* userdef */ if (newob && !enter_editmode) { - ED_object_editmode_exit(C, EM_FREEDATA); + ED_object_editmode_exit_ex(bmain, scene, obedit, EM_FREEDATA); } WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit); diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c index 3c426e5d2b1..b7bf6230f22 100644 --- a/source/blender/editors/mesh/editmesh_add.c +++ b/source/blender/editors/mesh/editmesh_add.c @@ -104,7 +104,7 @@ static void make_prim_finish(bContext *C, /* userdef */ if (exit_editmode) { - ED_object_editmode_exit(C, EM_FREEDATA); + ED_object_editmode_exit_ex(CTX_data_main(C), CTX_data_scene(C), obedit, EM_FREEDATA); } WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit); } diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 4de48fba494..fa1d147dc5e 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -529,9 +529,12 @@ Object *ED_object_add_type_with_obdata(bContext *C, ViewLayer *view_layer = CTX_data_view_layer(C); Object *ob; - /* for as long scene has editmode... */ - if (CTX_data_edit_object(C)) { - ED_object_editmode_exit(C, EM_FREEDATA); + /* For as long scene has editmode... */ + { + Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + if (obedit != NULL) { + ED_object_editmode_exit_ex(bmain, scene, obedit, EM_FREEDATA); + } } /* deselects all, sets active object */ @@ -778,18 +781,20 @@ static int effector_add_exec(bContext *C, wmOperator *op) dia = RNA_float_get(op->ptr, "radius"); if (type == PFIELD_GUIDE) { + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); Curve *cu; ob = ED_object_add_type( C, OB_CURVE, get_effector_defname(type), loc, rot, false, local_view_bits); cu = ob->data; cu->flag |= CU_PATH | CU_3D; - ED_object_editmode_enter(C, 0); + ED_object_editmode_enter_ex(bmain, scene, ob, 0); ED_object_new_primitive_matrix(C, ob, loc, rot, mat); BLI_addtail(&cu->editnurb->nurbs, ED_curve_add_nurbs_primitive(C, ob, mat, CU_NURBS | CU_PRIM_PATH, dia)); if (!enter_editmode) { - ED_object_editmode_exit(C, EM_FREEDATA); + ED_object_editmode_exit_ex(bmain, scene, ob, EM_FREEDATA); } } else { @@ -900,7 +905,10 @@ void OBJECT_OT_camera_add(wmOperatorType *ot) static int object_metaball_add_exec(bContext *C, wmOperator *op) { - Object *obedit = CTX_data_edit_object(C); + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); bool newob = false; bool enter_editmode; ushort local_view_bits; @@ -931,7 +939,7 @@ static int object_metaball_add_exec(bContext *C, wmOperator *op) /* userdef */ if (newob && !enter_editmode) { - ED_object_editmode_exit(C, EM_FREEDATA); + ED_object_editmode_exit_ex(bmain, scene, obedit, EM_FREEDATA); } WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit); @@ -1017,7 +1025,11 @@ void OBJECT_OT_text_add(wmOperatorType *ot) static int object_armature_add_exec(bContext *C, wmOperator *op) { - Object *obedit = CTX_data_edit_object(C); + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + RegionView3D *rv3d = CTX_wm_region_view3d(C); bool newob = false; bool enter_editmode; @@ -1032,7 +1044,7 @@ static int object_armature_add_exec(bContext *C, wmOperator *op) } if ((obedit == NULL) || (obedit->type != OB_ARMATURE)) { obedit = ED_object_add_type(C, OB_ARMATURE, NULL, loc, rot, true, local_view_bits); - ED_object_editmode_enter(C, 0); + ED_object_editmode_enter_ex(bmain, scene, obedit, 0); newob = true; } else { @@ -1049,7 +1061,7 @@ static int object_armature_add_exec(bContext *C, wmOperator *op) /* userdef */ if (newob && !enter_editmode) { - ED_object_editmode_exit(C, EM_FREEDATA); + ED_object_editmode_exit_ex(bmain, scene, obedit, EM_FREEDATA); } WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit); diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index 8b10a865a68..85522209e29 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -80,8 +80,10 @@ /** \name Constraint Data Accessors * \{ */ -/* If object is in posemode, return active bone constraints, else object constraints. No - * constraints are returned for a bone on an inactive bonelayer. */ +/** + * If object is in pose-mode, return active bone constraints, else object constraints. + * No constraints are returned for a bone on an inactive bone-layer. + */ ListBase *ED_object_constraint_active_list(Object *ob) { if (ob == NULL) { @@ -103,8 +105,10 @@ ListBase *ED_object_constraint_active_list(Object *ob) return NULL; } -/* Get the constraints for the active pose bone. Bone may be on an inactive bonelayer (unlike - * ED_object_constraint_active_list, such constraints are not excluded here). */ +/** + * Get the constraints for the active pose bone. Bone may be on an inactive bone-layer + * (unlike #ED_object_constraint_active_list, such constraints are not excluded here). + */ ListBase *ED_object_pose_constraint_list(const bContext *C) { bPoseChannel *pose_bone = CTX_data_pointer_get(C, "active_pose_bone").data; diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 966aeed75ab..7e0df736228 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -769,14 +769,14 @@ bool ED_object_editmode_enter(bContext *C, int flag) static int editmode_toggle_exec(bContext *C, wmOperator *op) { - struct wmMsgBus *mbus = CTX_wm_message_bus(C); - const int mode_flag = OB_MODE_EDIT; - const bool is_mode_set = (CTX_data_edit_object(C) != NULL); Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); + ViewLayer *view_layer = CTX_data_view_layer(C); Object *obact = OBACT(view_layer); + const int mode_flag = OB_MODE_EDIT; + const bool is_mode_set = (obact->mode & mode_flag) != 0; + struct wmMsgBus *mbus = CTX_wm_message_bus(C); if (!is_mode_set) { if (!ED_object_mode_compat_set(C, obact, mode_flag, op->reports)) { @@ -785,7 +785,7 @@ static int editmode_toggle_exec(bContext *C, wmOperator *op) } if (!is_mode_set) { - ED_object_editmode_enter(C, 0); + ED_object_editmode_enter_ex(bmain, scene, obact, 0); if (obact->mode & mode_flag) { FOREACH_SELECTED_OBJECT_BEGIN (view_layer, v3d, ob) { if ((ob != obact) && (ob->type == obact->type)) { @@ -796,7 +796,8 @@ static int editmode_toggle_exec(bContext *C, wmOperator *op) } } else { - ED_object_editmode_exit(C, EM_FREEDATA); + ED_object_editmode_exit_ex(bmain, scene, obact, EM_FREEDATA); + if ((obact->mode & mode_flag) == 0) { FOREACH_OBJECT_BEGIN (view_layer, ob) { if ((ob != obact) && (ob->type == obact->type)) { @@ -859,6 +860,9 @@ void OBJECT_OT_editmode_toggle(wmOperatorType *ot) static int posemode_exec(bContext *C, wmOperator *op) { struct wmMsgBus *mbus = CTX_wm_message_bus(C); + struct Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); Base *base = CTX_data_active_base(C); /* If the base is NULL it means we have an active object, but the object itself is hidden. */ @@ -880,16 +884,17 @@ static int posemode_exec(bContext *C, wmOperator *op) return OPERATOR_PASS_THROUGH; } - if (obact == CTX_data_edit_object(C)) { - ED_object_editmode_exit(C, EM_FREEDATA); - is_mode_set = false; + { + Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + if (obact == obedit) { + ED_object_editmode_exit_ex(bmain, scene, obedit, EM_FREEDATA); + is_mode_set = false; + } } if (is_mode_set) { bool ok = ED_object_posemode_exit(C, obact); if (ok) { - struct Main *bmain = CTX_data_main(C); - ViewLayer *view_layer = CTX_data_view_layer(C); FOREACH_OBJECT_BEGIN (view_layer, ob) { if ((ob != obact) && (ob->type == OB_ARMATURE) && (ob->mode & mode_flag)) { ED_object_posemode_exit_ex(bmain, ob); @@ -901,9 +906,7 @@ static int posemode_exec(bContext *C, wmOperator *op) else { bool ok = ED_object_posemode_enter(C, obact); if (ok) { - struct Main *bmain = CTX_data_main(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - View3D *v3d = CTX_wm_view3d(C); + const View3D *v3d = CTX_wm_view3d(C); FOREACH_SELECTED_OBJECT_BEGIN (view_layer, v3d, ob) { if ((ob != obact) && (ob->type == OB_ARMATURE) && (ob->mode == OB_MODE_OBJECT) && (!ID_IS_LINKED(ob))) { diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 25b4ddc15fd..509097c7a70 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -604,6 +604,7 @@ static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrec ED_draw_imbuf_method(ibuf) != IMAGE_DRAW_METHOD_GLSL) { image_buffer_rect_update(rj, rr, ibuf, &rj->iuser, renrect, viewname); } + ima->gpuflag |= IMA_GPU_REFRESH; /* make jobs timer to send notifier */ *(rj->do_update) = true; diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index 058436a46bf..85d153feb4c 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -865,7 +865,7 @@ void draw_image_main(const bContext *C, ARegion *region) Image *ima; ImBuf *ibuf; float zoomx, zoomy; - bool show_viewer, show_render, show_paint, show_stereo3d, show_multilayer; + bool show_viewer, show_stereo3d, show_multilayer; void *lock; /* XXX can we do this in refresh? */ @@ -898,9 +898,6 @@ void draw_image_main(const bContext *C, ARegion *region) } show_viewer = (ima && ima->source == IMA_SRC_VIEWER) != 0; - show_render = (show_viewer && ima->type == IMA_TYPE_R_RESULT) != 0; - show_paint = (ima && (sima->mode == SI_MODE_PAINT) && (show_viewer == false) && - (show_render == false)); show_stereo3d = (ima && BKE_image_is_stereo(ima) && (sima->iuser.flag & IMA_SHOW_STEREO)); show_multilayer = ima && BKE_image_is_multilayer(ima); @@ -998,16 +995,32 @@ void draw_image_main(const bContext *C, ARegion *region) } draw_udim_tile_grids(region, sima, ima); - - /* paint helpers */ - if (show_paint) { - draw_image_paint_helpers(C, region, scene, zoomx, zoomy); - } + draw_image_main_helpers(C, region); if (show_viewer) { BLI_thread_unlock(LOCK_DRAW_IMAGE); } +} + +void draw_image_main_helpers(const bContext *C, ARegion *region) +{ + SpaceImage *sima = CTX_wm_space_image(C); + Scene *scene = CTX_data_scene(C); + Image *ima; + float zoomx, zoomy; + bool show_viewer, show_render, show_paint; + ima = ED_space_image(sima); + ED_space_image_get_zoom(sima, region, &zoomx, &zoomy); + + show_viewer = (ima && ima->source == IMA_SRC_VIEWER) != 0; + show_render = (show_viewer && ima->type == IMA_TYPE_R_RESULT) != 0; + show_paint = (ima && (sima->mode == SI_MODE_PAINT) && (show_viewer == false) && + (show_render == false)); + /* paint helpers */ + if (show_paint) { + draw_image_paint_helpers(C, region, scene, zoomx, zoomy); + } /* render info */ if (ima && show_render) { draw_render_info(C, sima->iuser.scene, ima, region, zoomx, zoomy); diff --git a/source/blender/editors/space_image/image_intern.h b/source/blender/editors/space_image/image_intern.h index e6f5988aed8..100556ad29a 100644 --- a/source/blender/editors/space_image/image_intern.h +++ b/source/blender/editors/space_image/image_intern.h @@ -37,6 +37,7 @@ extern const char *image_context_dir[]; /* doc access */ /* image_draw.c */ void draw_image_main(const struct bContext *C, struct ARegion *region); +void draw_image_main_helpers(const struct bContext *C, struct ARegion *region); void draw_image_cache(const struct bContext *C, struct ARegion *region); void draw_image_grease_pencil(struct bContext *C, bool onlyv2d); void draw_image_sample_line(struct SpaceImage *sima); diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index aa3f6446d51..f1becd5f027 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -76,6 +76,7 @@ #include "GPU_framebuffer.h" #include "GPU_viewport.h" +#include "DRW_engine.h" #include "DRW_engine_types.h" #include "image_intern.h" @@ -638,8 +639,6 @@ static void image_main_region_draw(const bContext *C, ARegion *region) Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); View2D *v2d = ®ion->v2d; - // View2DScrollers *scrollers; - float col[3]; GPUViewport *viewport = WM_draw_region_get_viewport(region); GPUFrameBuffer *framebuffer_default, *framebuffer_overlay; @@ -647,35 +646,14 @@ static void image_main_region_draw(const bContext *C, ARegion *region) framebuffer_default = GPU_viewport_framebuffer_default_get(viewport); framebuffer_overlay = GPU_viewport_framebuffer_overlay_get(viewport); - GPU_framebuffer_bind(framebuffer_default); - GPU_clear_color(0.0f, 0.0f, 0.0f, 0.0f); - - GPU_framebuffer_bind(framebuffer_overlay); - /* XXX not supported yet, disabling for now */ scene->r.scemode &= ~R_COMP_CROP; - /* clear and setup matrix */ - UI_GetThemeColor3fv(TH_BACK, col); - srgb_to_linearrgb_v3_v3(col, col); - GPU_clear_color(col[0], col[1], col[2], 1.0f); - GPU_depth_test(GPU_DEPTH_NONE); - image_user_refresh_scene(C, sima); /* we set view2d from own zoom and offset each time */ image_main_region_set_view2d(sima, region); - /* we draw image in pixelspace */ - draw_image_main(C, region); - - /* and uvs in 0.0-1.0 space */ - UI_view2d_view_ortho(v2d); - - ED_region_draw_cb_draw(C, region, REGION_DRAW_PRE_VIEW); - - ED_uvedit_draw_main(sima, scene, view_layer, obedit, obact, depsgraph); - /* check for mask (delay draw) */ if (ED_space_image_show_uvedit(sima, obedit)) { show_uvedit = true; @@ -687,21 +665,52 @@ static void image_main_region_draw(const bContext *C, ARegion *region) show_curve = true; } - ED_region_draw_cb_draw(C, region, REGION_DRAW_POST_VIEW); + /* we draw image in pixelspace */ + if (!U.experimental.use_image_editor_legacy_drawing) { + DRW_draw_view(C); + draw_image_main_helpers(C, region); - if (sima->flag & SI_SHOW_GPENCIL) { - /* Grease Pencil too (in addition to UV's) */ - draw_image_grease_pencil((bContext *)C, true); + /* sample line */ + UI_view2d_view_ortho(v2d); + draw_image_sample_line(sima); + UI_view2d_view_restore(C); } + else { + GPU_framebuffer_bind(framebuffer_default); + GPU_clear_color(0.0f, 0.0f, 0.0f, 0.0f); + + GPU_framebuffer_bind(framebuffer_overlay); + + float col[3]; + /* clear and setup matrix */ + UI_GetThemeColor3fv(TH_BACK, col); + srgb_to_linearrgb_v3_v3(col, col); + GPU_clear_color(col[0], col[1], col[2], 1.0f); + GPU_depth_test(GPU_DEPTH_NONE); + draw_image_main(C, region); + + /* and uvs in 0.0-1.0 space */ + UI_view2d_view_ortho(v2d); + + ED_region_draw_cb_draw(C, region, REGION_DRAW_PRE_VIEW); - /* sample line */ - draw_image_sample_line(sima); + ED_uvedit_draw_main(sima, scene, view_layer, obedit, obact, depsgraph); - UI_view2d_view_restore(C); + ED_region_draw_cb_draw(C, region, REGION_DRAW_POST_VIEW); - if (sima->flag & SI_SHOW_GPENCIL) { - /* draw Grease Pencil - screen space only */ - draw_image_grease_pencil((bContext *)C, false); + if (sima->flag & SI_SHOW_GPENCIL) { + /* Grease Pencil too (in addition to UV's) */ + draw_image_grease_pencil((bContext *)C, true); + } + /* sample line */ + draw_image_sample_line(sima); + + UI_view2d_view_restore(C); + + if (sima->flag & SI_SHOW_GPENCIL) { + /* draw Grease Pencil - screen space only */ + draw_image_grease_pencil((bContext *)C, false); + } } if (mask) { @@ -741,7 +750,7 @@ static void image_main_region_draw(const bContext *C, ARegion *region) C); } - if (show_uvedit || mask || show_curve) { + if ((show_uvedit || mask || show_curve) && U.experimental.use_image_editor_legacy_drawing) { UI_view2d_view_ortho(v2d); ED_image_draw_cursor(region, sima->cursor); UI_view2d_view_restore(C); diff --git a/source/blender/gpu/opengl/gl_debug.cc b/source/blender/gpu/opengl/gl_debug.cc index de88fdc154c..db99e90d0ec 100644 --- a/source/blender/gpu/opengl/gl_debug.cc +++ b/source/blender/gpu/opengl/gl_debug.cc @@ -243,7 +243,7 @@ void raise_gl_error(const char *info) /* -------------------------------------------------------------------- */ /** \name Object Label * - * Useful for debugging through renderdoc. Only defined if using --debug-gpu. + * Useful for debugging through render-doc. Only defined if using `--debug-gpu`. * Make sure to bind the object first so that it gets defined by the GL implementation. * \{ */ diff --git a/source/blender/makesdna/DNA_image_defaults.h b/source/blender/makesdna/DNA_image_defaults.h index ce1296d681f..93ff8792dfa 100644 --- a/source/blender/makesdna/DNA_image_defaults.h +++ b/source/blender/makesdna/DNA_image_defaults.h @@ -36,6 +36,8 @@ .gen_type = IMA_GENTYPE_GRID, \ \ .gpuframenr = INT_MAX, \ + .gpu_pass = SHRT_MAX, \ + .gpu_layer = SHRT_MAX, \ } /** \} */ diff --git a/source/blender/makesdna/DNA_image_types.h b/source/blender/makesdna/DNA_image_types.h index 749bc55fcb9..4a05d7ba319 100644 --- a/source/blender/makesdna/DNA_image_types.h +++ b/source/blender/makesdna/DNA_image_types.h @@ -147,9 +147,11 @@ typedef struct Image { int lastframe; /* GPU texture flag. */ - short gpuflag; - char _pad2[2]; int gpuframenr; + short gpuflag; + short gpu_pass; + short gpu_layer; + char _pad2[6]; /** Deprecated. */ struct PackedFile *packedfile DNA_DEPRECATED; diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 589077ea67b..b63f4529559 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -620,9 +620,10 @@ typedef struct UserDef_Experimental { char use_new_hair_type; char use_cycles_debug; char use_sculpt_vertex_colors; + char use_image_editor_legacy_drawing; char use_tools_missing_icons; /** `makesdna` does not allow empty structs. */ - char _pad[2]; + char _pad[1]; } UserDef_Experimental; #define USER_EXPERIMENTAL_TEST(userdef, member) \ diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index eab6349317a..13b068c2be5 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -243,35 +243,87 @@ static void rna_ParticleHairKey_location_object_get(PointerRNA *ptr, float *valu } } +/* Helper function which returns index of the given hair_key in particle which owns it. + * Works with cases when hair_key is coming from the particle which was passed here, and from the + * original particle of the given one. + * + * Such trickery is needed to allow modification of hair keys in the original object using + * evaluated particle and object to access proper hair matrix. */ +static int hair_key_index_get(/*const*/ HairKey *hair_key, + /*const*/ ParticleSystemModifierData *modifier, + /*const*/ ParticleData *particle) +{ + if (ARRAY_HAS_ITEM(hair_key, particle->hair, particle->totkey)) { + return hair_key - particle->hair; + } + + const ParticleSystem *particle_system = modifier->psys; + const int particle_index = particle - particle_system->particles; + + const ParticleSystemModifierData *original_modifier = (ParticleSystemModifierData *) + BKE_modifier_get_original(&modifier->modifier); + const ParticleSystem *original_particle_system = original_modifier->psys; + const ParticleData *original_particle = &original_particle_system->particles[particle_index]; + + if (ARRAY_HAS_ITEM(hair_key, original_particle->hair, original_particle->totkey)) { + return hair_key - original_particle->hair; + } + + return -1; +} + +/* Set hair_key->co to the given coordinate in object space (the given coordinate will be + * converted to the proper space). + * + * The hair_key can be coming from both original and evaluated object. Object, modifier and + * particle are to be from evaluated object, so that all the data needed for hair matrix is + * present. */ +static void hair_key_location_object_set(HairKey *hair_key, + Object *object, + ParticleSystemModifierData *modifier, + ParticleData *particle, + const float src_co[3]) +{ + Mesh *hair_mesh = (modifier->psys->flag & PSYS_HAIR_DYNAMICS) ? modifier->psys->hair_out_mesh : + NULL; + + if (hair_mesh != NULL) { + const int hair_key_index = hair_key_index_get(hair_key, modifier, particle); + if (hair_key_index == -1) { + return; + } + + MVert *mvert = &hair_mesh->mvert[particle->hair_index + (hair_key_index)]; + copy_v3_v3(mvert->co, src_co); + return; + } + + float hairmat[4][4]; + psys_mat_hair_to_object( + object, modifier->mesh_final, modifier->psys->part->from, particle, hairmat); + + float imat[4][4]; + invert_m4_m4(imat, hairmat); + + copy_v3_v3(hair_key->co, src_co); + mul_m4_v3(imat, hair_key->co); +} + static void rna_ParticleHairKey_location_object_set(PointerRNA *ptr, const float *values) { HairKey *hkey = (HairKey *)ptr->data; Object *ob = (Object *)ptr->owner_id; + ParticleSystemModifierData *psmd; ParticleData *pa; - rna_ParticleHairKey_location_object_info(ptr, &psmd, &pa); - if (pa) { - Mesh *hair_mesh = (psmd->psys->flag & PSYS_HAIR_DYNAMICS) ? psmd->psys->hair_out_mesh : NULL; - - if (hair_mesh) { - MVert *mvert = &hair_mesh->mvert[pa->hair_index + (hkey - pa->hair)]; - copy_v3_v3(mvert->co, values); - } - else { - float hairmat[4][4]; - float imat[4][4]; - - psys_mat_hair_to_object(ob, psmd->mesh_final, psmd->psys->part->from, pa, hairmat); - invert_m4_m4(imat, hairmat); - copy_v3_v3(hkey->co, values); - mul_m4_v3(imat, hkey->co); - } - } - else { + if (pa == NULL) { zero_v3(hkey->co); + return; } + + hair_key_location_object_set(hkey, ob, psmd, pa, values); } static void rna_ParticleHairKey_co_object(HairKey *hairkey, @@ -301,6 +353,31 @@ static void rna_ParticleHairKey_co_object(HairKey *hairkey, } } +static void rna_ParticleHairKey_co_object_set(ID *id, + HairKey *hair_key, + Object *object, + ParticleSystemModifierData *modifier, + ParticleData *particle, + float co[3]) +{ + + if (particle == NULL) { + return; + } + + /* Mark particle system as edited, so then particle_system_update() does not reset the hair + * keys from path. This behavior is similar to how particle edit mode sets flags. */ + ParticleSystemModifierData *orig_modifier = (ParticleSystemModifierData *) + modifier->modifier.orig_modifier_data; + orig_modifier->psys->flag |= PSYS_EDITED; + + hair_key_location_object_set(hair_key, object, modifier, particle, co); + + /* Tag similar to brushes in particle edit mode, so the modifier stack is properly evaluated + * with the same particle system recalc flags as during combing. */ + DEG_id_tag_update(id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_REDO); +} + static void rna_Particle_uv_on_emitter(ParticleData *particle, ReportList *reports, ParticleSystemModifierData *modifier, @@ -1651,6 +1728,19 @@ static void rna_def_particle_hair_key(BlenderRNA *brna) func, "co", 3, NULL, -FLT_MAX, FLT_MAX, "Co", "Exported hairkey location", -1e4, 1e4); RNA_def_parameter_flags(parm, PROP_THICK_WRAP, 0); RNA_def_function_output(func, parm); + + func = RNA_def_function(srna, "co_object_set", "rna_ParticleHairKey_co_object_set"); + RNA_def_function_flag(func, FUNC_USE_SELF_ID); + RNA_def_function_ui_description(func, "Set hairkey location with particle and modifier data"); + parm = RNA_def_pointer(func, "object", "Object", "", "Object"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_pointer(func, "modifier", "ParticleSystemModifier", "", "Particle modifier"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_pointer(func, "particle", "Particle", "", "hair particle"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_float_vector( + func, "co", 3, NULL, -FLT_MAX, FLT_MAX, "Co", "Specified hairkey location", -1e4, 1e4); + RNA_def_parameter_flags(parm, PROP_THICK_WRAP, PARM_REQUIRED); } static void rna_def_particle_key(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 66d7685b3a6..794b516489a 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -2971,10 +2971,10 @@ static void rna_def_space_outliner(BlenderRNA *brna) "View Layer", "Display collections and objects in the view layer"}, {SO_SEQUENCE, - "SEQUENCE", - ICON_SEQUENCE, - "Video Sequencer", - "Display data belonging to the Video Sequencer"}, + "SEQUENCE", + ICON_SEQUENCE, + "Video Sequencer", + "Display data belonging to the Video Sequencer"}, {SO_LIBRARIES, "LIBRARIES", ICON_FILE_BLEND, diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 10e3f9c86ee..1ecd0a581b6 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -3061,6 +3061,11 @@ static void rna_def_userdef_theme_space_image(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Metadata Text", ""); RNA_def_property_update(prop, 0, "rna_userdef_theme_update"); + prop = RNA_def_property(srna, "grid", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_array(prop, 4); + RNA_def_property_ui_text(prop, "Grid", ""); + RNA_def_property_update(prop, 0, "rna_userdef_theme_update"); + rna_def_userdef_theme_spaces_curves(srna, false, false, false, true); rna_def_userdef_theme_spaces_paint_curves(srna); @@ -6118,6 +6123,11 @@ static void rna_def_userdef_experimental(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "use_sculpt_vertex_colors", 1); RNA_def_property_ui_text(prop, "Sculpt Vertex Colors", "Use the new Vertex Painting system"); + prop = RNA_def_property(srna, "use_image_editor_legacy_drawing", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "use_image_editor_legacy_drawing", 1); + RNA_def_property_ui_text( + prop, "Legacy Image Editor Drawing", "Use legacy UV/Image editor drawing"); + prop = RNA_def_property(srna, "use_tools_missing_icons", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "use_tools_missing_icons", 1); RNA_def_property_ui_text(prop, "Tools with Missing Icons", "Show tools with missing icons"); diff --git a/source/blender/modifiers/intern/MOD_meshcache_mdd.c b/source/blender/modifiers/intern/MOD_meshcache_mdd.c index cb150976ff5..d216c14ab43 100644 --- a/source/blender/modifiers/intern/MOD_meshcache_mdd.c +++ b/source/blender/modifiers/intern/MOD_meshcache_mdd.c @@ -65,13 +65,13 @@ static bool meshcache_read_mdd_head(FILE *fp, *err_str = "Invalid frame total"; return false; } - /* intentionally dont seek back */ + /* Intentionally don't seek back. */ return true; } /** - * Gets the index frange and factor + * Gets the index range and factor. */ static bool meshcache_read_mdd_range(FILE *fp, const int verts_tot, diff --git a/source/blender/python/gpu/gpu_py_shader.c b/source/blender/python/gpu/gpu_py_shader.c index f9ff0558570..55753e91f14 100644 --- a/source/blender/python/gpu/gpu_py_shader.c +++ b/source/blender/python/gpu/gpu_py_shader.c @@ -607,12 +607,12 @@ PyDoc_STRVAR( " ``GL_ARB_texture_gather``, ``GL_ARB_texture_cube_map_array`` and " "``GL_ARB_shader_draw_parameters``.\n" "\n" - " To debug shaders, use the --debug-gpu-shaders command line option" - " to see full GLSL shader compilation and linking errors.\n" + " To debug shaders, use the ``--debug-gpu-shaders`` command line option " + "to see full GLSL shader compilation and linking errors.\n" "\n" " For drawing user interface elements and gizmos, use " - " ``fragOutput = blender_srgb_to_framebuffer_space(fragOutput)``" - " to transform the output sRGB colors to the framebuffer colorspace." + "``fragOutput = blender_srgb_to_framebuffer_space(fragOutput)`` " + "to transform the output sRGB colors to the frame-buffer color-space." "\n" " :param vertexcode: Vertex shader code.\n" " :type vertexcode: str\n" diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index b85bf8cb323..5a22e990218 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -190,8 +190,6 @@ void WM_init_opengl(void) GPU_pass_cache_init(); - BKE_subdiv_init(); - opengl_is_init = true; } @@ -323,6 +321,8 @@ void WM_init(bContext *C, int argc, const char **argv) UI_init(); } + BKE_subdiv_init(); + ED_spacemacros_init(); /* note: there is a bug where python needs initializing before loading the |