Blender V5.0
workspace.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <cstdio>
10#include <cstdlib>
11#include <cstring>
12
13#include "BLI_listbase.h"
14#include "BLI_string.h"
15#include "BLI_string_utils.hh"
16#include "BLI_utildefines.h"
17
18#include "BLT_translation.hh"
19
20#include "BKE_asset.hh"
21#include "BKE_global.hh"
22#include "BKE_idprop.hh"
23#include "BKE_idtype.hh"
24#include "BKE_lib_id.hh"
25#include "BKE_lib_query.hh"
26#include "BKE_main.hh"
27#include "BKE_viewer_path.hh"
28#include "BKE_workspace.hh"
29
30#include "DNA_scene_types.h"
31#include "DNA_screen_types.h"
33#include "DNA_workspace_types.h"
34
35#include "MEM_guardedalloc.h"
36
37#include "BLO_read_write.hh"
38
39/* -------------------------------------------------------------------- */
40
41static void workspace_init_data(ID *id)
42{
43 WorkSpace *workspace = (WorkSpace *)id;
44
45 workspace->runtime = MEM_new<blender::bke::WorkSpaceRuntime>(__func__);
46
48}
49
50static void workspace_free_data(ID *id)
51{
52 WorkSpace *workspace = (WorkSpace *)id;
53
55
56 BLI_freelistN(&workspace->owner_ids);
57 BLI_freelistN(&workspace->layouts);
58
59 while (!BLI_listbase_is_empty(&workspace->tools)) {
60 BKE_workspace_tool_remove(workspace, static_cast<bToolRef *>(workspace->tools.first));
61 }
62
64 MEM_delete(workspace->runtime);
65
67}
68
82
83static void workspace_blend_write(BlendWriter *writer, ID *id, const void *id_address)
84{
85 WorkSpace *workspace = (WorkSpace *)id;
86
87 BLO_write_id_struct(writer, WorkSpace, id_address, &workspace->id);
88 BKE_id_blend_write(writer, &workspace->id);
89 BLO_write_struct_list(writer, WorkSpaceLayout, &workspace->layouts);
91 BLO_write_struct_list(writer, wmOwnerID, &workspace->owner_ids);
92 BLO_write_struct_list(writer, bToolRef, &workspace->tools);
93 LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
94 if (tref->properties) {
95 IDP_BlendWrite(writer, tref->properties);
96 }
97 }
98
99 BKE_viewer_path_blend_write(writer, &workspace->viewer_path);
100}
101
103{
104 WorkSpace *workspace = (WorkSpace *)id;
105
106 BLO_read_struct_list(reader, WorkSpaceLayout, &workspace->layouts);
108 BLO_read_struct_list(reader, wmOwnerID, &workspace->owner_ids);
109 BLO_read_struct_list(reader, bToolRef, &workspace->tools);
110
112 /* Parent pointer does not belong to workspace data and is therefore restored in lib_link step
113 * of window manager. */
114 /* FIXME: Should not use that untyped #BLO_read_data_address call, especially since it's
115 * reference-counting the matching data in readfile code. Problem currently is that there is no
116 * type info available for this void pointer (_should_ be pointing to a #WorkSpaceLayout ?), so
117 * #BLO_read_get_new_data_address_no_us cannot be used here. */
118 BLO_read_data_address(reader, &relation->value);
119 }
120
121 LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
122 tref->runtime = nullptr;
123 BLO_read_struct(reader, IDProperty, &tref->properties);
124 IDP_BlendDataRead(reader, &tref->properties);
125 }
126
127 workspace->runtime = MEM_new<blender::bke::WorkSpaceRuntime>(__func__);
128
129 /* Do not keep the scene reference when appending a workspace. Setting a scene for a workspace is
130 * a convenience feature, but the workspace should never truly depend on scene data. */
131 if (ID_IS_LINKED(workspace)) {
132 workspace->pin_scene = nullptr;
133 }
134
135 id_us_ensure_real(&workspace->id);
136
137 BKE_viewer_path_blend_read_data(reader, &workspace->viewer_path);
138}
139
141{
142 WorkSpace *workspace = reinterpret_cast<WorkSpace *>(id);
143 Main *bmain = BLO_read_lib_get_main(reader);
144
145 /* Restore proper 'parent' pointers to relevant data, and clean up unused/invalid entries. */
147 relation->parent = nullptr;
148 LISTBASE_FOREACH (wmWindowManager *, wm, &bmain->wm) {
149 LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
150 if (win->winid == relation->parentid) {
151 relation->parent = win->workspace_hook;
152 }
153 }
154 }
155 if (relation->parent == nullptr) {
156 BLI_freelinkN(&workspace->hook_layout_relations, relation);
157 }
158 }
159
160 LISTBASE_FOREACH_MUTABLE (WorkSpaceLayout *, layout, &workspace->layouts) {
161 if (layout->screen) {
162 if (ID_IS_LINKED(id)) {
163 layout->screen->winid = 0;
164 if (layout->screen->temp) {
165 /* delete temp layouts when appending */
166 BKE_workspace_layout_remove(bmain, workspace, layout);
167 }
168 }
169 }
170 else {
171 /* If we're reading a layout without screen stored, it's useless and we shouldn't keep it
172 * around. */
173 BKE_workspace_layout_remove(bmain, workspace, layout);
174 }
175 }
176}
177
179 /*id_code*/ WorkSpace::id_type,
180 /*id_filter*/ FILTER_ID_WS,
181 /*dependencies_id_types*/ FILTER_ID_SCE,
182 /*main_listbase_index*/ INDEX_ID_WS,
183 /*struct_size*/ sizeof(WorkSpace),
184 /*name*/ "WorkSpace",
185 /*name_plural*/ N_("workspaces"),
186 /*translation_context*/ BLT_I18NCONTEXT_ID_WORKSPACE,
189 /*asset_type_info*/ nullptr,
190
191 /*init_data*/ workspace_init_data,
192 /*copy_data*/ nullptr,
193 /*free_data*/ workspace_free_data,
194 /*make_local*/ nullptr,
195 /*foreach_id*/ workspace_foreach_id,
196 /*foreach_cache*/ nullptr,
197 /*foreach_path*/ nullptr,
198 /*foreach_working_space_color*/ nullptr,
199 /*owner_pointer_get*/ nullptr,
200
201 /*blend_write*/ workspace_blend_write,
202 /*blend_read_data*/ workspace_blend_read_data,
203 /*blend_read_after_liblink*/ workspace_blend_read_after_liblink,
204
205 /*blend_read_undo_preserve*/ nullptr,
206
207 /*lib_override_apply_post*/ nullptr,
208};
209
210/* -------------------------------------------------------------------- */
213
215 WorkSpaceLayout *layout,
216 const char *new_name)
217{
218 STRNCPY(layout->name, new_name);
219 BLI_uniquename(&workspace->layouts,
220 layout,
221 "Layout",
222 '.',
224 sizeof(layout->name));
225}
226
233 const bScreen *screen)
234{
235 return static_cast<WorkSpaceLayout *>(
236 BLI_findptr(&workspace->layouts, screen, offsetof(WorkSpaceLayout, screen)));
237}
238
239static void workspace_relation_add(ListBase *relation_list,
240 void *parent,
241 const int parentid,
242 void *data)
243{
245 relation->parent = parent;
246 relation->parentid = parentid;
247 relation->value = data;
248 /* add to head, if we switch back to it soon we find it faster. */
249 BLI_addhead(relation_list, relation);
250}
251static void workspace_relation_remove(ListBase *relation_list, WorkSpaceDataRelation *relation)
252{
253 BLI_remlink(relation_list, relation);
254 MEM_freeN(relation);
255}
256
258 void *parent,
259 const int parentid,
260 void *data)
261{
263 relation_list, &parentid, sizeof(parentid), offsetof(WorkSpaceDataRelation, parentid)));
264 if (relation != nullptr) {
265 relation->parent = parent;
266 relation->value = data;
267 /* reinsert at the head of the list, so that more commonly used relations are found faster. */
268 BLI_remlink(relation_list, relation);
269 BLI_addhead(relation_list, relation);
270 }
271 else {
272 /* no matching relation found, add new one */
273 workspace_relation_add(relation_list, parent, parentid, data);
274 }
275}
276
278 const void *parent)
279{
280 WorkSpaceDataRelation *relation = static_cast<WorkSpaceDataRelation *>(
281 BLI_findptr(relation_list, parent, offsetof(WorkSpaceDataRelation, parent)));
282 if (relation != nullptr) {
283 return relation->value;
284 }
285
286 return nullptr;
287}
288
295#ifndef NDEBUG
297#else
299#endif
300 (const Main *bmain, bScreen *screen)
301{
302 for (WorkSpace *workspace = static_cast<WorkSpace *>(bmain->workspaces.first); workspace;
303 workspace = static_cast<WorkSpace *>(workspace->id.next))
304 {
305 if (workspace_layout_find_exec(workspace, screen)) {
306 return true;
307 }
308 }
309
310 return false;
311}
312
314
315/* -------------------------------------------------------------------- */
318
320{
321 WorkSpace *new_workspace = BKE_id_new<WorkSpace>(bmain, name);
322 id_us_ensure_real(&new_workspace->id);
323 return new_workspace;
324}
325
326void BKE_workspace_remove(Main *bmain, WorkSpace *workspace)
327{
328 for (WorkSpaceLayout *layout = static_cast<WorkSpaceLayout *>(workspace->layouts.first),
329 *layout_next;
330 layout;
331 layout = layout_next)
332 {
333 layout_next = layout->next;
334 BKE_workspace_layout_remove(bmain, workspace, layout);
335 }
336 BKE_id_free(bmain, workspace);
337}
338
340{
342
343 /* set an active screen-layout for each possible window/workspace combination */
344 for (WorkSpace *workspace = static_cast<WorkSpace *>(bmain->workspaces.first); workspace;
345 workspace = static_cast<WorkSpace *>(workspace->id.next))
346 {
348 hook, winid, workspace, static_cast<WorkSpaceLayout *>(workspace->layouts.first));
349 }
350
351 return hook;
352}
354{
355 /* workspaces should never be freed before wm (during which we call this function).
356 * However, when running in background mode, loading a blend file may allocate windows (that need
357 * to be freed) without creating workspaces. This happens in BlendfileLoadingBaseTest. */
358 BLI_assert(!BLI_listbase_is_empty(&bmain->workspaces) || G.background);
359
360 /* Free relations for this hook */
361 for (WorkSpace *workspace = static_cast<WorkSpace *>(bmain->workspaces.first); workspace;
362 workspace = static_cast<WorkSpace *>(workspace->id.next))
363 {
364 for (WorkSpaceDataRelation *relation = static_cast<WorkSpaceDataRelation *>(
365 workspace->hook_layout_relations.first),
366 *relation_next;
367 relation;
368 relation = relation_next)
369 {
370 relation_next = relation->next;
371 if (relation->parent == hook) {
372 workspace_relation_remove(&workspace->hook_layout_relations, relation);
373 }
374 }
375 }
376
377 MEM_freeN(hook);
378}
379
381 WorkSpace *workspace,
382 bScreen *screen,
383 const char *name)
384{
386
387 BLI_assert(!workspaces_is_screen_used(bmain, screen));
388#ifdef NDEBUG
389 UNUSED_VARS(bmain);
390#endif
391 layout->screen = screen;
392 id_us_plus(&layout->screen->id);
393 workspace_layout_name_set(workspace, layout, name);
394 BLI_addtail(&workspace->layouts, layout);
395
396 return layout;
397}
398
400{
401 /* Screen should usually be set, but we call this from file reading to get rid of invalid
402 * layouts. */
403 if (layout->screen) {
404 id_us_min(&layout->screen->id);
405 BKE_id_free(bmain, layout->screen);
406 }
407 BLI_freelinkN(&workspace->layouts, layout);
408}
409
411{
413 relation = static_cast<WorkSpaceDataRelation *>(relation_list->first),
414 *relation_next;
415 relation;
416 relation = relation_next)
417 {
418 relation_next = relation->next;
419 workspace_relation_remove(relation_list, relation);
420 }
421}
422
424
425/* -------------------------------------------------------------------- */
428
430{
431 WorkSpaceLayout *layout = workspace_layout_find_exec(workspace, screen);
432 if (layout) {
433 return layout;
434 }
435
436 printf(
437 "%s: Couldn't find layout in this workspace: '%s' screen: '%s'. "
438 "This should not happen!\n",
439 __func__,
440 workspace->id.name + 2,
441 screen->id.name + 2);
442
443 return nullptr;
444}
445
447 const bScreen *screen,
448 WorkSpace **r_workspace)
449{
450 if (r_workspace) {
451 *r_workspace = nullptr;
452 }
453
454 for (WorkSpace *workspace = static_cast<WorkSpace *>(bmain->workspaces.first); workspace;
455 workspace = static_cast<WorkSpace *>(workspace->id.next))
456 {
457 WorkSpaceLayout *layout = workspace_layout_find_exec(workspace, screen);
458 if (layout) {
459 if (r_workspace) {
460 *r_workspace = workspace;
461 }
462
463 return layout;
464 }
465 }
466
467 return nullptr;
468}
469
471 WorkSpaceLayout *start,
472 bool (*callback)(const WorkSpaceLayout *layout,
473 void *arg),
474 void *arg,
475 const bool iter_backward)
476{
477 WorkSpaceLayout *iter_layout;
478
479 if (iter_backward) {
480 LISTBASE_CIRCULAR_BACKWARD_BEGIN (WorkSpaceLayout *, &workspace->layouts, iter_layout, start) {
481 if (!callback(iter_layout, arg)) {
482 return iter_layout;
483 }
484 }
485 LISTBASE_CIRCULAR_BACKWARD_END(WorkSpaceLayout *, &workspace->layouts, iter_layout, start);
486 }
487 else {
488 LISTBASE_CIRCULAR_FORWARD_BEGIN (WorkSpaceLayout *, &workspace->layouts, iter_layout, start) {
489 if (!callback(iter_layout, arg)) {
490 return iter_layout;
491 }
492 }
493 LISTBASE_CIRCULAR_FORWARD_END(WorkSpaceLayout *, &workspace->layouts, iter_layout, start);
494 }
495
496 return nullptr;
497}
498
500{
501 if (tref->runtime) {
502 MEM_freeN(tref->runtime);
503 }
504 if (tref->properties) {
506 }
507 BLI_remlink(&workspace->tools, tref);
508 MEM_freeN(tref);
509}
510
512 const int space_type,
513 const int mode,
514 const char *idname_prefix_skip,
515 const char *replace_table[][2],
516 int replace_table_num)
517{
518 const size_t idname_prefix_len = idname_prefix_skip ? strlen(idname_prefix_skip) : 0;
519 const size_t idname_suffix_maxncpy = sizeof(bToolRef::idname) - idname_prefix_len;
520
521 LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
522 if (!(tref->space_type == space_type && tref->mode == mode)) {
523 continue;
524 }
525 char *idname_suffix = tref->idname;
526 if (idname_prefix_skip) {
527 if (!STRPREFIX(idname_suffix, idname_prefix_skip)) {
528 continue;
529 }
530 idname_suffix += idname_prefix_len;
531 }
533 idname_suffix, idname_suffix_maxncpy, replace_table, replace_table_num);
534 }
535}
536
537bool BKE_workspace_owner_id_check(const WorkSpace *workspace, const char *owner_id)
538{
539 if ((*owner_id == '\0') || ((workspace->flags & WORKSPACE_USE_FILTER_BY_ORIGIN) == 0)) {
540 return true;
541 }
542
543 /* We could use hash lookup, for now this list is highly likely under < ~16 items. */
544 return BLI_findstring(&workspace->owner_ids, owner_id, offsetof(wmOwnerID, name)) != nullptr;
545}
546
548{
549 BKE_main_id_tag_listbase(&bmain->workspaces, tag, false);
550 wmWindowManager *wm = static_cast<wmWindowManager *>(bmain->wm.first);
551 LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
552 WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook);
553 workspace->id.tag |= tag;
554 }
555}
556
558
559/* -------------------------------------------------------------------- */
562
568{
569 /* DO NOT check for `hook->active == workspace` here. Caller code is supposed to do it if
570 * that optimization is possible and needed.
571 * This code can be called from places where we might have this equality, but still want to
572 * ensure/update the active layout below.
573 * Known case where this is buggy and will crash later due to nullptr active layout: reading
574 * a blend file, when the new read workspace ID happens to have the exact same memory address
575 * as when it was saved in the blend file (extremely unlikely, but possible). */
576
577 hook->active = workspace;
578 if (workspace) {
579 WorkSpaceLayout *layout = static_cast<WorkSpaceLayout *>(
581 if (layout) {
582 hook->act_layout = layout;
583 }
584 }
585}
586
591
593 const WorkSpace *workspace)
594{
595 /* If the workspace is active, the active layout can be returned, no need for a lookup. */
596 if (hook->active == workspace) {
597 return hook->act_layout;
598 }
599
600 /* Inactive workspace */
601 return static_cast<WorkSpaceLayout *>(
603}
604
606 const int winid,
607 WorkSpace *workspace,
608 WorkSpaceLayout *layout)
609{
610 hook->act_layout = layout;
612}
613
619 const int winid,
620 WorkSpace *workspace,
621 bScreen *screen)
622{
623 /* we need to find the WorkspaceLayout that wraps this screen */
624 WorkSpaceLayout *layout = BKE_workspace_layout_find(hook->active, screen);
625 BKE_workspace_active_layout_set(hook, winid, workspace, layout);
626}
627
629{
630 return layout->name;
631}
633 WorkSpaceLayout *layout,
634 const char *new_name)
635{
636 workspace_layout_name_set(workspace, layout, new_name);
637}
638
640{
641 return layout->screen;
642}
643
645
646/* -------------------------------------------------------------------- */
649
651{
652 workspace->runtime->status.clear_and_shrink();
653}
654
void BKE_asset_library_reference_init_default(AssetLibraryReference *library_ref)
Definition asset.cc:149
#define IDP_BlendDataRead(reader, prop)
void IDP_FreeProperty(IDProperty *prop)
Definition idprop.cc:1251
void IDP_BlendWrite(BlendWriter *writer, const IDProperty *prop)
Definition idprop.cc:1461
IDTypeInfo IDType_ID_WS
Definition workspace.cc:178
@ IDTYPE_FLAGS_NO_ANIMDATA
Definition BKE_idtype.hh:49
@ IDTYPE_FLAGS_ONLY_APPEND
Definition BKE_idtype.hh:41
@ IDTYPE_FLAGS_NO_COPY
Definition BKE_idtype.hh:33
@ IDTYPE_FLAGS_NO_MEMFILE_UNDO
Definition BKE_idtype.hh:58
@ IDTYPE_FLAGS_NEVER_UNUSED
Definition BKE_idtype.hh:72
void BKE_id_free(Main *bmain, void *idv)
void id_us_plus(ID *id)
Definition lib_id.cc:358
void id_us_ensure_real(ID *id)
Definition lib_id.cc:313
void * BKE_id_new(Main *bmain, short type, const char *name)
Definition lib_id.cc:1514
void id_us_min(ID *id)
Definition lib_id.cc:366
void BKE_main_id_tag_listbase(ListBase *lb, int tag, bool value)
Definition lib_id.cc:1201
void BKE_id_blend_write(BlendWriter *writer, ID *id)
Definition lib_id.cc:2631
#define BKE_LIB_FOREACHID_PROCESS_IDSUPER(data_, id_super_, cb_flag_)
@ IDWALK_CB_USER
@ IDWALK_CB_DIRECT_WEAK_LINK
void BKE_viewer_path_foreach_id(LibraryForeachIDData *data, ViewerPath *viewer_path)
void BKE_viewer_path_clear(ViewerPath *viewer_path)
void BKE_viewer_path_blend_read_data(BlendDataReader *reader, ViewerPath *viewer_path)
void BKE_viewer_path_blend_write(BlendWriter *writer, const ViewerPath *viewer_path)
#define BLI_assert(a)
Definition BLI_assert.h:46
#define LISTBASE_FOREACH(type, var, list)
void * BLI_findstring(const ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:608
#define LISTBASE_CIRCULAR_BACKWARD_END(type, lb, lb_iter, lb_init)
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
#define LISTBASE_CIRCULAR_FORWARD_BEGIN(type, lb, lb_iter, lb_init)
void BLI_freelinkN(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:270
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
void void BLI_freelistN(ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:497
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
void BLI_remlink(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:131
void BLI_addhead(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:91
void * BLI_findptr(const struct ListBase *listbase, const void *ptr, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define LISTBASE_CIRCULAR_BACKWARD_BEGIN(type, lb, lb_iter, lb_init)
void * BLI_listbase_bytes_find(const ListBase *listbase, const void *bytes, size_t bytes_size, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
#define LISTBASE_CIRCULAR_FORWARD_END(type, lb, lb_iter, lb_init)
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:693
bool BLI_string_replace_table_exact(char *string, size_t string_maxncpy, const char *replace_table[][2], int replace_table_len)
void BLI_uniquename(const struct ListBase *list, void *vlink, const char *defname, char delim, int name_offset, size_t name_maxncpy) ATTR_NONNULL(1
#define UNUSED_FUNCTION(x)
#define STRPREFIX(a, b)
#define UNUSED_VARS(...)
#define BLO_read_data_address(reader, ptr_p)
Main * BLO_read_lib_get_main(BlendLibReader *reader)
Definition readfile.cc:5988
#define BLO_write_id_struct(writer, struct_name, id_address, id)
#define BLO_read_struct_list(reader, struct_name, list)
#define BLO_write_struct_list(writer, struct_name, list_ptr)
#define BLO_read_struct(reader, struct_name, ptr_p)
#define BLT_I18NCONTEXT_ID_WORKSPACE
#define FILTER_ID_WS
Definition DNA_ID.h:1226
#define ID_IS_LINKED(_id)
Definition DNA_ID.h:694
@ INDEX_ID_WS
Definition DNA_ID.h:1353
#define FILTER_ID_SCE
Definition DNA_ID.h:1217
@ WORKSPACE_USE_FILTER_BY_ORIGIN
Read Guarded memory(de)allocation.
BMesh const char void * data
#define offsetof(t, d)
#define printf(...)
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
#define G(x, y, z)
const char * name
Definition DNA_ID.h:414
int tag
Definition DNA_ID.h:442
char name[258]
Definition DNA_ID.h:432
void * first
ListBase wm
Definition BKE_main.hh:307
ListBase workspaces
Definition BKE_main.hh:315
struct WorkSpaceLayout * act_layout
Wrapper for bScreen.
struct bScreen * screen
AssetLibraryReference asset_library_ref
struct Scene * sequencer_scene
WorkSpaceRuntimeHandle * runtime
ListBase hook_layout_relations
ViewerPath viewer_path
struct Scene * pin_scene
IDProperty * properties
bToolRef_Runtime * runtime
#define N_(msgid)
int winid
Definition wm_draw.cc:177
static void workspace_relation_ensure_updated(ListBase *relation_list, void *parent, const int parentid, void *data)
Definition workspace.cc:257
static void workspace_relation_remove(ListBase *relation_list, WorkSpaceDataRelation *relation)
Definition workspace.cc:251
static void workspace_free_data(ID *id)
Definition workspace.cc:50
static void workspace_layout_name_set(WorkSpace *workspace, WorkSpaceLayout *layout, const char *new_name)
Definition workspace.cc:214
static void workspace_blend_read_after_liblink(BlendLibReader *reader, ID *id)
Definition workspace.cc:140
static void workspace_blend_write(BlendWriter *writer, ID *id, const void *id_address)
Definition workspace.cc:83
const char * BKE_workspace_layout_name_get(const WorkSpaceLayout *layout)
Definition workspace.cc:628
static bool workspaces_is_screen_used(const Main *bmain, bScreen *screen)
Definition workspace.cc:300
WorkSpace * BKE_workspace_add(Main *bmain, const char *name)
Definition workspace.cc:319
void BKE_workspace_layout_remove(Main *bmain, WorkSpace *workspace, WorkSpaceLayout *layout)
Definition workspace.cc:399
static void workspace_foreach_id(ID *id, LibraryForeachIDData *data)
Definition workspace.cc:69
bool BKE_workspace_owner_id_check(const WorkSpace *workspace, const char *owner_id)
Definition workspace.cc:537
bScreen * BKE_workspace_layout_screen_get(const WorkSpaceLayout *layout)
Definition workspace.cc:639
void BKE_workspace_active_screen_set(WorkSpaceInstanceHook *hook, const int winid, WorkSpace *workspace, bScreen *screen)
Definition workspace.cc:618
WorkSpaceLayout * BKE_workspace_layout_find(const WorkSpace *workspace, const bScreen *screen)
Definition workspace.cc:429
void BKE_workspace_status_clear(WorkSpace *workspace)
Definition workspace.cc:650
WorkSpaceLayout * BKE_workspace_layout_add(Main *bmain, WorkSpace *workspace, bScreen *screen, const char *name)
Definition workspace.cc:380
bScreen * BKE_workspace_active_screen_get(const WorkSpaceInstanceHook *hook)
Definition workspace.cc:614
static void workspace_relation_add(ListBase *relation_list, void *parent, const int parentid, void *data)
Definition workspace.cc:239
void BKE_workspace_instance_hook_free(const Main *bmain, WorkSpaceInstanceHook *hook)
Definition workspace.cc:353
WorkSpaceLayout * BKE_workspace_active_layout_for_workspace_get(const WorkSpaceInstanceHook *hook, const WorkSpace *workspace)
Definition workspace.cc:592
static void workspace_init_data(ID *id)
Definition workspace.cc:41
void BKE_workspace_active_set(WorkSpaceInstanceHook *hook, WorkSpace *workspace)
Definition workspace.cc:567
WorkSpaceLayout * BKE_workspace_layout_find_global(const Main *bmain, const bScreen *screen, WorkSpace **r_workspace)
Definition workspace.cc:446
WorkSpaceLayout * BKE_workspace_layout_iter_circular(const WorkSpace *workspace, WorkSpaceLayout *start, bool(*callback)(const WorkSpaceLayout *layout, void *arg), void *arg, const bool iter_backward)
Definition workspace.cc:470
void BKE_workspace_id_tag_all_visible(Main *bmain, int tag)
Definition workspace.cc:547
void BKE_workspace_relations_free(ListBase *relation_list)
Definition workspace.cc:410
void BKE_workspace_remove(Main *bmain, WorkSpace *workspace)
Definition workspace.cc:326
void BKE_workspace_active_layout_set(WorkSpaceInstanceHook *hook, const int winid, WorkSpace *workspace, WorkSpaceLayout *layout)
Activate a layout.
Definition workspace.cc:605
void BKE_workspace_tool_id_replace_table(WorkSpace *workspace, const int space_type, const int mode, const char *idname_prefix_skip, const char *replace_table[][2], int replace_table_num)
Definition workspace.cc:511
static void workspace_blend_read_data(BlendDataReader *reader, ID *id)
Definition workspace.cc:102
WorkSpaceInstanceHook * BKE_workspace_instance_hook_create(const Main *bmain, const int winid)
Definition workspace.cc:339
void BKE_workspace_layout_name_set(WorkSpace *workspace, WorkSpaceLayout *layout, const char *new_name)
Definition workspace.cc:632
WorkSpace * BKE_workspace_active_get(WorkSpaceInstanceHook *hook)
Definition workspace.cc:563
static WorkSpaceLayout * workspace_layout_find_exec(const WorkSpace *workspace, const bScreen *screen)
Definition workspace.cc:232
WorkSpaceLayout * BKE_workspace_active_layout_get(const WorkSpaceInstanceHook *hook)
Definition workspace.cc:587
static void * workspace_relation_get_data_matching_parent(const ListBase *relation_list, const void *parent)
Definition workspace.cc:277
void BKE_workspace_tool_remove(WorkSpace *workspace, bToolRef *tref)
Definition workspace.cc:499