Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/space_outliner/outliner_sync.c')
-rw-r--r--source/blender/editors/space_outliner/outliner_sync.c582
1 files changed, 0 insertions, 582 deletions
diff --git a/source/blender/editors/space_outliner/outliner_sync.c b/source/blender/editors/space_outliner/outliner_sync.c
deleted file mode 100644
index d78767019b5..00000000000
--- a/source/blender/editors/space_outliner/outliner_sync.c
+++ /dev/null
@@ -1,582 +0,0 @@
-/*
- * 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.
- *
- * The Original Code is Copyright (C) 2004 Blender Foundation.
- * All rights reserved.
- */
-
-/** \file
- * \ingroup spoutliner
- */
-
-#include <stdio.h>
-
-#include "DNA_armature_types.h"
-#include "DNA_layer_types.h"
-#include "DNA_outliner_types.h"
-#include "DNA_screen_types.h"
-#include "DNA_sequence_types.h"
-#include "DNA_space_types.h"
-
-#include "BLI_compiler_compat.h"
-#include "BLI_ghash.h"
-#include "BLI_listbase.h"
-
-#include "BKE_armature.h"
-#include "BKE_context.h"
-#include "BKE_layer.h"
-#include "BKE_main.h"
-
-#include "DEG_depsgraph.h"
-
-#include "ED_armature.h"
-#include "ED_object.h"
-#include "ED_outliner.h"
-
-#include "SEQ_select.h"
-
-#include "WM_api.h"
-#include "WM_types.h"
-
-#include "outliner_intern.h"
-
-/* Functions for tagging outliner selection syncing is dirty from operators */
-void ED_outliner_select_sync_from_object_tag(bContext *C)
-{
- wmWindowManager *wm = CTX_wm_manager(C);
- wm->outliner_sync_select_dirty |= WM_OUTLINER_SYNC_SELECT_FROM_OBJECT;
-}
-
-void ED_outliner_select_sync_from_edit_bone_tag(bContext *C)
-{
- wmWindowManager *wm = CTX_wm_manager(C);
- wm->outliner_sync_select_dirty |= WM_OUTLINER_SYNC_SELECT_FROM_EDIT_BONE;
-}
-
-void ED_outliner_select_sync_from_pose_bone_tag(bContext *C)
-{
- wmWindowManager *wm = CTX_wm_manager(C);
- wm->outliner_sync_select_dirty |= WM_OUTLINER_SYNC_SELECT_FROM_POSE_BONE;
-}
-
-void ED_outliner_select_sync_from_sequence_tag(bContext *C)
-{
- wmWindowManager *wm = CTX_wm_manager(C);
- wm->outliner_sync_select_dirty |= WM_OUTLINER_SYNC_SELECT_FROM_SEQUENCE;
-}
-
-void ED_outliner_select_sync_from_all_tag(bContext *C)
-{
- wmWindowManager *wm = CTX_wm_manager(C);
- wm->outliner_sync_select_dirty |= WM_OUTLINER_SYNC_SELECT_FROM_ALL;
-}
-
-bool ED_outliner_select_sync_is_dirty(const bContext *C)
-{
- wmWindowManager *wm = CTX_wm_manager(C);
- return wm->outliner_sync_select_dirty & WM_OUTLINER_SYNC_SELECT_FROM_ALL;
-}
-
-/* Copy sync select dirty flag from window manager to all outliners to be synced lazily on draw */
-void ED_outliner_select_sync_flag_outliners(const bContext *C)
-{
- Main *bmain = CTX_data_main(C);
- wmWindowManager *wm = CTX_wm_manager(C);
-
- for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
- LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
- LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
- if (sl->spacetype == SPACE_OUTLINER) {
- SpaceOutliner *space_outliner = (SpaceOutliner *)sl;
-
- space_outliner->sync_select_dirty |= wm->outliner_sync_select_dirty;
- }
- }
- }
- }
-
- /* Clear global sync flag */
- wm->outliner_sync_select_dirty = 0;
-}
-
-/**
- * Outliner sync select dirty flags are not enough to determine which types to sync,
- * outliner display mode also needs to be considered. This stores the types of data
- * to sync to increase code clarity.
- */
-typedef struct SyncSelectTypes {
- bool object;
- bool edit_bone;
- bool pose_bone;
- bool sequence;
-} SyncSelectTypes;
-
-/**
- * Set which types of data to sync when syncing selection from the outliner based on object
- * interaction mode and outliner display mode
- */
-static void outliner_sync_select_from_outliner_set_types(bContext *C,
- SpaceOutliner *space_outliner,
- SyncSelectTypes *sync_types)
-{
- TreeViewContext tvc;
- outliner_viewcontext_init(C, &tvc);
-
- const bool sequence_view = space_outliner->outlinevis == SO_SEQUENCE;
-
- sync_types->object = !sequence_view;
- sync_types->edit_bone = !sequence_view && (tvc.ob_edit && tvc.ob_edit->type == OB_ARMATURE);
- sync_types->pose_bone = !sequence_view && (tvc.ob_pose && tvc.ob_pose->mode == OB_MODE_POSE);
- sync_types->sequence = sequence_view;
-}
-
-/**
- * Current dirty flags and outliner display mode determine which type of syncing should occur.
- * This is to ensure sync flag data is not lost on sync in the wrong display mode.
- * Returns true if a sync is needed.
- */
-static bool outliner_sync_select_to_outliner_set_types(const bContext *C,
- SpaceOutliner *space_outliner,
- SyncSelectTypes *sync_types)
-{
- TreeViewContext tvc;
- outliner_viewcontext_init(C, &tvc);
-
- const bool sequence_view = space_outliner->outlinevis == SO_SEQUENCE;
-
- sync_types->object = !sequence_view &&
- (space_outliner->sync_select_dirty & WM_OUTLINER_SYNC_SELECT_FROM_OBJECT);
- sync_types->edit_bone = !sequence_view && (tvc.ob_edit && tvc.ob_edit->type == OB_ARMATURE) &&
- (space_outliner->sync_select_dirty &
- WM_OUTLINER_SYNC_SELECT_FROM_EDIT_BONE);
- sync_types->pose_bone = !sequence_view && (tvc.ob_pose && tvc.ob_pose->mode == OB_MODE_POSE) &&
- (space_outliner->sync_select_dirty &
- WM_OUTLINER_SYNC_SELECT_FROM_POSE_BONE);
- sync_types->sequence = sequence_view && (space_outliner->sync_select_dirty &
- WM_OUTLINER_SYNC_SELECT_FROM_SEQUENCE);
-
- return sync_types->object || sync_types->edit_bone || sync_types->pose_bone ||
- sync_types->sequence;
-}
-
-/**
- * Stores items selected from a sync from the outliner. Prevents syncing the selection
- * state of the last instance of an object linked in multiple collections.
- */
-typedef struct SelectedItems {
- GSet *objects;
- GSet *edit_bones;
- GSet *pose_bones;
-} SelectedItems;
-
-static void selected_items_init(SelectedItems *selected_items)
-{
- selected_items->objects = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
- selected_items->edit_bones = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
- selected_items->pose_bones = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
-}
-
-static void selected_items_free(SelectedItems *selected_items)
-{
- BLI_gset_free(selected_items->objects, NULL);
- BLI_gset_free(selected_items->edit_bones, NULL);
- BLI_gset_free(selected_items->pose_bones, NULL);
-}
-
-/* Check if an instance of this object been selected by the sync */
-static bool is_object_selected(GSet *selected_objects, Base *base)
-{
- return BLI_gset_haskey(selected_objects, base);
-}
-
-/* Check if an instance of this edit bone been selected by the sync */
-static bool is_edit_bone_selected(GSet *selected_ebones, EditBone *ebone)
-{
- return BLI_gset_haskey(selected_ebones, ebone);
-}
-
-/* Check if an instance of this pose bone been selected by the sync */
-static bool is_pose_bone_selected(GSet *selected_pbones, bPoseChannel *pchan)
-{
- return BLI_gset_haskey(selected_pbones, pchan);
-}
-
-/* Add element's data to selected item set */
-static void add_selected_item(GSet *selected, void *data)
-{
- BLI_gset_add(selected, data);
-}
-
-static void outliner_select_sync_to_object(ViewLayer *view_layer,
- TreeElement *te,
- TreeStoreElem *tselem,
- GSet *selected_objects)
-{
- Object *ob = (Object *)tselem->id;
- Base *base = (te->directdata) ? (Base *)te->directdata :
- BKE_view_layer_base_find(view_layer, ob);
-
- if (base && (base->flag & BASE_SELECTABLE)) {
- if (tselem->flag & TSE_SELECTED) {
- ED_object_base_select(base, BA_SELECT);
-
- add_selected_item(selected_objects, base);
- }
- else if (!is_object_selected(selected_objects, base)) {
- ED_object_base_select(base, BA_DESELECT);
- }
- }
-}
-
-static void outliner_select_sync_to_edit_bone(ViewLayer *view_layer,
- TreeElement *te,
- TreeStoreElem *tselem,
- GSet *selected_ebones)
-{
- bArmature *arm = (bArmature *)tselem->id;
- EditBone *ebone = (EditBone *)te->directdata;
-
- short bone_flag = ebone->flag;
-
- if (EBONE_SELECTABLE(arm, ebone)) {
- if (tselem->flag & TSE_SELECTED) {
- ED_armature_ebone_select_set(ebone, true);
- add_selected_item(selected_ebones, ebone);
- }
- else if (!is_edit_bone_selected(selected_ebones, ebone)) {
- /* Don't flush to parent bone tip, synced selection is iterating the whole tree so
- * deselecting potential children with `ED_armature_ebone_select_set(ebone, false)`
- * would leave own tip deselected. */
- ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- }
- }
-
- /* Tag if selection changed */
- if (bone_flag != ebone->flag) {
- Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
- DEG_id_tag_update(&arm->id, ID_RECALC_SELECT);
- WM_main_add_notifier(NC_OBJECT | ND_BONE_SELECT, obedit);
- }
-}
-
-static void outliner_select_sync_to_pose_bone(TreeElement *te,
- TreeStoreElem *tselem,
- GSet *selected_pbones)
-{
- Object *ob = (Object *)tselem->id;
- bArmature *arm = ob->data;
- bPoseChannel *pchan = (bPoseChannel *)te->directdata;
-
- short bone_flag = pchan->bone->flag;
-
- if (PBONE_SELECTABLE(arm, pchan->bone)) {
- if (tselem->flag & TSE_SELECTED) {
- pchan->bone->flag |= BONE_SELECTED;
-
- add_selected_item(selected_pbones, pchan);
- }
- else if (!is_pose_bone_selected(selected_pbones, pchan)) {
- pchan->bone->flag &= ~BONE_SELECTED;
- }
- }
-
- /* Tag if selection changed */
- if (bone_flag != pchan->bone->flag) {
- DEG_id_tag_update(&arm->id, ID_RECALC_SELECT);
- WM_main_add_notifier(NC_OBJECT | ND_BONE_SELECT, ob);
- }
-}
-
-static void outliner_select_sync_to_sequence(Scene *scene, TreeStoreElem *tselem)
-{
- Sequence *seq = (Sequence *)tselem->id;
-
- if (tselem->flag & TSE_ACTIVE) {
- SEQ_select_active_set(scene, seq);
- }
-
- if (tselem->flag & TSE_SELECTED) {
- seq->flag |= SELECT;
- }
- else {
- seq->flag &= ~SELECT;
- }
-}
-
-/** Sync select and active flags from outliner to active view layer, bones, and sequencer. */
-static void outliner_sync_selection_from_outliner(Scene *scene,
- ViewLayer *view_layer,
- ListBase *tree,
- const SyncSelectTypes *sync_types,
- SelectedItems *selected_items)
-{
-
- LISTBASE_FOREACH (TreeElement *, te, tree) {
- TreeStoreElem *tselem = TREESTORE(te);
-
- if ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB)) {
- if (sync_types->object) {
- outliner_select_sync_to_object(view_layer, te, tselem, selected_items->objects);
- }
- }
- else if (tselem->type == TSE_EBONE) {
- if (sync_types->edit_bone) {
- outliner_select_sync_to_edit_bone(view_layer, te, tselem, selected_items->edit_bones);
- }
- }
- else if (tselem->type == TSE_POSE_CHANNEL) {
- if (sync_types->pose_bone) {
- outliner_select_sync_to_pose_bone(te, tselem, selected_items->pose_bones);
- }
- }
- else if (tselem->type == TSE_SEQUENCE) {
- if (sync_types->sequence) {
- outliner_select_sync_to_sequence(scene, tselem);
- }
- }
-
- outliner_sync_selection_from_outliner(
- scene, view_layer, &te->subtree, sync_types, selected_items);
- }
-}
-
-/* Set clean outliner and mark other outliners for syncing */
-void ED_outliner_select_sync_from_outliner(bContext *C, SpaceOutliner *space_outliner)
-{
- /* Don't sync if not checked or in certain outliner display modes */
- if (!(space_outliner->flag & SO_SYNC_SELECT) || ELEM(space_outliner->outlinevis,
- SO_LIBRARIES,
- SO_OVERRIDES_LIBRARY,
- SO_DATA_API,
- SO_ID_ORPHANS)) {
- return;
- }
-
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
-
- SyncSelectTypes sync_types;
- outliner_sync_select_from_outliner_set_types(C, space_outliner, &sync_types);
-
- /* To store elements that have been selected to prevent linked object sync errors */
- SelectedItems selected_items;
-
- selected_items_init(&selected_items);
-
- outliner_sync_selection_from_outliner(
- scene, view_layer, &space_outliner->tree, &sync_types, &selected_items);
-
- selected_items_free(&selected_items);
-
- /* Tag for updates and clear dirty flag to prevent a sync to the outliner on draw. */
- if (sync_types.object) {
- space_outliner->sync_select_dirty &= ~WM_OUTLINER_SYNC_SELECT_FROM_OBJECT;
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- }
- else if (sync_types.edit_bone) {
- space_outliner->sync_select_dirty &= ~WM_OUTLINER_SYNC_SELECT_FROM_EDIT_BONE;
- }
- else if (sync_types.pose_bone) {
- space_outliner->sync_select_dirty &= ~WM_OUTLINER_SYNC_SELECT_FROM_POSE_BONE;
- }
- if (sync_types.sequence) {
- space_outliner->sync_select_dirty &= ~WM_OUTLINER_SYNC_SELECT_FROM_SEQUENCE;
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
- }
-}
-
-static void outliner_select_sync_from_object(ViewLayer *view_layer,
- Object *obact,
- TreeElement *te,
- TreeStoreElem *tselem)
-{
- Object *ob = (Object *)tselem->id;
- Base *base = (te->directdata) ? (Base *)te->directdata :
- BKE_view_layer_base_find(view_layer, ob);
- const bool is_selected = (base != NULL) && ((base->flag & BASE_SELECTED) != 0);
-
- if (base && (ob == obact)) {
- tselem->flag |= TSE_ACTIVE;
- }
- else {
- tselem->flag &= ~TSE_ACTIVE;
- }
-
- if (is_selected) {
- tselem->flag |= TSE_SELECTED;
- }
- else {
- tselem->flag &= ~TSE_SELECTED;
- }
-}
-
-static void outliner_select_sync_from_edit_bone(EditBone *ebone_active,
- TreeElement *te,
- TreeStoreElem *tselem)
-{
- EditBone *ebone = (EditBone *)te->directdata;
-
- if (ebone == ebone_active) {
- tselem->flag |= TSE_ACTIVE;
- }
- else {
- tselem->flag &= ~TSE_ACTIVE;
- }
-
- if (ebone->flag & BONE_SELECTED) {
- tselem->flag |= TSE_SELECTED;
- }
- else {
- tselem->flag &= ~TSE_SELECTED;
- }
-}
-
-static void outliner_select_sync_from_pose_bone(bPoseChannel *pchan_active,
- TreeElement *te,
- TreeStoreElem *tselem)
-{
- bPoseChannel *pchan = (bPoseChannel *)te->directdata;
- Bone *bone = pchan->bone;
-
- if (pchan == pchan_active) {
- tselem->flag |= TSE_ACTIVE;
- }
- else {
- tselem->flag &= ~TSE_ACTIVE;
- }
-
- if (bone->flag & BONE_SELECTED) {
- tselem->flag |= TSE_SELECTED;
- }
- else {
- tselem->flag &= ~TSE_SELECTED;
- }
-}
-
-static void outliner_select_sync_from_sequence(Sequence *sequence_active, TreeStoreElem *tselem)
-{
- Sequence *seq = (Sequence *)tselem->id;
-
- if (seq == sequence_active) {
- tselem->flag |= TSE_ACTIVE;
- }
- else {
- tselem->flag &= ~TSE_ACTIVE;
- }
-
- if (seq->flag & SELECT) {
- tselem->flag |= TSE_SELECTED;
- }
- else {
- tselem->flag &= ~TSE_SELECTED;
- }
-}
-
-/**
- * Contains active object, bones, and sequence for syncing to prevent getting active data
- * repeatedly throughout syncing to the outliner.
- */
-typedef struct SyncSelectActiveData {
- Object *object;
- EditBone *edit_bone;
- bPoseChannel *pose_channel;
- Sequence *sequence;
-} SyncSelectActiveData;
-
-/** Sync select and active flags from active view layer, bones, and sequences to the outliner. */
-static void outliner_sync_selection_to_outliner(ViewLayer *view_layer,
- SpaceOutliner *space_outliner,
- ListBase *tree,
- SyncSelectActiveData *active_data,
- const SyncSelectTypes *sync_types)
-{
- LISTBASE_FOREACH (TreeElement *, te, tree) {
- TreeStoreElem *tselem = TREESTORE(te);
-
- if ((tselem->type == TSE_SOME_ID) && te->idcode == ID_OB) {
- if (sync_types->object) {
- outliner_select_sync_from_object(view_layer, active_data->object, te, tselem);
- }
- }
- else if (tselem->type == TSE_EBONE) {
- if (sync_types->edit_bone) {
- outliner_select_sync_from_edit_bone(active_data->edit_bone, te, tselem);
- }
- }
- else if (tselem->type == TSE_POSE_CHANNEL) {
- if (sync_types->pose_bone) {
- outliner_select_sync_from_pose_bone(active_data->pose_channel, te, tselem);
- }
- }
- else if (tselem->type == TSE_SEQUENCE) {
- if (sync_types->sequence) {
- outliner_select_sync_from_sequence(active_data->sequence, tselem);
- }
- }
- else {
- tselem->flag &= ~(TSE_SELECTED | TSE_ACTIVE);
- }
-
- /* Sync subtree elements */
- outliner_sync_selection_to_outliner(
- view_layer, space_outliner, &te->subtree, active_data, sync_types);
- }
-}
-
-/* Get active data from context */
-static void get_sync_select_active_data(const bContext *C, SyncSelectActiveData *active_data)
-{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- active_data->object = OBACT(view_layer);
- active_data->edit_bone = CTX_data_active_bone(C);
- active_data->pose_channel = CTX_data_active_pose_bone(C);
- active_data->sequence = SEQ_select_active_get(scene);
-}
-
-/* If outliner is dirty sync selection from view layer and sequencer. */
-void outliner_sync_selection(const bContext *C, SpaceOutliner *space_outliner)
-{
- /* Set which types of data to sync from sync dirty flag and outliner display mode */
- SyncSelectTypes sync_types;
- const bool sync_required = outliner_sync_select_to_outliner_set_types(
- C, space_outliner, &sync_types);
-
- if (sync_required) {
- ViewLayer *view_layer = CTX_data_view_layer(C);
-
- /* Store active object, bones, and sequence */
- SyncSelectActiveData active_data;
- get_sync_select_active_data(C, &active_data);
-
- outliner_sync_selection_to_outliner(
- view_layer, space_outliner, &space_outliner->tree, &active_data, &sync_types);
-
- /* Keep any unsynced data in the dirty flag */
- if (sync_types.object) {
- space_outliner->sync_select_dirty &= ~WM_OUTLINER_SYNC_SELECT_FROM_OBJECT;
- }
- if (sync_types.edit_bone) {
- space_outliner->sync_select_dirty &= ~WM_OUTLINER_SYNC_SELECT_FROM_EDIT_BONE;
- }
- if (sync_types.pose_bone) {
- space_outliner->sync_select_dirty &= ~WM_OUTLINER_SYNC_SELECT_FROM_POSE_BONE;
- }
- if (sync_types.sequence) {
- space_outliner->sync_select_dirty &= ~WM_OUTLINER_SYNC_SELECT_FROM_SEQUENCE;
- }
- }
-}