Blender V5.0
workspace_edit.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 <cstdlib>
10#include <cstring>
11
12#include <fmt/format.h>
13
14#include "BLI_fileops.h"
15#include "BLI_listbase.h"
16#include "BLI_path_utils.hh"
17#include "BLI_string.h"
18#include "BLI_utildefines.h"
19
20#include "BKE_appdir.hh"
21#include "BKE_blendfile.hh"
22#include "BKE_context.hh"
23#include "BKE_layer.hh"
24#include "BKE_lib_id.hh"
25#include "BKE_main.hh"
26#include "BKE_screen.hh"
27#include "BKE_workspace.hh"
28
29#include "BLO_readfile.hh"
30
31#include "DNA_screen_types.h"
33#include "DNA_workspace_types.h"
34
35#include "ED_datafiles.h"
36#include "ED_object.hh"
37#include "ED_screen.hh"
38
39#include "RNA_access.hh"
40#include "RNA_define.hh"
41
42#include "UI_interface.hh"
44#include "UI_resources.hh"
45
46#include "BLT_translation.hh"
47
48#include "WM_api.hh"
49#include "WM_types.hh"
50
51#include "screen_intern.hh"
52
53using blender::Vector;
54
55/* -------------------------------------------------------------------- */
60
61WorkSpace *ED_workspace_add(Main *bmain, const char *name)
62{
63 return BKE_workspace_add(bmain, name);
64}
65
66static void workspace_exit(WorkSpace *workspace, wmWindow *win)
67{
68 /* Scene pinning: Store whatever scene was active when leaving the workspace. It's reactivated
69 * when the workspace gets reactivated as well. */
70 if (workspace->flags & WORKSPACE_USE_PIN_SCENE) {
71 workspace->pin_scene = WM_window_get_active_scene(win);
72 }
73 else {
74 /* The active scene may have been changed. So also always update the unpinned scene to the
75 * latest when leaving a workspace that has no scene pinning. */
77 }
78}
79
95static void workspace_scene_pinning_update(WorkSpace *workspace_new,
96 const WorkSpace *workspace_old,
97 bContext *C)
98{
99 wmWindow *win = CTX_wm_window(C);
100 Main *bmain = CTX_data_main(C);
101 Scene *active_scene = WM_window_get_active_scene(win);
102
103 const bool is_new_pinned = (workspace_new->flags & WORKSPACE_USE_PIN_SCENE);
104 const bool is_old_pinned = (workspace_old->flags & WORKSPACE_USE_PIN_SCENE);
105
106 /* State changes 1 and 2. */
107 if (is_new_pinned) {
108 if (workspace_new->pin_scene && (workspace_new->pin_scene != active_scene)) {
109 WM_window_set_active_scene(bmain, C, win, workspace_new->pin_scene);
110 workspace_new->pin_scene = nullptr;
111 }
112 }
113 /* State change 3 - Changing from workspace with pinned scene to unpinned scene. */
114 else if (is_old_pinned) {
115 if (win->unpinned_scene) {
117 }
118 else {
119 /* When leaving a workspace where the pinning was just enabled, the unpinned scene wasn't set
120 * yet. */
121 win->unpinned_scene = active_scene;
122 }
123 }
124 else {
125 /* When leaving a workspace where the pinning was just disabled, we still want to restore the
126 * unpinned scene. */
127 if (win->unpinned_scene) {
129 }
130 }
131
133}
134
139static void workspace_change_update(WorkSpace *workspace_new,
140 WorkSpace *workspace_old,
141 bContext *C,
142 wmWindowManager *wm)
143{
144 workspace_scene_pinning_update(workspace_new, workspace_old, C);
145 /* needs to be done before changing mode! (to ensure right context) */
146 UNUSED_VARS(wm);
147#if 0
149 eObjectMode mode_old = workspace_old->object_mode;
150 eObjectMode mode_new = workspace_new->object_mode;
151
152 if (mode_old != mode_new) {
154 }
155#endif
156}
157
159 WorkSpace *workspace_new,
160 wmWindow *win)
161{
163 WorkSpaceLayout *layout_new;
164
165 /* ED_workspace_duplicate may have stored a layout to activate
166 * once the workspace gets activated. */
168 layout_new = win->workspace_hook->temp_layout_store;
169 }
170 else {
171 layout_new = BKE_workspace_active_layout_for_workspace_get(win->workspace_hook, workspace_new);
172 if (!layout_new) {
173 layout_new = static_cast<WorkSpaceLayout *>(workspace_new->layouts.first);
174 }
175 }
176
178 bmain, workspace_new, layout_new, layout_old, win);
179}
180
182{
183 Main *bmain = CTX_data_main(C);
184 WorkSpace *workspace_old = WM_window_get_active_workspace(win);
185 WorkSpaceLayout *layout_new = workspace_change_get_new_layout(bmain, workspace_new, win);
186 bScreen *screen_new = BKE_workspace_layout_screen_get(layout_new);
188
189 win->workspace_hook->temp_layout_store = nullptr;
190 if (workspace_old == workspace_new) {
191 /* Could also return true, everything that needs to be done was done (nothing :P),
192 * but nothing changed */
193 return false;
194 }
195
196 workspace_exit(workspace_old, win);
197
198 screen_change_prepare(screen_old, screen_new, bmain, C, win);
199
200 if (screen_new == nullptr) {
201 return false;
202 }
203
204 BKE_workspace_active_layout_set(win->workspace_hook, win->winid, workspace_new, layout_new);
205 BKE_workspace_active_set(win->workspace_hook, workspace_new);
206
207 /* update screen *after* changing workspace - which also causes the
208 * actual screen change and updates context (including CTX_wm_workspace) */
209 screen_change_update(C, win, screen_new);
210 workspace_change_update(workspace_new, workspace_old, C, wm);
211
212 BLI_assert(CTX_wm_workspace(C) == workspace_new);
213
214 /* Automatic mode switching. */
215 if (workspace_new->object_mode != workspace_old->object_mode) {
216 const Object *object = nullptr;
217 if (const Base *base = CTX_data_active_base(C)) {
218 object = base->object;
219 /* Behavior that depends on the active area is not expected in the context of workspace
220 * switching, ignore the view-port even if it's available. */
221 const View3D *v3d = nullptr;
222
223 const bool base_visible = BKE_base_is_visible(v3d, base);
224 if (!base_visible && object->mode == OB_MODE_OBJECT) {
225 /* Set this to nullptr to indicate that the mode should not be switched. This matches
226 * CTX_data_active_object behavior in the 3D Viewport. See `view3d_context` for more
227 * details. */
228 object = nullptr;
229 }
230 }
231
232 if (object) {
234 }
235 }
236
237 return true;
238}
239
241{
243 WorkSpace *workspace_new = ED_workspace_add(bmain, workspace_old->id.name + 2);
244
245 workspace_new->flags = workspace_old->flags;
246 workspace_new->pin_scene = workspace_old->pin_scene;
247 workspace_new->sequencer_scene = workspace_old->sequencer_scene;
248 workspace_new->object_mode = workspace_old->object_mode;
249 workspace_new->order = workspace_old->order;
250 BLI_duplicatelist(&workspace_new->owner_ids, &workspace_old->owner_ids);
251
252 /* TODO(@ideasman42): tools */
253
254 LISTBASE_FOREACH (WorkSpaceLayout *, layout_old, &workspace_old->layouts) {
256 bmain, workspace_new, layout_old, win);
257
258 if (layout_active_old == layout_old) {
259 win->workspace_hook->temp_layout_store = layout_new;
260 }
261 }
262 return workspace_new;
263}
264
266{
267 if (BLI_listbase_is_single(&bmain->workspaces)) {
268 return false;
269 }
270
272 const int index = ordered.first_index_of(&workspace->id);
273
274 WorkSpace *new_active = reinterpret_cast<WorkSpace *>(index == 0 ? ordered[1] :
275 ordered[index - 1]);
276
277 LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
278 WorkSpace *workspace_active = WM_window_get_active_workspace(win);
279 if (workspace_active == workspace) {
280 ED_workspace_change(new_active, C, wm, win);
281 }
282 }
283
284 /* Also delete managed screens if they have no other users. */
285 LISTBASE_FOREACH (WorkSpaceLayout *, layout, &workspace->layouts) {
286 BKE_id_free_us(bmain, layout->screen);
287 layout->screen = nullptr;
288 }
289
290 BKE_id_free(bmain, &workspace->id);
291 return true;
292}
293
299
301
302/* -------------------------------------------------------------------- */
305
307{
309 if (id && GS(id->name) == ID_WS) {
310 return (WorkSpace *)id;
311 }
312
313 return CTX_wm_workspace(C);
314}
315
317{
318 return workspace_context_get(C) != nullptr;
319}
320
322{
323 Main *bmain = CTX_data_main(C);
324 wmWindow *win = CTX_wm_window(C);
325 WorkSpace *workspace = workspace_context_get(C);
326
327 workspace = ED_workspace_duplicate(workspace, bmain, win);
328
330
331 return OPERATOR_FINISHED;
332}
333
335{
336 /* identifiers */
337 ot->name = "New Workspace";
338 ot->description = "Add a new workspace";
339 ot->idname = "WORKSPACE_OT_duplicate";
340
341 /* API callbacks. */
343 ot->exec = workspace_new_exec;
344}
345
354
356{
357 /* identifiers */
358 ot->name = "Delete Workspace";
359 ot->description = "Delete the active workspace";
360 ot->idname = "WORKSPACE_OT_delete";
361
362 /* API callbacks. */
365}
366
368{
369 Main *bmain = CTX_data_main(C);
370 WorkSpace *workspace = workspace_context_get(C);
371
372 LISTBASE_FOREACH (WorkSpace *, ws, &bmain->workspaces) {
373 if (ws != workspace) {
376 }
377 }
378
379 return OPERATOR_FINISHED;
380}
381
383{
384 /* identifiers */
385 ot->name = "Delete Other Workspaces";
386 ot->description = "Delete all workspaces except this one";
387 ot->idname = "WORKSPACE_OT_delete_all_others";
388
389 /* api callbacks */
392}
393
395{
396 Main *bmain = CTX_data_main(C);
397 char idname[MAX_ID_NAME - 2], filepath[FILE_MAX];
398
399 if (!RNA_struct_property_is_set(op->ptr, "idname") ||
400 !RNA_struct_property_is_set(op->ptr, "filepath"))
401 {
402 return OPERATOR_CANCELLED;
403 }
404 RNA_string_get(op->ptr, "idname", idname);
405 RNA_string_get(op->ptr, "filepath", filepath);
406
407 WorkSpace *appended_workspace = nullptr;
408 /* NOTE: Need to check `filepath`, in the rare case where the usual source of work-spaces
409 * (the startup blend-file) is the one currently open (see #144305). */
410 const char *blendfile_path = BKE_main_blendfile_path(bmain);
411 if ((blendfile_path[0] != '\0') && (BLI_path_cmp(blendfile_path, filepath) == 0)) {
412 appended_workspace = reinterpret_cast<WorkSpace *>(
413 BKE_libblock_find_name(bmain, ID_WS, idname, nullptr));
414 if (appended_workspace) {
415 /* Copy, to mimic behavior when appending from another file (which always creates a new copy
416 * of the data). */
417 appended_workspace = ED_workspace_duplicate(appended_workspace, bmain, CTX_wm_window(C));
418 }
419 }
420 else {
421 appended_workspace = reinterpret_cast<WorkSpace *>(
426 filepath,
427 ID_WS,
428 idname,
430 }
431
432 if (appended_workspace) {
433 /* Translate workspace name, unless it was taken from current blendfile. */
436 *bmain, appended_workspace->id, CTX_DATA_(BLT_I18NCONTEXT_ID_WORKSPACE, idname));
437 }
438
439 /* Set defaults. */
440 BLO_update_defaults_workspace(appended_workspace, nullptr);
441
442 /* Reorder to last position. */
443 BKE_id_reorder(&bmain->workspaces, &appended_workspace->id, nullptr, true);
444
445 /* Changing workspace changes context. Do delayed! */
446 WM_event_add_notifier(C, NC_SCREEN | ND_WORKSPACE_SET, appended_workspace);
447
448 return OPERATOR_FINISHED;
449 }
450
451 return OPERATOR_CANCELLED;
452}
453
455{
456 /* identifiers */
457 ot->name = "Append and Activate Workspace";
458 ot->description = "Append a workspace and make it the active one in the current window";
459 ot->idname = "WORKSPACE_OT_append_activate";
460
461 /* API callbacks. */
463
464 PropertyRNA *prop;
465 RNA_def_string(ot->srna,
466 "idname",
467 nullptr,
468 MAX_ID_NAME - 2,
469 "Identifier",
470 "Name of the workspace to append and activate");
471 prop = RNA_def_string(
472 ot->srna, "filepath", nullptr, FILE_MAX, "Filepath", "Path to the library");
475}
476
478{
479 const std::optional<std::string> cfgdir = BKE_appdir_folder_id(BLENDER_USER_CONFIG,
481 char startup_file_path[FILE_MAX] = {0};
482
483 if (cfgdir.has_value()) {
485 startup_file_path, sizeof(startup_file_path), cfgdir->c_str(), BLENDER_STARTUP_FILE);
486 }
487
488 bool has_path = BLI_exists(startup_file_path);
489 return (has_path) ? BKE_blendfile_workspace_config_read(startup_file_path, nullptr, 0, nullptr) :
490 nullptr;
491}
492
494{
495 if (app_template == nullptr) {
498 }
499
500 char template_dir[FILE_MAX];
501 if (!BKE_appdir_app_template_id_search(app_template, template_dir, sizeof(template_dir))) {
502 return nullptr;
503 }
504
505 char startup_file_path[FILE_MAX];
506 BLI_path_join(startup_file_path, sizeof(startup_file_path), template_dir, BLENDER_STARTUP_FILE);
507
508 bool has_path = BLI_exists(startup_file_path);
509 return (has_path) ? BKE_blendfile_workspace_config_read(startup_file_path, nullptr, 0, nullptr) :
510 nullptr;
511}
512
514 wmOperatorType *ot_append,
515 const WorkSpace *workspace,
516 const Main *from_main)
517{
518 const ID *id = (ID *)workspace;
519 const char *filepath = from_main->filepath;
520
521 if (filepath[0] == '\0') {
523 }
524
525 BLI_assert(STREQ(ot_append->idname, "WORKSPACE_OT_append_activate"));
526
527 PointerRNA opptr;
528 opptr = layout->op(ot_append,
530 ICON_NONE,
533 RNA_string_set(&opptr, "idname", id->name + 2);
534 RNA_string_set(&opptr, "filepath", filepath);
535}
536
537static void workspace_add_menu(bContext * /*C*/, uiLayout *layout, void *template_v)
538{
539 const char *app_template = static_cast<const char *>(template_v);
540 bool has_startup_items = false;
541
542 wmOperatorType *ot_append = WM_operatortype_find("WORKSPACE_OT_append_activate", true);
545
546 if (startup_config) {
547 LISTBASE_FOREACH (WorkSpace *, workspace, &startup_config->workspaces) {
548 uiLayout *row = &layout->row(false);
549 workspace_append_button(row, ot_append, workspace, startup_config->main);
550 has_startup_items = true;
551 }
552 }
553
554 if (builtin_config) {
555 bool has_title = false;
556
557 LISTBASE_FOREACH (WorkSpace *, workspace, &builtin_config->workspaces) {
558 if (startup_config &&
559 BLI_findstring(&startup_config->workspaces, workspace->id.name, offsetof(ID, name)))
560 {
561 continue;
562 }
563
564 if (!has_title) {
565 if (has_startup_items) {
566 layout->separator();
567 }
568 has_title = true;
569 }
570
571 uiLayout *row = &layout->row(false);
572 workspace_append_button(row, ot_append, workspace, builtin_config->main);
573 }
574 }
575
576 if (startup_config) {
578 }
579 if (builtin_config) {
581 }
582}
583
585 wmOperator *op,
586 const wmEvent * /*event*/)
587{
590 uiLayout *layout = UI_popup_menu_layout(pup);
591
592 layout->menu_fn(IFACE_("General"), ICON_NONE, workspace_add_menu, nullptr);
593
594 ListBase templates;
595 BKE_appdir_app_templates(&templates);
596
597 LISTBASE_FOREACH (LinkData *, link, &templates) {
598 char *app_template = static_cast<char *>(link->data);
599 char display_name[FILE_MAX];
600
601 BLI_path_to_display_name(display_name, sizeof(display_name), IFACE_(app_template));
602
603 /* Steals ownership of link data string. */
604 layout->menu_fn_argN_free(display_name, ICON_NONE, workspace_add_menu, app_template);
605 }
606
607 BLI_freelistN(&templates);
608
609 layout->separator();
610 layout->op("WORKSPACE_OT_duplicate",
611 CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Duplicate Current"),
612 ICON_DUPLICATE);
613
614 UI_popup_menu_end(C, pup);
615
616 return OPERATOR_INTERFACE;
617}
618
620{
621 /* identifiers */
622 ot->name = "Add Workspace";
623 ot->description =
624 "Add a new workspace by duplicating the current one or appending one "
625 "from the user configuration";
626 ot->idname = "WORKSPACE_OT_add";
627
628 /* API callbacks. */
629 ot->invoke = workspace_add_invoke;
630}
631
633{
634 Main *bmain = CTX_data_main(C);
635 WorkSpace *workspace = workspace_context_get(C);
636
637 BKE_id_reorder(&bmain->workspaces, &workspace->id, nullptr, true);
639
640 return OPERATOR_INTERFACE;
641}
642
644{
645 /* identifiers */
646 ot->name = "Workspace Reorder to Back";
647 ot->description = "Reorder workspace to be last in the list";
648 ot->idname = "WORKSPACE_OT_reorder_to_back";
649
650 /* API callbacks. */
653}
654
656{
657 Main *bmain = CTX_data_main(C);
658 WorkSpace *workspace = workspace_context_get(C);
659
660 BKE_id_reorder(&bmain->workspaces, &workspace->id, nullptr, false);
662
663 return OPERATOR_INTERFACE;
664}
665
667{
668 /* identifiers */
669 ot->name = "Workspace Reorder to Front";
670 ot->description = "Reorder workspace to be first in the list";
671 ot->idname = "WORKSPACE_OT_reorder_to_front";
672
673 /* API callbacks. */
676}
677
679{
680 WorkSpace *workspace = workspace_context_get(C);
681
682 /* Trivial. The operator is only needed to display a superimposed extra icon, which
683 * requires an operator. */
684 workspace->flags ^= WORKSPACE_USE_PIN_SCENE;
685
687
688 return OPERATOR_FINISHED;
689}
690
692{
693 /* identifiers */
694 ot->name = "Pin Scene to Workspace";
695 ot->description =
696 "Remember the last used scene for the current workspace and switch to it whenever this "
697 "workspace is activated again";
698 ot->idname = "WORKSPACE_OT_scene_pin_toggle";
699
700 /* API callbacks. */
703
704 ot->flag = OPTYPE_INTERNAL;
705}
706
718
bool BKE_appdir_app_template_id_search(const char *app_template, char *path, size_t path_maxncpy) ATTR_NONNULL(1)
Definition appdir.cc:1082
void BKE_appdir_app_templates(ListBase *templates) ATTR_NONNULL(1)
Definition appdir.cc:1116
std::optional< std::string > BKE_appdir_folder_id(int folder_id, const char *subfolder) ATTR_WARN_UNUSED_RESULT
Definition appdir.cc:721
#define BLENDER_STARTUP_FILE
@ BLENDER_USER_CONFIG
WorkspaceConfigFileData * BKE_blendfile_workspace_config_read(const char *filepath, const void *file_buf, int file_buf_size, ReportList *reports)
void BKE_blendfile_workspace_config_data_free(WorkspaceConfigFileData *workspace_config)
WorkSpace * CTX_wm_workspace(const bContext *C)
wmWindow * CTX_wm_window(const bContext *C)
Object * CTX_data_active_object(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Base * CTX_data_active_base(const bContext *C)
Main * CTX_data_main(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
bool BKE_base_is_visible(const View3D *v3d, const Base *base)
ID * BKE_libblock_find_name(Main *bmain, short type, const char *name, const std::optional< Library * > lib=std::nullopt) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition lib_id.cc:1710
void BKE_id_free_us(Main *bmain, void *idv) ATTR_NONNULL()
void BKE_id_free(Main *bmain, void *idv)
void BKE_id_reorder(const ListBase *lb, ID *id, ID *relative, bool after)
Definition lib_id.cc:2595
blender::Vector< ID * > BKE_id_ordered_list(const ListBase *lb)
Definition lib_id.cc:2576
IDNewNameResult BKE_libblock_rename(Main &bmain, ID &id, blender::StringRefNull name, const IDNewNameMode mode=IDNewNameMode::RenameExistingNever)
Definition lib_id.cc:2370
const char * BKE_main_blendfile_path(const Main *bmain) ATTR_NONNULL()
Definition main.cc:887
void BKE_screen_view3d_scene_sync(bScreen *screen, Scene *scene)
Definition screen.cc:1004
WorkSpace * BKE_workspace_add(Main *bmain, const char *name)
Definition workspace.cc:319
bScreen * BKE_workspace_layout_screen_get(const WorkSpaceLayout *layout) GETTER_ATTRS
Definition workspace.cc:639
void BKE_workspace_active_layout_set(WorkSpaceInstanceHook *hook, int winid, WorkSpace *workspace, WorkSpaceLayout *layout) SETTER_ATTRS
Activate a layout.
Definition workspace.cc:605
bScreen * BKE_workspace_active_screen_get(const WorkSpaceInstanceHook *hook) GETTER_ATTRS
Definition workspace.cc:614
WorkSpaceLayout * BKE_workspace_active_layout_for_workspace_get(const WorkSpaceInstanceHook *hook, const WorkSpace *workspace) GETTER_ATTRS
Definition workspace.cc:592
void BKE_workspace_active_set(WorkSpaceInstanceHook *hook, WorkSpace *workspace) SETTER_ATTRS
Definition workspace.cc:567
WorkSpaceLayout * BKE_workspace_active_layout_get(const WorkSpaceInstanceHook *hook) GETTER_ATTRS
Definition workspace.cc:587
#define BLI_assert(a)
Definition BLI_assert.h:46
File and directory operations.
int BLI_exists(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition storage.cc:360
#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
void void BLI_freelistN(ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:497
void void void void void void BLI_duplicatelist(ListBase *dst, const ListBase *src) ATTR_NONNULL(1
void void BLI_INLINE bool BLI_listbase_is_single(const ListBase *lb)
void BLI_path_to_display_name(char *display_name, int display_name_maxncpy, const char *name) ATTR_NONNULL(1
#define FILE_MAX
#define BLI_path_join(...)
#define BLI_path_cmp
#define UNUSED_VARS(...)
#define STREQ(a, b)
external readfile function prototypes.
void BLO_update_defaults_workspace(WorkSpace *workspace, const char *app_template)
@ BLO_LIBLINK_APPEND_RECURSIVE
#define BLO_EMBEDDED_STARTUP_BLEND
bool BLT_translate_new_dataname()
#define BLT_I18NCONTEXT_ID_WORKSPACE
#define CTX_IFACE_(context, msgid)
#define BLT_I18NCONTEXT_OPERATOR_DEFAULT
#define CTX_DATA_(context, msgid)
#define IFACE_(msgid)
#define MAX_ID_NAME
Definition DNA_ID.h:373
@ ID_WS
eObjectMode
@ OB_MODE_OBJECT
@ OPERATOR_CANCELLED
@ OPERATOR_INTERFACE
@ OPERATOR_FINISHED
@ WORKSPACE_USE_PIN_SCENE
int datatoc_startup_blend_size
const char datatoc_startup_blend[]
WorkSpaceLayout * ED_workspace_screen_change_ensure_unused_layout(Main *bmain, WorkSpace *workspace, WorkSpaceLayout *layout_new, const WorkSpaceLayout *layout_fallback_base, wmWindow *win) ATTR_NONNULL()
WorkSpaceLayout * ED_workspace_layout_duplicate(Main *bmain, WorkSpace *workspace, const WorkSpaceLayout *layout_old, wmWindow *win) ATTR_NONNULL()
@ PROP_PATH_SUPPORTS_BLEND_RELATIVE
Definition RNA_types.hh:456
@ PROP_FILEPATH
Definition RNA_types.hh:236
#define C
Definition RandGen.cpp:29
void UI_popup_menu_end(bContext *C, uiPopupMenu *pup)
ID * UI_context_active_but_get_tab_ID(bContext *C)
uiPopupMenu * UI_popup_menu_begin(bContext *C, const char *title, int icon) ATTR_NONNULL()
uiLayout * UI_popup_menu_layout(uiPopupMenu *pup)
#define UI_ITEM_NONE
#define NC_WINDOW
Definition WM_types.hh:375
#define NC_SCREEN
Definition WM_types.hh:377
@ OPTYPE_INTERNAL
Definition WM_types.hh:202
#define ND_WORKSPACE_DELETE
Definition WM_types.hh:429
#define NC_WORKSPACE
Definition WM_types.hh:376
#define ND_WORKSPACE_SET
Definition WM_types.hh:428
int64_t first_index_of(const T &value) const
#define offsetof(t, d)
#define GS(x)
bool mode_set(bContext *C, eObjectMode mode)
const char * name
void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
std::string RNA_string_get(PointerRNA *ptr, const char *name)
bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier)
PropertyRNA * RNA_def_string(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value, const int maxlen, const char *ui_name, const char *ui_description)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
void RNA_def_property_subtype(PropertyRNA *prop, PropertySubType subtype)
void screen_change_prepare(bScreen *screen_old, bScreen *screen_new, Main *bmain, bContext *C, wmWindow *win)
void screen_change_update(bContext *C, wmWindow *win, bScreen *screen)
Definition DNA_ID.h:414
char name[258]
Definition DNA_ID.h:432
void * first
char filepath[1024]
Definition BKE_main.hh:179
ListBase workspaces
Definition BKE_main.hh:315
struct WorkSpaceLayout * temp_layout_store
Wrapper for bScreen.
struct Scene * sequencer_scene
struct Scene * pin_scene
void menu_fn_argN_free(blender::StringRefNull name, int icon, uiMenuCreateFunc func, void *argN)
void separator(float factor=1.0f, LayoutSeparatorType type=LayoutSeparatorType::Auto)
void menu_fn(blender::StringRefNull name, int icon, uiMenuCreateFunc func, void *arg)
uiLayout & row(bool align)
PointerRNA op(wmOperatorType *ot, std::optional< blender::StringRef > name, int icon, blender::wm::OpCallContext context, eUI_Item_Flag flag)
const char * name
Definition WM_types.hh:1033
const char * idname
Definition WM_types.hh:1035
struct wmOperatorType * type
struct PointerRNA * ptr
struct Scene * unpinned_scene
struct WorkSpaceInstanceHook * workspace_hook
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
char app_template[64]
Definition wm_files.cc:1191
wmOperatorType * ot
Definition wm_files.cc:4237
void WM_operatortype_append(void(*opfunc)(wmOperatorType *))
wmOperatorType * WM_operatortype_find(const char *idname, bool quiet)
void WM_window_set_active_scene(Main *bmain, bContext *C, wmWindow *win, Scene *scene)
WorkSpaceLayout * WM_window_get_active_layout(const wmWindow *win)
Scene * WM_window_get_active_scene(const wmWindow *win)
WorkSpace * WM_window_get_active_workspace(const wmWindow *win)
static void workspace_append_button(uiLayout *layout, wmOperatorType *ot_append, const WorkSpace *workspace, const Main *from_main)
static wmOperatorStatus workspace_reorder_to_front_exec(bContext *C, wmOperator *)
static wmOperatorStatus workspace_new_exec(bContext *C, wmOperator *)
static void WORKSPACE_OT_delete_all_others(wmOperatorType *ot)
static WorkSpace * workspace_context_get(bContext *C)
static void WORKSPACE_OT_add(wmOperatorType *ot)
static void WORKSPACE_OT_scene_pin_toggle(wmOperatorType *ot)
static void workspace_scene_pinning_update(WorkSpace *workspace_new, const WorkSpace *workspace_old, bContext *C)
static wmOperatorStatus workspace_add_invoke(bContext *C, wmOperator *op, const wmEvent *)
WorkSpace * ED_workspace_duplicate(WorkSpace *workspace_old, Main *bmain, wmWindow *win)
static void workspace_change_update(WorkSpace *workspace_new, WorkSpace *workspace_old, bContext *C, wmWindowManager *wm)
static wmOperatorStatus workspace_delete_all_others_exec(bContext *C, wmOperator *)
static void workspace_exit(WorkSpace *workspace, wmWindow *win)
static WorkspaceConfigFileData * workspace_config_file_read(const char *app_template)
static wmOperatorStatus workspace_delete_exec(bContext *C, wmOperator *)
static void WORKSPACE_OT_delete(wmOperatorType *ot)
static void WORKSPACE_OT_append_activate(wmOperatorType *ot)
static void workspace_add_menu(bContext *, uiLayout *layout, void *template_v)
static void WORKSPACE_OT_reorder_to_back(wmOperatorType *ot)
bool ED_workspace_change(WorkSpace *workspace_new, bContext *C, wmWindowManager *wm, wmWindow *win)
Change the active workspace.
static void WORKSPACE_OT_duplicate(wmOperatorType *ot)
void ED_workspace_scene_data_sync(WorkSpaceInstanceHook *hook, Scene *scene)
bool ED_workspace_delete(WorkSpace *workspace, Main *bmain, bContext *C, wmWindowManager *wm)
static wmOperatorStatus workspace_append_activate_exec(bContext *C, wmOperator *op)
void ED_operatortypes_workspace()
static void WORKSPACE_OT_reorder_to_front(wmOperatorType *ot)
static wmOperatorStatus workspace_scene_pin_toggle_exec(bContext *C, wmOperator *)
static WorkspaceConfigFileData * workspace_system_file_read(const char *app_template)
static WorkSpaceLayout * workspace_change_get_new_layout(Main *bmain, WorkSpace *workspace_new, wmWindow *win)
static bool workspace_context_poll(bContext *C)
static wmOperatorStatus workspace_reorder_to_back_exec(bContext *C, wmOperator *)
WorkSpace * ED_workspace_add(Main *bmain, const char *name)