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

tree_element.cc « tree « space_outliner « editors « blender « source - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 4b85784d2aee1e3823fb367378db97114de883a0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
/* SPDX-License-Identifier: GPL-2.0-or-later */

/** \file
 * \ingroup spoutliner
 */

#include <string>
#include <string_view>

#include "DNA_anim_types.h"
#include "DNA_listBase.h"
#include "DNA_space_types.h"

#include "UI_resources.h"

#include "BLT_translation.h"

#include "tree_element_anim_data.hh"
#include "tree_element_collection.hh"
#include "tree_element_driver.hh"
#include "tree_element_gpencil_layer.hh"
#include "tree_element_id.hh"
#include "tree_element_label.hh"
#include "tree_element_nla.hh"
#include "tree_element_overrides.hh"
#include "tree_element_rna.hh"
#include "tree_element_scene_objects.hh"
#include "tree_element_seq.hh"
#include "tree_element_view_layer.hh"

#include "../outliner_intern.hh"
#include "tree_element.hh"

namespace blender::ed::outliner {

std::unique_ptr<AbstractTreeElement> AbstractTreeElement::createFromType(const int type,
                                                                         TreeElement &legacy_te,
                                                                         void *idv)
{
  if (idv == nullptr) {
    return nullptr;
  }

  /*
   * The following calls make an implicit assumption about what data was passed to the `idv`
   * argument of #outliner_add_element(). The old code does this already, here we just centralize
   * it as much as possible for now. Would be nice to entirely get rid of that, no more `void *`.
   *
   * Once #outliner_add_element() is sufficiently simplified, it should be replaced by a C++ call.
   * It could take the derived type as template parameter (e.g. #TreeElementAnimData) and use C++
   * perfect forwarding to pass any data to the type's constructor.
   * If general Outliner code wants to access the data, they can query that through the derived
   * element type then. There's no need for `void *` anymore then.
   */

  switch (type) {
    case TSE_SOME_ID:
      return TreeElementID::createFromID(legacy_te, *static_cast<ID *>(idv));
    case TSE_GENERIC_LABEL:
      return std::make_unique<TreeElementLabel>(legacy_te, static_cast<const char *>(idv));
    case TSE_ANIM_DATA:
      return std::make_unique<TreeElementAnimData>(legacy_te,
                                                   *static_cast<IdAdtTemplate *>(idv)->adt);
    case TSE_DRIVER_BASE:
      return std::make_unique<TreeElementDriverBase>(legacy_te, *static_cast<AnimData *>(idv));
    case TSE_NLA:
      return std::make_unique<TreeElementNLA>(legacy_te, *static_cast<AnimData *>(idv));
    case TSE_NLA_TRACK:
      return std::make_unique<TreeElementNLATrack>(legacy_te, *static_cast<NlaTrack *>(idv));
    case TSE_NLA_ACTION:
      return std::make_unique<TreeElementNLAAction>(legacy_te, *static_cast<bAction *>(idv));
    case TSE_GP_LAYER:
      return std::make_unique<TreeElementGPencilLayer>(legacy_te, *static_cast<bGPDlayer *>(idv));
    case TSE_R_LAYER_BASE:
      return std::make_unique<TreeElementViewLayerBase>(legacy_te, *static_cast<Scene *>(idv));
    case TSE_SCENE_COLLECTION_BASE:
      return std::make_unique<TreeElementCollectionBase>(legacy_te, *static_cast<Scene *>(idv));
    case TSE_SCENE_OBJECTS_BASE:
      return std::make_unique<TreeElementSceneObjectsBase>(legacy_te, *static_cast<Scene *>(idv));
    case TSE_LIBRARY_OVERRIDE_BASE:
      return std::make_unique<TreeElementOverridesBase>(legacy_te, *static_cast<ID *>(idv));
    case TSE_LIBRARY_OVERRIDE:
      return std::make_unique<TreeElementOverridesProperty>(
          legacy_te, *static_cast<TreeElementOverridesData *>(idv));
    case TSE_LIBRARY_OVERRIDE_OPERATION:
      return std::make_unique<TreeElementOverridesPropertyOperation>(
          legacy_te, *static_cast<TreeElementOverridesData *>(idv));
    case TSE_RNA_STRUCT:
      return std::make_unique<TreeElementRNAStruct>(legacy_te, *static_cast<PointerRNA *>(idv));
    case TSE_RNA_PROPERTY:
      return std::make_unique<TreeElementRNAProperty>(
          legacy_te, *static_cast<PointerRNA *>(idv), legacy_te.index);
    case TSE_RNA_ARRAY_ELEM:
      return std::make_unique<TreeElementRNAArrayElement>(
          legacy_te, *static_cast<PointerRNA *>(idv), legacy_te.index);
    case TSE_SEQUENCE:
      return std::make_unique<TreeElementSequence>(legacy_te, *static_cast<Sequence *>(idv));
    case TSE_SEQ_STRIP:
      return std::make_unique<TreeElementSequenceStrip>(legacy_te, *static_cast<Strip *>(idv));
    case TSE_SEQUENCE_DUP:
      return std::make_unique<TreeElementSequenceStripDuplicate>(legacy_te,
                                                                 *static_cast<Sequence *>(idv));
    default:
      break;
  }

  return nullptr;
}

StringRefNull AbstractTreeElement::getWarning() const
{
  return "";
}

std::optional<BIFIconID> AbstractTreeElement::getIcon() const
{
  return {};
}

void AbstractTreeElement::print_path()
{
  std::string path = legacy_te_.name;

  for (TreeElement *parent = legacy_te_.parent; parent; parent = parent->parent) {
    path = parent->name + std::string_view("/") + path;
  }

  std::cout << path << std::endl;
}

void AbstractTreeElement::uncollapse_by_default(TreeElement *legacy_te)
{
  if (!TREESTORE(legacy_te)->used) {
    TREESTORE(legacy_te)->flag &= ~TSE_CLOSED;
  }
}

void tree_element_expand(const AbstractTreeElement &tree_element, SpaceOutliner &space_outliner)
{
  /* Most types can just expand. IDs optionally expand (hence the poll) and do additional, common
   * expanding. Could be done nicer, we could request a small "expander" helper object from the
   * element type, that the IDs have a more advanced implementation for. */
  if (!tree_element.expandPoll(space_outliner)) {
    return;
  }
  tree_element.expand(space_outliner);
}

/* -------------------------------------------------------------------- */

SubTree::SubTree(TreeElement &parent) : parent_(&parent)
{
}

SubTree::SubTree(SpaceOutliner_Runtime &) : parent_(nullptr)
{
}

void SubTree::add_back(std::unique_ptr<TreeElement> element)
{
  element->parent = parent_;
  /* TODO is this the right place for this? */
  element->child_elements.parent_ = element.get();
  elements_.push_back(std::move(element));
}

void SubTree::insert_before(Iterator pos, std::unique_ptr<TreeElement> element)
{
  element->parent = parent_;
  elements_.insert(pos.iter_, std::move(element));
}

std::unique_ptr<TreeElement> SubTree::remove(TreeElement &element)
{
  std::unique_ptr<TreeElement> element_uptr = nullptr;
  /* TODO doesn't free element entirely yet, #TreeElement.name may need freeing! See
   * #outliner_free_tree_element(). */

  for (decltype(elements_)::iterator iter = elements_.begin(); iter != elements_.end(); ++iter) {
    if (iter->get() == &element) {
      element_uptr = std::move(*iter);
      elements_.erase(iter);
      break;
    }
  }
  BLI_assert(!has_child(element));

  if (element_uptr) {
    element_uptr->parent = nullptr;
  }
  return element_uptr;
}

void SubTree::clear()
{
  elements_.clear();
  /* No need to clear the parent pointer, elements get destructed entirely anyway. */
}

bool SubTree::has_child(const TreeElement &needle) const
{
  for (const TreeElement &te : *this) {
    if (&te == &needle) {
      return true;
    }
  }
  return false;
}

bool SubTree::is_empty() const
{
  return elements_.empty();
}

TreeElement *SubTree::parent() const
{
  return parent_;
}

}  // namespace blender::ed::outliner