Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/space_spreadsheet/space_spreadsheet.cc
| Show All 16 Lines | |||||
| #include <cstring> | #include <cstring> | ||||
| #include "BLI_listbase.h" | #include "BLI_listbase.h" | ||||
| #include "BKE_screen.h" | #include "BKE_screen.h" | ||||
| #include "ED_screen.h" | #include "ED_screen.h" | ||||
| #include "ED_space_api.h" | #include "ED_space_api.h" | ||||
| #include "ED_spreadsheet.h" | |||||
| #include "DNA_scene_types.h" | #include "DNA_scene_types.h" | ||||
| #include "DNA_screen_types.h" | #include "DNA_screen_types.h" | ||||
| #include "DNA_space_types.h" | #include "DNA_space_types.h" | ||||
| #include "MEM_guardedalloc.h" | #include "MEM_guardedalloc.h" | ||||
| #include "UI_interface.h" | #include "UI_interface.h" | ||||
| #include "UI_resources.h" | #include "UI_resources.h" | ||||
| #include "UI_view2d.h" | #include "UI_view2d.h" | ||||
| #include "DEG_depsgraph_query.h" | #include "DEG_depsgraph_query.h" | ||||
| #include "RNA_access.h" | #include "RNA_access.h" | ||||
| #include "WM_api.h" | #include "WM_api.h" | ||||
| #include "WM_types.h" | #include "WM_types.h" | ||||
| #include "BLF_api.h" | #include "BLF_api.h" | ||||
| #include "spreadsheet_intern.hh" | #include "spreadsheet_intern.hh" | ||||
| #include "spreadsheet_breadcrumb.hh" | |||||
| #include "spreadsheet_data_source_geometry.hh" | #include "spreadsheet_data_source_geometry.hh" | ||||
| #include "spreadsheet_intern.hh" | #include "spreadsheet_intern.hh" | ||||
| #include "spreadsheet_layout.hh" | #include "spreadsheet_layout.hh" | ||||
| using namespace blender; | using namespace blender; | ||||
| using namespace blender::ed::spreadsheet; | using namespace blender::ed::spreadsheet; | ||||
| static SpaceLink *spreadsheet_create(const ScrArea *UNUSED(area), const Scene *UNUSED(scene)) | static SpaceLink *spreadsheet_create(const ScrArea *UNUSED(area), const Scene *UNUSED(scene)) | ||||
| Show All 31 Lines | |||||
| static void spreadsheet_free(SpaceLink *sl) | static void spreadsheet_free(SpaceLink *sl) | ||||
| { | { | ||||
| SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)sl; | SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)sl; | ||||
| MEM_SAFE_FREE(sspreadsheet->runtime); | MEM_SAFE_FREE(sspreadsheet->runtime); | ||||
| LISTBASE_FOREACH_MUTABLE (SpreadsheetColumn *, column, &sspreadsheet->columns) { | LISTBASE_FOREACH_MUTABLE (SpreadsheetColumn *, column, &sspreadsheet->columns) { | ||||
| spreadsheet_column_free(column); | spreadsheet_column_free(column); | ||||
| } | } | ||||
| LISTBASE_FOREACH_MUTABLE (SpreadsheetContext *, context, &sspreadsheet->context_path) { | |||||
| spreadsheet_context_free(context); | |||||
| } | |||||
| } | } | ||||
| static void spreadsheet_init(wmWindowManager *UNUSED(wm), ScrArea *area) | static void spreadsheet_init(wmWindowManager *UNUSED(wm), ScrArea *area) | ||||
| { | { | ||||
| SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)area->spacedata.first; | SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)area->spacedata.first; | ||||
| if (sspreadsheet->runtime == nullptr) { | if (sspreadsheet->runtime == nullptr) { | ||||
| sspreadsheet->runtime = (SpaceSpreadsheet_Runtime *)MEM_callocN( | sspreadsheet->runtime = (SpaceSpreadsheet_Runtime *)MEM_callocN( | ||||
| sizeof(SpaceSpreadsheet_Runtime), __func__); | sizeof(SpaceSpreadsheet_Runtime), __func__); | ||||
| } | } | ||||
| LISTBASE_FOREACH_MUTABLE (SpreadsheetColumn *, column, &sspreadsheet->columns) { | |||||
| spreadsheet_column_free(column); | |||||
| } | |||||
| BLI_listbase_clear(&sspreadsheet->columns); | |||||
| } | } | ||||
| static SpaceLink *spreadsheet_duplicate(SpaceLink *sl) | static SpaceLink *spreadsheet_duplicate(SpaceLink *sl) | ||||
| { | { | ||||
| const SpaceSpreadsheet *sspreadsheet_old = (SpaceSpreadsheet *)sl; | const SpaceSpreadsheet *sspreadsheet_old = (SpaceSpreadsheet *)sl; | ||||
| SpaceSpreadsheet *sspreadsheet_new = (SpaceSpreadsheet *)MEM_dupallocN(sspreadsheet_old); | SpaceSpreadsheet *sspreadsheet_new = (SpaceSpreadsheet *)MEM_dupallocN(sspreadsheet_old); | ||||
| sspreadsheet_new->runtime = (SpaceSpreadsheet_Runtime *)MEM_dupallocN(sspreadsheet_old->runtime); | sspreadsheet_new->runtime = (SpaceSpreadsheet_Runtime *)MEM_dupallocN(sspreadsheet_old->runtime); | ||||
| BLI_listbase_clear(&sspreadsheet_new->columns); | BLI_listbase_clear(&sspreadsheet_new->columns); | ||||
| LISTBASE_FOREACH (SpreadsheetColumn *, src_column, &sspreadsheet_old->columns) { | LISTBASE_FOREACH (SpreadsheetColumn *, src_column, &sspreadsheet_old->columns) { | ||||
| SpreadsheetColumn *new_column = spreadsheet_column_copy(src_column); | SpreadsheetColumn *new_column = spreadsheet_column_copy(src_column); | ||||
| BLI_addtail(&sspreadsheet_new->columns, new_column); | 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); | |||||
| } | |||||
| return (SpaceLink *)sspreadsheet_new; | return (SpaceLink *)sspreadsheet_new; | ||||
| } | } | ||||
| static void spreadsheet_keymap(wmKeyConfig *UNUSED(keyconf)) | static void spreadsheet_keymap(wmKeyConfig *UNUSED(keyconf)) | ||||
| { | { | ||||
| } | } | ||||
| static void spreadsheet_id_remap(ScrArea *UNUSED(area), SpaceLink *slink, ID *old_id, ID *new_id) | |||||
| { | |||||
| SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)slink; | |||||
| LISTBASE_FOREACH (SpreadsheetContext *, context, &sspreadsheet->context_path) { | |||||
| if (context->type == SPREADSHEET_CONTEXT_OBJECT) { | |||||
| SpreadsheetContextObject *object_context = (SpreadsheetContextObject *)context; | |||||
| if ((ID *)object_context->object == old_id) { | |||||
| if (new_id && GS(new_id->name) == ID_OB) { | |||||
| object_context->object = (Object *)new_id; | |||||
| } | |||||
| else { | |||||
| object_context->object = nullptr; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| static void spreadsheet_main_region_init(wmWindowManager *wm, ARegion *region) | static void spreadsheet_main_region_init(wmWindowManager *wm, ARegion *region) | ||||
| { | { | ||||
| region->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM; | region->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM; | ||||
| region->v2d.align = V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y; | region->v2d.align = V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y; | ||||
| region->v2d.keepzoom = V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT; | region->v2d.keepzoom = V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT; | ||||
| region->v2d.keeptot = V2D_KEEPTOT_STRICT; | region->v2d.keeptot = V2D_KEEPTOT_STRICT; | ||||
| region->v2d.minzoom = region->v2d.maxzoom = 1.0f; | region->v2d.minzoom = region->v2d.maxzoom = 1.0f; | ||||
| UI_view2d_region_reinit(®ion->v2d, V2D_COMMONVIEW_LIST, region->winx, region->winy); | UI_view2d_region_reinit(®ion->v2d, V2D_COMMONVIEW_LIST, region->winx, region->winy); | ||||
| wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "View2D Buttons List", 0, 0); | wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "View2D Buttons List", 0, 0); | ||||
| WM_event_add_keymap_handler(®ion->handlers, keymap); | WM_event_add_keymap_handler(®ion->handlers, keymap); | ||||
| } | } | ||||
| static ID *get_used_id(const bContext *C) | ID *ED_spreadsheet_get_current_id(struct SpaceSpreadsheet *sspreadsheet) | ||||
| { | |||||
| if (BLI_listbase_is_empty(&sspreadsheet->context_path)) { | |||||
| return nullptr; | |||||
| } | |||||
| SpreadsheetContext *root_context = (SpreadsheetContext *)sspreadsheet->context_path.first; | |||||
| if (root_context->type != SPREADSHEET_CONTEXT_OBJECT) { | |||||
| return nullptr; | |||||
| } | |||||
| SpreadsheetContextObject *object_context = (SpreadsheetContextObject *)root_context; | |||||
| return (ID *)object_context->object; | |||||
| } | |||||
| /* 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) | |||||
HooglyBoogly: The first question a reader has is "what does outdated mean?" From reading the code it looks… | |||||
| { | { | ||||
| SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C); | SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C); | ||||
| if (sspreadsheet->pinned_id != nullptr) { | |||||
| return sspreadsheet->pinned_id; | /* Currently, this only checks if the object has been deleted. In the future we can have a more | ||||
| * sophisticated check for the entire context (including modifier and nodes). */ | |||||
| LISTBASE_FOREACH (SpreadsheetContext *, context, &sspreadsheet->context_path) { | |||||
| if (context->type == SPREADSHEET_CONTEXT_OBJECT) { | |||||
| SpreadsheetContextObject *object_context = (SpreadsheetContextObject *)context; | |||||
| if (object_context->object == nullptr) { | |||||
| ED_spreadsheet_context_path_clear(sspreadsheet); | |||||
| break; | |||||
| } | |||||
| } | } | ||||
| } | |||||
| if (BLI_listbase_is_empty(&sspreadsheet->context_path)) { | |||||
| Object *active_object = CTX_data_active_object(C); | Object *active_object = CTX_data_active_object(C); | ||||
| return (ID *)active_object; | if (active_object != nullptr) { | ||||
| SpreadsheetContext *new_context = spreadsheet_context_new(SPREADSHEET_CONTEXT_OBJECT); | |||||
| ((SpreadsheetContextObject *)new_context)->object = active_object; | |||||
| BLI_addtail(&sspreadsheet->context_path, new_context); | |||||
| } | |||||
| } | |||||
| if (BLI_listbase_is_empty(&sspreadsheet->context_path)) { | |||||
| /* Don't pin empty context_path, that could be annoying. */ | |||||
| sspreadsheet->flag &= ~SPREADSHEET_FLAG_PINNED; | |||||
| } | |||||
| } | |||||
| static void update_context_path_from_context(const bContext *C) | |||||
| { | |||||
| SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C); | |||||
| Object *active_object = CTX_data_active_object(C); | |||||
| if (active_object == nullptr) { | |||||
| ED_spreadsheet_context_path_clear(sspreadsheet); | |||||
| return; | |||||
| } | |||||
| if (!BLI_listbase_is_empty(&sspreadsheet->context_path)) { | |||||
| SpreadsheetContext *root_context = (SpreadsheetContext *)sspreadsheet->context_path.first; | |||||
| if (root_context->type == SPREADSHEET_CONTEXT_OBJECT) { | |||||
| SpreadsheetContextObject *object_context = (SpreadsheetContextObject *)root_context; | |||||
| if (object_context->object != active_object) { | |||||
| ED_spreadsheet_context_path_clear(sspreadsheet); | |||||
| } | |||||
| } | |||||
| } | |||||
| if (BLI_listbase_is_empty(&sspreadsheet->context_path)) { | |||||
| SpreadsheetContext *new_context = spreadsheet_context_new(SPREADSHEET_CONTEXT_OBJECT); | |||||
| ((SpreadsheetContextObject *)new_context)->object = active_object; | |||||
| BLI_addtail(&sspreadsheet->context_path, new_context); | |||||
| } | |||||
| } | |||||
| static void 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); | |||||
| } | |||||
| } | } | ||||
| static std::unique_ptr<DataSource> get_data_source(const bContext *C) | static std::unique_ptr<DataSource> get_data_source(const bContext *C) | ||||
| { | { | ||||
| Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); | Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); | ||||
| ID *used_id = get_used_id(C); | SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C); | ||||
| ID *used_id = ED_spreadsheet_get_current_id(sspreadsheet); | |||||
| if (used_id == nullptr) { | if (used_id == nullptr) { | ||||
| return {}; | return {}; | ||||
| } | } | ||||
| const ID_Type id_type = GS(used_id->name); | const ID_Type id_type = GS(used_id->name); | ||||
| if (id_type != ID_OB) { | if (id_type != ID_OB) { | ||||
| return {}; | return {}; | ||||
| } | } | ||||
| Object *object_orig = (Object *)used_id; | Object *object_orig = (Object *)used_id; | ||||
| ▲ Show 20 Lines • Show All 58 Lines • ▼ Show 20 Lines | if (values) { | ||||
| } | } | ||||
| } | } | ||||
| }); | }); | ||||
| } | } | ||||
| static void spreadsheet_main_region_draw(const bContext *C, ARegion *region) | static void spreadsheet_main_region_draw(const bContext *C, ARegion *region) | ||||
| { | { | ||||
| SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C); | SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C); | ||||
| update_context_path(C); | |||||
| std::unique_ptr<DataSource> data_source = get_data_source(C); | std::unique_ptr<DataSource> data_source = get_data_source(C); | ||||
| if (!data_source) { | if (!data_source) { | ||||
| data_source = std::make_unique<DataSource>(); | data_source = std::make_unique<DataSource>(); | ||||
| } | } | ||||
| update_visible_columns(sspreadsheet->columns, *data_source); | update_visible_columns(sspreadsheet->columns, *data_source); | ||||
| ▲ Show 20 Lines • Show All 74 Lines • ▼ Show 20 Lines | |||||
| static void spreadsheet_header_region_init(wmWindowManager *UNUSED(wm), ARegion *region) | static void spreadsheet_header_region_init(wmWindowManager *UNUSED(wm), ARegion *region) | ||||
| { | { | ||||
| ED_region_header_init(region); | ED_region_header_init(region); | ||||
| } | } | ||||
| static void spreadsheet_header_region_draw(const bContext *C, ARegion *region) | static void spreadsheet_header_region_draw(const bContext *C, ARegion *region) | ||||
| { | { | ||||
| update_context_path(C); | |||||
| ED_region_header(C, region); | ED_region_header(C, region); | ||||
| } | } | ||||
| static void spreadsheet_header_region_free(ARegion *UNUSED(region)) | static void spreadsheet_header_region_free(ARegion *UNUSED(region)) | ||||
| { | { | ||||
| } | } | ||||
| static void spreadsheet_header_region_listener(const wmRegionListenerParams *params) | static void spreadsheet_header_region_listener(const wmRegionListenerParams *params) | ||||
| ▲ Show 20 Lines • Show All 89 Lines • ▼ Show 20 Lines | void ED_spacetype_spreadsheet(void) | ||||
| strncpy(st->name, "Spreadsheet", BKE_ST_MAXNAME); | strncpy(st->name, "Spreadsheet", BKE_ST_MAXNAME); | ||||
| st->create = spreadsheet_create; | st->create = spreadsheet_create; | ||||
| st->free = spreadsheet_free; | st->free = spreadsheet_free; | ||||
| st->init = spreadsheet_init; | st->init = spreadsheet_init; | ||||
| st->duplicate = spreadsheet_duplicate; | st->duplicate = spreadsheet_duplicate; | ||||
| st->operatortypes = spreadsheet_operatortypes; | st->operatortypes = spreadsheet_operatortypes; | ||||
| st->keymap = spreadsheet_keymap; | st->keymap = spreadsheet_keymap; | ||||
| st->id_remap = spreadsheet_id_remap; | |||||
| /* regions: main window */ | /* regions: main window */ | ||||
| art = (ARegionType *)MEM_callocN(sizeof(ARegionType), "spacetype spreadsheet region"); | art = (ARegionType *)MEM_callocN(sizeof(ARegionType), "spacetype spreadsheet region"); | ||||
| art->regionid = RGN_TYPE_WINDOW; | art->regionid = RGN_TYPE_WINDOW; | ||||
| art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D; | art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D; | ||||
| art->init = spreadsheet_main_region_init; | art->init = spreadsheet_main_region_init; | ||||
| art->draw = spreadsheet_main_region_draw; | art->draw = spreadsheet_main_region_draw; | ||||
| Show All 31 Lines | |||||
The first question a reader has is "what does outdated mean?" From reading the code it looks like it might mean that the object was deleted? That makes sense, but then I wonder.. what about deleted nodes? Modifiers? The function could have a comment at the top to make its goals clearer.