diff options
Diffstat (limited to 'source/blender/editors/space_spreadsheet/space_spreadsheet.cc')
-rw-r--r-- | source/blender/editors/space_spreadsheet/space_spreadsheet.cc | 251 |
1 files changed, 174 insertions, 77 deletions
diff --git a/source/blender/editors/space_spreadsheet/space_spreadsheet.cc b/source/blender/editors/space_spreadsheet/space_spreadsheet.cc index 8dbb4a2ee0c..c546a371ef0 100644 --- a/source/blender/editors/space_spreadsheet/space_spreadsheet.cc +++ b/source/blender/editors/space_spreadsheet/space_spreadsheet.cc @@ -10,6 +10,7 @@ #include "ED_screen.h" #include "ED_space_api.h" #include "ED_spreadsheet.h" +#include "ED_viewer_path.hh" #include "DNA_scene_types.h" #include "DNA_screen_types.h" @@ -21,6 +22,8 @@ #include "UI_resources.h" #include "UI_view2d.h" +#include "BLO_read_write.h" + #include "DEG_depsgraph_query.h" #include "RNA_access.h" @@ -32,7 +35,6 @@ #include "BLF_api.h" -#include "spreadsheet_context.hh" #include "spreadsheet_data_source_geometry.hh" #include "spreadsheet_dataset_draw.hh" #include "spreadsheet_intern.hh" @@ -43,7 +45,7 @@ using namespace blender; using namespace blender::ed::spreadsheet; -static SpaceLink *spreadsheet_create(const ScrArea *UNUSED(area), const Scene *UNUSED(scene)) +static SpaceLink *spreadsheet_create(const ScrArea * /*area*/, const Scene * /*scene*/) { SpaceSpreadsheet *spreadsheet_space = MEM_cnew<SpaceSpreadsheet>("spreadsheet space"); spreadsheet_space->spacetype = SPACE_SPREADSHEET; @@ -105,12 +107,10 @@ static void spreadsheet_free(SpaceLink *sl) LISTBASE_FOREACH_MUTABLE (SpreadsheetColumn *, column, &sspreadsheet->columns) { spreadsheet_column_free(column); } - LISTBASE_FOREACH_MUTABLE (SpreadsheetContext *, context, &sspreadsheet->context_path) { - spreadsheet_context_free(context); - } + BKE_viewer_path_clear(&sspreadsheet->viewer_path); } -static void spreadsheet_init(wmWindowManager *UNUSED(wm), ScrArea *area) +static void spreadsheet_init(wmWindowManager * /*wm*/, ScrArea *area) { SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)area->spacedata.first; if (sspreadsheet->runtime == nullptr) { @@ -141,11 +141,7 @@ static SpaceLink *spreadsheet_duplicate(SpaceLink *sl) BLI_addtail(&sspreadsheet_new->columns, new_column); } - BLI_listbase_clear(&sspreadsheet_new->context_path); - LISTBASE_FOREACH_MUTABLE (SpreadsheetContext *, src_context, &sspreadsheet_old->context_path) { - SpreadsheetContext *new_context = spreadsheet_context_copy(src_context); - BLI_addtail(&sspreadsheet_new->context_path, new_context); - } + BKE_viewer_path_copy(&sspreadsheet_new->viewer_path, &sspreadsheet_old->viewer_path); return (SpaceLink *)sspreadsheet_new; } @@ -156,24 +152,10 @@ static void spreadsheet_keymap(wmKeyConfig *keyconf) WM_keymap_ensure(keyconf, "Spreadsheet Generic", SPACE_SPREADSHEET, 0); } -static void spreadsheet_id_remap(ScrArea *UNUSED(area), - SpaceLink *slink, - const IDRemapper *mappings) +static void spreadsheet_id_remap(ScrArea * /*area*/, SpaceLink *slink, const IDRemapper *mappings) { SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)slink; - LISTBASE_FOREACH (SpreadsheetContext *, context, &sspreadsheet->context_path) { - if (context->type != SPREADSHEET_CONTEXT_OBJECT) { - continue; - } - SpreadsheetContextObject *object_context = (SpreadsheetContextObject *)context; - - if (object_context->object != nullptr && GS(object_context->object->id.name) != ID_OB) { - object_context->object = nullptr; - continue; - } - - BKE_id_remapper_apply(mappings, ((ID **)&object_context->object), ID_REMAP_APPLY_DEFAULT); - } + BKE_viewer_path_id_remap(&sspreadsheet->viewer_path, mappings); } static void spreadsheet_main_region_init(wmWindowManager *wm, ARegion *region) @@ -199,54 +181,101 @@ static void spreadsheet_main_region_init(wmWindowManager *wm, ARegion *region) ID *ED_spreadsheet_get_current_id(const struct SpaceSpreadsheet *sspreadsheet) { - if (BLI_listbase_is_empty(&sspreadsheet->context_path)) { + if (BLI_listbase_is_empty(&sspreadsheet->viewer_path.path)) { return nullptr; } - SpreadsheetContext *root_context = (SpreadsheetContext *)sspreadsheet->context_path.first; - if (root_context->type != SPREADSHEET_CONTEXT_OBJECT) { + ViewerPathElem *root_context = static_cast<ViewerPathElem *>( + sspreadsheet->viewer_path.path.first); + if (root_context->type != VIEWER_PATH_ELEM_TYPE_ID) { return nullptr; } - SpreadsheetContextObject *object_context = (SpreadsheetContextObject *)root_context; - return (ID *)object_context->object; + IDViewerPathElem *id_elem = reinterpret_cast<IDViewerPathElem *>(root_context); + return id_elem->id; } -/* Check if the pinned context still exists. If it doesn't try to find a new context. */ -static void update_pinned_context_path_if_outdated(const bContext *C) +static void view_active_object(const bContext *C, SpaceSpreadsheet *sspreadsheet) { - SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C); - Main *bmain = CTX_data_main(C); - if (!ED_spreadsheet_context_path_exists(bmain, sspreadsheet)) { - ED_spreadsheet_context_path_guess(C, sspreadsheet); - if (ED_spreadsheet_context_path_update_tag(sspreadsheet)) { - ED_area_tag_redraw(CTX_wm_area(C)); - } - } - - if (BLI_listbase_is_empty(&sspreadsheet->context_path)) { - /* Don't pin empty context_path, that could be annoying. */ - sspreadsheet->flag &= ~SPREADSHEET_FLAG_PINNED; + BKE_viewer_path_clear(&sspreadsheet->viewer_path); + Object *ob = CTX_data_active_object(C); + if (ob == nullptr) { + return; } + IDViewerPathElem *id_elem = BKE_viewer_path_elem_new_id(); + id_elem->id = &ob->id; + BLI_addtail(&sspreadsheet->viewer_path.path, id_elem); + ED_area_tag_redraw(CTX_wm_area(C)); } -static void update_context_path_from_context(const bContext *C) +static void spreadsheet_update_context(const bContext *C) { + using blender::ed::viewer_path::ViewerPathForGeometryNodesViewer; + SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C); - if (!ED_spreadsheet_context_path_is_active(C, sspreadsheet)) { - ED_spreadsheet_context_path_guess(C, sspreadsheet); - if (ED_spreadsheet_context_path_update_tag(sspreadsheet)) { - ED_area_tag_redraw(CTX_wm_area(C)); + Object *active_object = CTX_data_active_object(C); + Object *context_object = blender::ed::viewer_path::parse_object_only(sspreadsheet->viewer_path); + switch (eSpaceSpreadsheet_ObjectEvalState(sspreadsheet->object_eval_state)) { + case SPREADSHEET_OBJECT_EVAL_STATE_ORIGINAL: + case SPREADSHEET_OBJECT_EVAL_STATE_EVALUATED: { + if (sspreadsheet->flag & SPREADSHEET_FLAG_PINNED) { + if (context_object == nullptr) { + /* Object is not available anymore, so clear the pinning. */ + sspreadsheet->flag &= ~SPREADSHEET_FLAG_PINNED; + } + else { + /* The object is still pinned, do nothing. */ + break; + } + } + else { + if (active_object != context_object) { + /* The active object has changed, so view the new active object. */ + view_active_object(C, sspreadsheet); + } + else { + /* Nothing changed. */ + break; + } + } + break; } - } -} + case SPREADSHEET_OBJECT_EVAL_STATE_VIEWER_NODE: { + WorkSpace *workspace = CTX_wm_workspace(C); + if (sspreadsheet->flag & SPREADSHEET_FLAG_PINNED) { + const std::optional<ViewerPathForGeometryNodesViewer> parsed_path = + blender::ed::viewer_path::parse_geometry_nodes_viewer(sspreadsheet->viewer_path); + if (parsed_path.has_value()) { + if (blender::ed::viewer_path::exists_geometry_nodes_viewer(*parsed_path)) { + /* The pinned path is still valid, do nothing. */ + break; + } + /* The pinned path does not exist anymore, clear pinning. */ + sspreadsheet->flag &= ~SPREADSHEET_FLAG_PINNED; + } + else { + /* Unknown pinned path, clear pinning. */ + sspreadsheet->flag &= ~SPREADSHEET_FLAG_PINNED; + } + } + /* Now try to update the viewer path from the workspace. */ + const std::optional<ViewerPathForGeometryNodesViewer> workspace_parsed_path = + blender::ed::viewer_path::parse_geometry_nodes_viewer(workspace->viewer_path); + if (workspace_parsed_path.has_value()) { + if (BKE_viewer_path_equal(&sspreadsheet->viewer_path, &workspace->viewer_path)) { + /* Nothing changed. */ + break; + } + /* Update the viewer path from the workspace. */ + BKE_viewer_path_clear(&sspreadsheet->viewer_path); + BKE_viewer_path_copy(&sspreadsheet->viewer_path, &workspace->viewer_path); + } + else { + /* No active viewer node, change back to showing evaluated active object. */ + sspreadsheet->object_eval_state = SPREADSHEET_OBJECT_EVAL_STATE_EVALUATED; + view_active_object(C, sspreadsheet); + } -void spreadsheet_update_context_path(const bContext *C) -{ - SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C); - if (sspreadsheet->flag & SPREADSHEET_FLAG_PINNED) { - update_pinned_context_path_if_outdated(C); - } - else { - update_context_path_from_context(C); + break; + } } } @@ -327,7 +356,7 @@ static float get_column_width(const ColumnValues &values) { float data_width = get_default_column_width(values); const int fontid = UI_style_get()->widget.uifont_id; - BLF_size(fontid, UI_DEFAULT_TEXT_POINTS, U.dpi); + BLF_size(fontid, UI_DEFAULT_TEXT_POINTS * U.dpi_fac); const StringRefNull name = values.name(); const float name_width = BLF_width(fontid, name.data(), name.size()); return std::max<float>(name_width / UI_UNIT_X + 1.0f, data_width); @@ -341,7 +370,7 @@ static float get_column_width_in_pixels(const ColumnValues &values) static int get_index_column_width(const int tot_rows) { const int fontid = UI_style_get()->widget.uifont_id; - BLF_size(fontid, UI_style_get_dpi()->widget.points * U.pixelsize, U.dpi); + BLF_size(fontid, UI_style_get_dpi()->widget.points * U.dpi_fac); return std::to_string(std::max(0, tot_rows - 1)).size() * BLF_width(fontid, "0", 1) + UI_UNIT_X * 0.75; } @@ -388,7 +417,7 @@ static void spreadsheet_main_region_draw(const bContext *C, ARegion *region) { SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C); sspreadsheet->runtime->cache.set_all_unused(); - spreadsheet_update_context_path(C); + spreadsheet_update_context(C); std::unique_ptr<DataSource> data_source = get_data_source(C); if (!data_source) { @@ -436,7 +465,8 @@ static void spreadsheet_main_region_draw(const bContext *C, ARegion *region) static void spreadsheet_main_region_listener(const wmRegionListenerParams *params) { ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; + SpaceSpreadsheet *sspreadsheet = static_cast<SpaceSpreadsheet *>(params->area->spacedata.first); switch (wmn->category) { case NC_SCENE: { @@ -465,28 +495,35 @@ static void spreadsheet_main_region_listener(const wmRegionListenerParams *param ED_region_tag_redraw(region); break; } + case NC_VIEWER_PATH: { + if (sspreadsheet->object_eval_state == SPREADSHEET_OBJECT_EVAL_STATE_VIEWER_NODE) { + ED_region_tag_redraw(region); + } + break; + } } } -static void spreadsheet_header_region_init(wmWindowManager *UNUSED(wm), ARegion *region) +static void spreadsheet_header_region_init(wmWindowManager * /*wm*/, ARegion *region) { ED_region_header_init(region); } static void spreadsheet_header_region_draw(const bContext *C, ARegion *region) { - spreadsheet_update_context_path(C); + spreadsheet_update_context(C); ED_region_header(C, region); } -static void spreadsheet_header_region_free(ARegion *UNUSED(region)) +static void spreadsheet_header_region_free(ARegion * /*region*/) { } static void spreadsheet_header_region_listener(const wmRegionListenerParams *params) { ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; + SpaceSpreadsheet *sspreadsheet = static_cast<SpaceSpreadsheet *>(params->area->spacedata.first); switch (wmn->category) { case NC_SCENE: { @@ -513,10 +550,16 @@ static void spreadsheet_header_region_listener(const wmRegionListenerParams *par ED_region_tag_redraw(region); break; } + case NC_VIEWER_PATH: { + if (sspreadsheet->object_eval_state == SPREADSHEET_OBJECT_EVAL_STATE_VIEWER_NODE) { + ED_region_tag_redraw(region); + } + break; + } } } -static void spreadsheet_footer_region_init(wmWindowManager *UNUSED(wm), ARegion *region) +static void spreadsheet_footer_region_init(wmWindowManager * /*wm*/, ARegion *region) { ED_region_header_init(region); } @@ -559,18 +602,18 @@ static void spreadsheet_footer_region_draw(const bContext *C, ARegion *region) UI_block_draw(C, block); } -static void spreadsheet_footer_region_free(ARegion *UNUSED(region)) +static void spreadsheet_footer_region_free(ARegion * /*region*/) { } -static void spreadsheet_footer_region_listener(const wmRegionListenerParams *UNUSED(params)) +static void spreadsheet_footer_region_listener(const wmRegionListenerParams * /*params*/) { } static void spreadsheet_dataset_region_listener(const wmRegionListenerParams *params) { ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; switch (wmn->category) { case NC_SCENE: { @@ -591,7 +634,7 @@ static void spreadsheet_dataset_region_listener(const wmRegionListenerParams *pa static void spreadsheet_dataset_region_draw(const bContext *C, ARegion *region) { - spreadsheet_update_context_path(C); + spreadsheet_update_context(C); ED_region_panels(C, region); } @@ -605,21 +648,72 @@ static void spreadsheet_sidebar_init(wmWindowManager *wm, ARegion *region) WM_event_add_keymap_handler(®ion->handlers, keymap); } -static void spreadsheet_right_region_free(ARegion *UNUSED(region)) +static void spreadsheet_right_region_free(ARegion * /*region*/) { } -static void spreadsheet_right_region_listener(const wmRegionListenerParams *UNUSED(params)) +static void spreadsheet_right_region_listener(const wmRegionListenerParams * /*params*/) { } +static void spreadsheet_blend_read_data(BlendDataReader *reader, SpaceLink *sl) +{ + SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)sl; + + sspreadsheet->runtime = nullptr; + BLO_read_list(reader, &sspreadsheet->row_filters); + LISTBASE_FOREACH (SpreadsheetRowFilter *, row_filter, &sspreadsheet->row_filters) { + BLO_read_data_address(reader, &row_filter->value_string); + } + BLO_read_list(reader, &sspreadsheet->columns); + LISTBASE_FOREACH (SpreadsheetColumn *, column, &sspreadsheet->columns) { + BLO_read_data_address(reader, &column->id); + BLO_read_data_address(reader, &column->id->name); + /* While the display name is technically runtime data, it is loaded here, otherwise the row + * filters might not now their type if their region draws before the main region. + * This would ideally be cleared here. */ + BLO_read_data_address(reader, &column->display_name); + } + + BKE_viewer_path_blend_read_data(reader, &sspreadsheet->viewer_path); +} + +static void spreadsheet_blend_read_lib(BlendLibReader *reader, ID *parent_id, SpaceLink *sl) +{ + SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)sl; + BKE_viewer_path_blend_read_lib(reader, parent_id->lib, &sspreadsheet->viewer_path); +} + +static void spreadsheet_blend_write(BlendWriter *writer, SpaceLink *sl) +{ + BLO_write_struct(writer, SpaceSpreadsheet, sl); + SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)sl; + + LISTBASE_FOREACH (SpreadsheetRowFilter *, row_filter, &sspreadsheet->row_filters) { + BLO_write_struct(writer, SpreadsheetRowFilter, row_filter); + BLO_write_string(writer, row_filter->value_string); + } + + LISTBASE_FOREACH (SpreadsheetColumn *, column, &sspreadsheet->columns) { + BLO_write_struct(writer, SpreadsheetColumn, column); + BLO_write_struct(writer, SpreadsheetColumnID, column->id); + BLO_write_string(writer, column->id->name); + /* While the display name is technically runtime data, we write it here, otherwise the row + * filters might not now their type if their region draws before the main region. + * This would ideally be cleared here. */ + BLO_write_string(writer, column->display_name); + } + + BKE_viewer_path_blend_write(writer, &sspreadsheet->viewer_path); +} + void ED_spacetype_spreadsheet() { SpaceType *st = MEM_cnew<SpaceType>("spacetype spreadsheet"); ARegionType *art; st->spaceid = SPACE_SPREADSHEET; - strncpy(st->name, "Spreadsheet", BKE_ST_MAXNAME); + STRNCPY(st->name, "Spreadsheet"); st->create = spreadsheet_create; st->free = spreadsheet_free; @@ -628,6 +722,9 @@ void ED_spacetype_spreadsheet() st->operatortypes = spreadsheet_operatortypes; st->keymap = spreadsheet_keymap; st->id_remap = spreadsheet_id_remap; + st->blend_read_data = spreadsheet_blend_read_data; + st->blend_read_lib = spreadsheet_blend_read_lib; + st->blend_write = spreadsheet_blend_write; /* regions: main window */ art = MEM_cnew<ARegionType>("spacetype spreadsheet region"); |