ClangFormat: apply to source, most of intern

Apply clang format as proposed in T53211.

For details on usage and instructions for migrating branches
without conflicts, see:

https://wiki.blender.org/wiki/Tools/ClangFormat
This commit is contained in:
2019-04-17 06:17:24 +02:00
parent b3dabc200a
commit e12c08e8d1
4481 changed files with 1230080 additions and 1155401 deletions

View File

@@ -16,51 +16,51 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
../include
../../blenfont
../../blenkernel
../../blenlib
../../blenloader
../../blentranslation
../../bmesh
../../depsgraph
../../gpu
../../imbuf
../../makesdna
../../makesrna
../../windowmanager
../../../../intern/guardedalloc
../../../../intern/glew-mx
../include
../../blenfont
../../blenkernel
../../blenlib
../../blenloader
../../blentranslation
../../bmesh
../../depsgraph
../../gpu
../../imbuf
../../makesdna
../../makesrna
../../windowmanager
../../../../intern/guardedalloc
../../../../intern/glew-mx
)
set(INC_SYS
${GLEW_INCLUDE_PATH}
${GLEW_INCLUDE_PATH}
)
set(SRC
area.c
area_utils.c
glutil.c
screen_context.c
screen_draw.c
screen_edit.c
screen_geometry.c
screen_ops.c
screen_user_menu.c
screendump.c
workspace_edit.c
workspace_layout_edit.c
area.c
area_utils.c
glutil.c
screen_context.c
screen_draw.c
screen_edit.c
screen_geometry.c
screen_ops.c
screen_user_menu.c
screendump.c
workspace_edit.c
workspace_layout_edit.c
screen_intern.h
screen_intern.h
)
set(LIB
bf_editor_datafiles
bf_editor_space_sequencer
bf_editor_datafiles
bf_editor_space_sequencer
)
if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
add_definitions(${GL_DEFINITIONS})

File diff suppressed because it is too large Load Diff

View File

@@ -42,18 +42,20 @@
/**
* Callback for #ARegionType.message_subscribe
*/
void ED_region_generic_tools_region_message_subscribe(
const struct bContext *UNUSED(C),
struct WorkSpace *UNUSED(workspace), struct Scene *UNUSED(scene),
struct bScreen *UNUSED(screen), struct ScrArea *UNUSED(sa), struct ARegion *ar,
struct wmMsgBus *mbus)
void ED_region_generic_tools_region_message_subscribe(const struct bContext *UNUSED(C),
struct WorkSpace *UNUSED(workspace),
struct Scene *UNUSED(scene),
struct bScreen *UNUSED(screen),
struct ScrArea *UNUSED(sa),
struct ARegion *ar,
struct wmMsgBus *mbus)
{
wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
.owner = ar,
.user_data = ar,
.notify = ED_region_do_msg_notify_tag_redraw,
};
WM_msg_subscribe_rna_anon_prop(mbus, WorkSpace, tools, &msg_sub_value_region_tag_redraw);
wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
.owner = ar,
.user_data = ar,
.notify = ED_region_do_msg_notify_tag_redraw,
};
WM_msg_subscribe_rna_anon_prop(mbus, WorkSpace, tools, &msg_sub_value_region_tag_redraw);
}
/**
@@ -61,23 +63,23 @@ void ED_region_generic_tools_region_message_subscribe(
*/
int ED_region_generic_tools_region_snap_size(const ARegion *ar, int size, int axis)
{
if (axis == 0) {
/* Note, this depends on the icon size: see #ICON_DEFAULT_HEIGHT_TOOLBAR. */
const float snap_units[] = {2 + 0.8f, 4 + 0.8f};
const float aspect = BLI_rctf_size_x(&ar->v2d.cur) / (BLI_rcti_size_x(&ar->v2d.mask) + 1);
int best_diff = INT_MAX;
int best_size = size;
for (uint i = 0; i < ARRAY_SIZE(snap_units); i += 1) {
const int test_size = (snap_units[i] * U.widget_unit) / (UI_DPI_FAC * aspect);
const int test_diff = ABS(test_size - size);
if (test_diff < best_diff) {
best_size = test_size;
best_diff = test_diff;
}
}
return best_size;
}
return size;
if (axis == 0) {
/* Note, this depends on the icon size: see #ICON_DEFAULT_HEIGHT_TOOLBAR. */
const float snap_units[] = {2 + 0.8f, 4 + 0.8f};
const float aspect = BLI_rctf_size_x(&ar->v2d.cur) / (BLI_rcti_size_x(&ar->v2d.mask) + 1);
int best_diff = INT_MAX;
int best_size = size;
for (uint i = 0; i < ARRAY_SIZE(snap_units); i += 1) {
const int test_size = (snap_units[i] * U.widget_unit) / (UI_DPI_FAC * aspect);
const int test_diff = ABS(test_size - size);
if (test_diff < best_diff) {
best_size = test_size;
best_diff = test_diff;
}
}
return best_size;
}
return size;
}
/** \} */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -44,80 +44,80 @@
*/
static void draw_horizontal_join_shape(ScrArea *sa, char dir, unsigned int pos)
{
const float width = screen_geom_area_width(sa) - 1;
const float height = screen_geom_area_height(sa) - 1;
vec2f points[10];
short i;
float w, h;
const float width = screen_geom_area_width(sa) - 1;
const float height = screen_geom_area_height(sa) - 1;
vec2f points[10];
short i;
float w, h;
if (height < width) {
h = height / 8;
w = height / 4;
}
else {
h = width / 8;
w = width / 4;
}
if (height < width) {
h = height / 8;
w = height / 4;
}
else {
h = width / 8;
w = width / 4;
}
points[0].x = sa->v1->vec.x;
points[0].y = sa->v1->vec.y + height / 2;
points[0].x = sa->v1->vec.x;
points[0].y = sa->v1->vec.y + height / 2;
points[1].x = sa->v1->vec.x;
points[1].y = sa->v1->vec.y;
points[1].x = sa->v1->vec.x;
points[1].y = sa->v1->vec.y;
points[2].x = sa->v4->vec.x - w;
points[2].y = sa->v4->vec.y;
points[2].x = sa->v4->vec.x - w;
points[2].y = sa->v4->vec.y;
points[3].x = sa->v4->vec.x - w;
points[3].y = sa->v4->vec.y + height / 2 - 2 * h;
points[3].x = sa->v4->vec.x - w;
points[3].y = sa->v4->vec.y + height / 2 - 2 * h;
points[4].x = sa->v4->vec.x - 2 * w;
points[4].y = sa->v4->vec.y + height / 2;
points[4].x = sa->v4->vec.x - 2 * w;
points[4].y = sa->v4->vec.y + height / 2;
points[5].x = sa->v4->vec.x - w;
points[5].y = sa->v4->vec.y + height / 2 + 2 * h;
points[5].x = sa->v4->vec.x - w;
points[5].y = sa->v4->vec.y + height / 2 + 2 * h;
points[6].x = sa->v3->vec.x - w;
points[6].y = sa->v3->vec.y;
points[6].x = sa->v3->vec.x - w;
points[6].y = sa->v3->vec.y;
points[7].x = sa->v2->vec.x;
points[7].y = sa->v2->vec.y;
points[7].x = sa->v2->vec.x;
points[7].y = sa->v2->vec.y;
points[8].x = sa->v4->vec.x;
points[8].y = sa->v4->vec.y + height / 2 - h;
points[8].x = sa->v4->vec.x;
points[8].y = sa->v4->vec.y + height / 2 - h;
points[9].x = sa->v4->vec.x;
points[9].y = sa->v4->vec.y + height / 2 + h;
points[9].x = sa->v4->vec.x;
points[9].y = sa->v4->vec.y + height / 2 + h;
if (dir == 'l') {
/* when direction is left, then we flip direction of arrow */
float cx = sa->v1->vec.x + width;
for (i = 0; i < 10; i++) {
points[i].x -= cx;
points[i].x = -points[i].x;
points[i].x += sa->v1->vec.x;
}
}
if (dir == 'l') {
/* when direction is left, then we flip direction of arrow */
float cx = sa->v1->vec.x + width;
for (i = 0; i < 10; i++) {
points[i].x -= cx;
points[i].x = -points[i].x;
points[i].x += sa->v1->vec.x;
}
}
immBegin(GPU_PRIM_TRI_FAN, 5);
immBegin(GPU_PRIM_TRI_FAN, 5);
for (i = 0; i < 5; i++) {
immVertex2f(pos, points[i].x, points[i].y);
}
for (i = 0; i < 5; i++) {
immVertex2f(pos, points[i].x, points[i].y);
}
immEnd();
immEnd();
immBegin(GPU_PRIM_TRI_FAN, 5);
immBegin(GPU_PRIM_TRI_FAN, 5);
for (i = 4; i < 8; i++) {
immVertex2f(pos, points[i].x, points[i].y);
}
for (i = 4; i < 8; i++) {
immVertex2f(pos, points[i].x, points[i].y);
}
immVertex2f(pos, points[0].x, points[0].y);
immEnd();
immVertex2f(pos, points[0].x, points[0].y);
immEnd();
immRectf(pos, points[2].x, points[2].y, points[8].x, points[8].y);
immRectf(pos, points[6].x, points[6].y, points[9].x, points[9].y);
immRectf(pos, points[2].x, points[2].y, points[8].x, points[8].y);
immRectf(pos, points[6].x, points[6].y, points[9].x, points[9].y);
}
/**
@@ -125,80 +125,80 @@ static void draw_horizontal_join_shape(ScrArea *sa, char dir, unsigned int pos)
*/
static void draw_vertical_join_shape(ScrArea *sa, char dir, unsigned int pos)
{
const float width = screen_geom_area_width(sa) - 1;
const float height = screen_geom_area_height(sa) - 1;
vec2f points[10];
short i;
float w, h;
const float width = screen_geom_area_width(sa) - 1;
const float height = screen_geom_area_height(sa) - 1;
vec2f points[10];
short i;
float w, h;
if (height < width) {
h = height / 4;
w = height / 8;
}
else {
h = width / 4;
w = width / 8;
}
if (height < width) {
h = height / 4;
w = height / 8;
}
else {
h = width / 4;
w = width / 8;
}
points[0].x = sa->v1->vec.x + width / 2;
points[0].y = sa->v3->vec.y;
points[0].x = sa->v1->vec.x + width / 2;
points[0].y = sa->v3->vec.y;
points[1].x = sa->v2->vec.x;
points[1].y = sa->v2->vec.y;
points[1].x = sa->v2->vec.x;
points[1].y = sa->v2->vec.y;
points[2].x = sa->v1->vec.x;
points[2].y = sa->v1->vec.y + h;
points[2].x = sa->v1->vec.x;
points[2].y = sa->v1->vec.y + h;
points[3].x = sa->v1->vec.x + width / 2 - 2 * w;
points[3].y = sa->v1->vec.y + h;
points[3].x = sa->v1->vec.x + width / 2 - 2 * w;
points[3].y = sa->v1->vec.y + h;
points[4].x = sa->v1->vec.x + width / 2;
points[4].y = sa->v1->vec.y + 2 * h;
points[4].x = sa->v1->vec.x + width / 2;
points[4].y = sa->v1->vec.y + 2 * h;
points[5].x = sa->v1->vec.x + width / 2 + 2 * w;
points[5].y = sa->v1->vec.y + h;
points[5].x = sa->v1->vec.x + width / 2 + 2 * w;
points[5].y = sa->v1->vec.y + h;
points[6].x = sa->v4->vec.x;
points[6].y = sa->v4->vec.y + h;
points[6].x = sa->v4->vec.x;
points[6].y = sa->v4->vec.y + h;
points[7].x = sa->v3->vec.x;
points[7].y = sa->v3->vec.y;
points[7].x = sa->v3->vec.x;
points[7].y = sa->v3->vec.y;
points[8].x = sa->v1->vec.x + width / 2 - w;
points[8].y = sa->v1->vec.y;
points[8].x = sa->v1->vec.x + width / 2 - w;
points[8].y = sa->v1->vec.y;
points[9].x = sa->v1->vec.x + width / 2 + w;
points[9].y = sa->v1->vec.y;
points[9].x = sa->v1->vec.x + width / 2 + w;
points[9].y = sa->v1->vec.y;
if (dir == 'u') {
/* when direction is up, then we flip direction of arrow */
float cy = sa->v1->vec.y + height;
for (i = 0; i < 10; i++) {
points[i].y -= cy;
points[i].y = -points[i].y;
points[i].y += sa->v1->vec.y;
}
}
if (dir == 'u') {
/* when direction is up, then we flip direction of arrow */
float cy = sa->v1->vec.y + height;
for (i = 0; i < 10; i++) {
points[i].y -= cy;
points[i].y = -points[i].y;
points[i].y += sa->v1->vec.y;
}
}
immBegin(GPU_PRIM_TRI_FAN, 5);
immBegin(GPU_PRIM_TRI_FAN, 5);
for (i = 0; i < 5; i++) {
immVertex2f(pos, points[i].x, points[i].y);
}
for (i = 0; i < 5; i++) {
immVertex2f(pos, points[i].x, points[i].y);
}
immEnd();
immEnd();
immBegin(GPU_PRIM_TRI_FAN, 5);
immBegin(GPU_PRIM_TRI_FAN, 5);
for (i = 4; i < 8; i++) {
immVertex2f(pos, points[i].x, points[i].y);
}
for (i = 4; i < 8; i++) {
immVertex2f(pos, points[i].x, points[i].y);
}
immVertex2f(pos, points[0].x, points[0].y);
immEnd();
immVertex2f(pos, points[0].x, points[0].y);
immEnd();
immRectf(pos, points[2].x, points[2].y, points[8].x, points[8].y);
immRectf(pos, points[6].x, points[6].y, points[9].x, points[9].y);
immRectf(pos, points[2].x, points[2].y, points[8].x, points[8].y);
immRectf(pos, points[6].x, points[6].y, points[9].x, points[9].y);
}
/**
@@ -206,88 +206,88 @@ static void draw_vertical_join_shape(ScrArea *sa, char dir, unsigned int pos)
*/
static void draw_join_shape(ScrArea *sa, char dir, unsigned int pos)
{
if (dir == 'u' || dir == 'd') {
draw_vertical_join_shape(sa, dir, pos);
}
else {
draw_horizontal_join_shape(sa, dir, pos);
}
if (dir == 'u' || dir == 'd') {
draw_vertical_join_shape(sa, dir, pos);
}
else {
draw_horizontal_join_shape(sa, dir, pos);
}
}
#define CORNER_RESOLUTION 3
static void do_vert_pair(GPUVertBuf *vbo, uint pos, uint *vidx, int corner, int i)
{
float inter[2], exter[2];
inter[0] = cosf(corner * M_PI_2 + (i * M_PI_2 / (CORNER_RESOLUTION - 1.0f)));
inter[1] = sinf(corner * M_PI_2 + (i * M_PI_2 / (CORNER_RESOLUTION - 1.0f)));
float inter[2], exter[2];
inter[0] = cosf(corner * M_PI_2 + (i * M_PI_2 / (CORNER_RESOLUTION - 1.0f)));
inter[1] = sinf(corner * M_PI_2 + (i * M_PI_2 / (CORNER_RESOLUTION - 1.0f)));
/* Snap point to edge */
float div = 1.0f / max_ff(fabsf(inter[0]), fabsf(inter[1]));
mul_v2_v2fl(exter, inter, div);
exter[0] = roundf(exter[0]);
exter[1] = roundf(exter[1]);
/* Snap point to edge */
float div = 1.0f / max_ff(fabsf(inter[0]), fabsf(inter[1]));
mul_v2_v2fl(exter, inter, div);
exter[0] = roundf(exter[0]);
exter[1] = roundf(exter[1]);
if (i == 0 || i == (CORNER_RESOLUTION - 1)) {
copy_v2_v2(inter, exter);
}
if (i == 0 || i == (CORNER_RESOLUTION - 1)) {
copy_v2_v2(inter, exter);
}
/* Line width is 20% of the entire corner size. */
const float line_width = 0.2f; /* Keep in sync with shader */
mul_v2_fl(inter, 1.0f - line_width);
mul_v2_fl(exter, 1.0f + line_width);
/* Line width is 20% of the entire corner size. */
const float line_width = 0.2f; /* Keep in sync with shader */
mul_v2_fl(inter, 1.0f - line_width);
mul_v2_fl(exter, 1.0f + line_width);
switch (corner) {
case 0:
add_v2_v2(inter, (float[2]){-1.0f, -1.0f});
add_v2_v2(exter, (float[2]){-1.0f, -1.0f});
break;
case 1:
add_v2_v2(inter, (float[2]){1.0f, -1.0f});
add_v2_v2(exter, (float[2]){1.0f, -1.0f});
break;
case 2:
add_v2_v2(inter, (float[2]){1.0f, 1.0f});
add_v2_v2(exter, (float[2]){1.0f, 1.0f});
break;
case 3:
add_v2_v2(inter, (float[2]){-1.0f, 1.0f});
add_v2_v2(exter, (float[2]){-1.0f, 1.0f});
break;
}
switch (corner) {
case 0:
add_v2_v2(inter, (float[2]){-1.0f, -1.0f});
add_v2_v2(exter, (float[2]){-1.0f, -1.0f});
break;
case 1:
add_v2_v2(inter, (float[2]){1.0f, -1.0f});
add_v2_v2(exter, (float[2]){1.0f, -1.0f});
break;
case 2:
add_v2_v2(inter, (float[2]){1.0f, 1.0f});
add_v2_v2(exter, (float[2]){1.0f, 1.0f});
break;
case 3:
add_v2_v2(inter, (float[2]){-1.0f, 1.0f});
add_v2_v2(exter, (float[2]){-1.0f, 1.0f});
break;
}
GPU_vertbuf_attr_set(vbo, pos, (*vidx)++, inter);
GPU_vertbuf_attr_set(vbo, pos, (*vidx)++, exter);
GPU_vertbuf_attr_set(vbo, pos, (*vidx)++, inter);
GPU_vertbuf_attr_set(vbo, pos, (*vidx)++, exter);
}
static GPUBatch *batch_screen_edges_get(int *corner_len)
{
static GPUBatch *screen_edges_batch = NULL;
static GPUBatch *screen_edges_batch = NULL;
if (screen_edges_batch == NULL) {
GPUVertFormat format = {0};
uint pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
if (screen_edges_batch == NULL) {
GPUVertFormat format = {0};
uint pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
GPU_vertbuf_data_alloc(vbo, CORNER_RESOLUTION * 2 * 4 + 2);
GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
GPU_vertbuf_data_alloc(vbo, CORNER_RESOLUTION * 2 * 4 + 2);
uint vidx = 0;
for (int corner = 0; corner < 4; ++corner) {
for (int c = 0; c < CORNER_RESOLUTION; ++c) {
do_vert_pair(vbo, pos, &vidx, corner, c);
}
}
/* close the loop */
do_vert_pair(vbo, pos, &vidx, 0, 0);
uint vidx = 0;
for (int corner = 0; corner < 4; ++corner) {
for (int c = 0; c < CORNER_RESOLUTION; ++c) {
do_vert_pair(vbo, pos, &vidx, corner, c);
}
}
/* close the loop */
do_vert_pair(vbo, pos, &vidx, 0, 0);
screen_edges_batch = GPU_batch_create_ex(GPU_PRIM_TRI_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO);
gpu_batch_presets_register(screen_edges_batch);
}
screen_edges_batch = GPU_batch_create_ex(GPU_PRIM_TRI_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO);
gpu_batch_presets_register(screen_edges_batch);
}
if (corner_len) {
*corner_len = CORNER_RESOLUTION * 2;
}
return screen_edges_batch;
if (corner_len) {
*corner_len = CORNER_RESOLUTION * 2;
}
return screen_edges_batch;
}
#undef CORNER_RESOLUTION
@@ -297,10 +297,11 @@ static GPUBatch *batch_screen_edges_get(int *corner_len)
*/
static void scrarea_draw_shape_dark(ScrArea *sa, char dir, unsigned int pos)
{
GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
immUniformColor4ub(0, 0, 0, 50);
GPU_blend_set_func_separate(
GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
immUniformColor4ub(0, 0, 0, 50);
draw_join_shape(sa, dir, pos);
draw_join_shape(sa, dir, pos);
}
/**
@@ -308,42 +309,43 @@ static void scrarea_draw_shape_dark(ScrArea *sa, char dir, unsigned int pos)
*/
static void scrarea_draw_shape_light(ScrArea *sa, char UNUSED(dir), unsigned int pos)
{
GPU_blend_set_func(GPU_DST_COLOR, GPU_SRC_ALPHA);
/* value 181 was hardly computed: 181~105 */
immUniformColor4ub(255, 255, 255, 50);
/* draw_join_shape(sa, dir); */
GPU_blend_set_func(GPU_DST_COLOR, GPU_SRC_ALPHA);
/* value 181 was hardly computed: 181~105 */
immUniformColor4ub(255, 255, 255, 50);
/* draw_join_shape(sa, dir); */
immRectf(pos, sa->v1->vec.x, sa->v1->vec.y, sa->v3->vec.x, sa->v3->vec.y);
immRectf(pos, sa->v1->vec.x, sa->v1->vec.y, sa->v3->vec.x, sa->v3->vec.y);
}
static void drawscredge_area_draw(int sizex, int sizey, short x1, short y1, short x2, short y2, float edge_thickness)
static void drawscredge_area_draw(
int sizex, int sizey, short x1, short y1, short x2, short y2, float edge_thickness)
{
rctf rect;
BLI_rctf_init(&rect, (float)x1, (float)x2, (float)y1, (float)y2);
rctf rect;
BLI_rctf_init(&rect, (float)x1, (float)x2, (float)y1, (float)y2);
/* right border area */
if (x2 >= sizex - 1) {
rect.xmax += edge_thickness * 0.5f;
}
/* right border area */
if (x2 >= sizex - 1) {
rect.xmax += edge_thickness * 0.5f;
}
/* left border area */
if (x1 <= 0) { /* otherwise it draws the emboss of window over */
rect.xmin -= edge_thickness * 0.5f;
}
/* left border area */
if (x1 <= 0) { /* otherwise it draws the emboss of window over */
rect.xmin -= edge_thickness * 0.5f;
}
/* top border area */
if (y2 >= sizey - 1) {
rect.ymax += edge_thickness * 0.5f;
}
/* top border area */
if (y2 >= sizey - 1) {
rect.ymax += edge_thickness * 0.5f;
}
/* bottom border area */
if (y1 <= 0) {
rect.ymin -= edge_thickness * 0.5f;
}
/* bottom border area */
if (y1 <= 0) {
rect.ymin -= edge_thickness * 0.5f;
}
GPUBatch *batch = batch_screen_edges_get(NULL);
GPU_batch_uniform_4fv(batch, "rect", (float *)&rect);
GPU_batch_draw(batch);
GPUBatch *batch = batch_screen_edges_get(NULL);
GPU_batch_uniform_4fv(batch, "rect", (float *)&rect);
GPU_batch_draw(batch);
}
/**
@@ -351,12 +353,12 @@ static void drawscredge_area_draw(int sizex, int sizey, short x1, short y1, shor
*/
static void drawscredge_area(ScrArea *sa, int sizex, int sizey, float edge_thickness)
{
short x1 = sa->v1->vec.x;
short y1 = sa->v1->vec.y;
short x2 = sa->v3->vec.x;
short y2 = sa->v3->vec.y;
short x1 = sa->v1->vec.x;
short y1 = sa->v1->vec.y;
short x2 = sa->v3->vec.x;
short y2 = sa->v3->vec.y;
drawscredge_area_draw(sizex, sizey, x1, y1, x2, y2, edge_thickness);
drawscredge_area_draw(sizex, sizey, x1, y1, x2, y2, edge_thickness);
}
/**
@@ -364,71 +366,72 @@ static void drawscredge_area(ScrArea *sa, int sizex, int sizey, float edge_thick
*/
void ED_screen_draw_edges(wmWindow *win)
{
bScreen *screen = WM_window_get_active_screen(win);
screen->do_draw = false;
bScreen *screen = WM_window_get_active_screen(win);
screen->do_draw = false;
if (screen->state == SCREENFULL) {
return;
}
if (screen->state == SCREENFULL) {
return;
}
if (screen->temp && BLI_listbase_is_single(&screen->areabase)) {
return;
}
if (screen->temp && BLI_listbase_is_single(&screen->areabase)) {
return;
}
const int winsize_x = WM_window_pixels_x(win);
const int winsize_y = WM_window_pixels_y(win);
float col[4], corner_scale, edge_thickness;
int verts_per_corner = 0;
const int winsize_x = WM_window_pixels_x(win);
const int winsize_y = WM_window_pixels_y(win);
float col[4], corner_scale, edge_thickness;
int verts_per_corner = 0;
ScrArea *sa;
ScrArea *sa;
rcti scissor_rect;
BLI_rcti_init_minmax(&scissor_rect);
for (sa = screen->areabase.first; sa; sa = sa->next) {
BLI_rcti_do_minmax_v(&scissor_rect, (int[2]){sa->v1->vec.x, sa->v1->vec.y});
BLI_rcti_do_minmax_v(&scissor_rect, (int[2]){sa->v3->vec.x, sa->v3->vec.y});
}
rcti scissor_rect;
BLI_rcti_init_minmax(&scissor_rect);
for (sa = screen->areabase.first; sa; sa = sa->next) {
BLI_rcti_do_minmax_v(&scissor_rect, (int[2]){sa->v1->vec.x, sa->v1->vec.y});
BLI_rcti_do_minmax_v(&scissor_rect, (int[2]){sa->v3->vec.x, sa->v3->vec.y});
}
if (GPU_type_matches(GPU_DEVICE_INTEL_UHD, GPU_OS_UNIX, GPU_DRIVER_ANY)) {
/* For some reason, on linux + Intel UHD Graphics 620 the driver
* hangs if we don't flush before this. (See T57455) */
GPU_flush();
}
if (GPU_type_matches(GPU_DEVICE_INTEL_UHD, GPU_OS_UNIX, GPU_DRIVER_ANY)) {
/* For some reason, on linux + Intel UHD Graphics 620 the driver
* hangs if we don't flush before this. (See T57455) */
GPU_flush();
}
GPU_scissor(scissor_rect.xmin,
scissor_rect.ymin,
BLI_rcti_size_x(&scissor_rect) + 1,
BLI_rcti_size_y(&scissor_rect) + 1);
GPU_scissor(scissor_rect.xmin,
scissor_rect.ymin,
BLI_rcti_size_x(&scissor_rect) + 1,
BLI_rcti_size_y(&scissor_rect) + 1);
/* It seems that all areas gets smaller when pixelsize is > 1.
* So in order to avoid missing pixels we just disable de scissors. */
if (U.pixelsize <= 1.0f) {
glEnable(GL_SCISSOR_TEST);
}
/* It seems that all areas gets smaller when pixelsize is > 1.
* So in order to avoid missing pixels we just disable de scissors. */
if (U.pixelsize <= 1.0f) {
glEnable(GL_SCISSOR_TEST);
}
UI_GetThemeColor4fv(TH_EDITOR_OUTLINE, col);
col[3] = 1.0f;
corner_scale = U.pixelsize * 8.0f;
edge_thickness = corner_scale * 0.21f;
UI_GetThemeColor4fv(TH_EDITOR_OUTLINE, col);
col[3] = 1.0f;
corner_scale = U.pixelsize * 8.0f;
edge_thickness = corner_scale * 0.21f;
GPU_blend(true);
GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
GPU_blend(true);
GPU_blend_set_func_separate(
GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
GPUBatch *batch = batch_screen_edges_get(&verts_per_corner);
GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_AREA_EDGES);
GPU_batch_uniform_1i(batch, "cornerLen", verts_per_corner);
GPU_batch_uniform_1f(batch, "scale", corner_scale);
GPU_batch_uniform_4fv(batch, "color", col);
GPUBatch *batch = batch_screen_edges_get(&verts_per_corner);
GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_AREA_EDGES);
GPU_batch_uniform_1i(batch, "cornerLen", verts_per_corner);
GPU_batch_uniform_1f(batch, "scale", corner_scale);
GPU_batch_uniform_4fv(batch, "color", col);
for (sa = screen->areabase.first; sa; sa = sa->next) {
drawscredge_area(sa, winsize_x, winsize_y, edge_thickness);
}
for (sa = screen->areabase.first; sa; sa = sa->next) {
drawscredge_area(sa, winsize_x, winsize_y, edge_thickness);
}
GPU_blend(false);
GPU_blend(false);
if (U.pixelsize <= 1.0f) {
glDisable(GL_SCISSOR_TEST);
}
if (U.pixelsize <= 1.0f) {
glDisable(GL_SCISSOR_TEST);
}
}
/**
@@ -439,100 +442,100 @@ void ED_screen_draw_edges(wmWindow *win)
*/
void ED_screen_draw_join_shape(ScrArea *sa1, ScrArea *sa2)
{
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
GPU_line_width(1);
GPU_line_width(1);
/* blended join arrow */
int dir = area_getorientation(sa1, sa2);
int dira = -1;
if (dir != -1) {
switch (dir) {
case 0: /* W */
dir = 'r';
dira = 'l';
break;
case 1: /* N */
dir = 'd';
dira = 'u';
break;
case 2: /* E */
dir = 'l';
dira = 'r';
break;
case 3: /* S */
dir = 'u';
dira = 'd';
break;
}
/* blended join arrow */
int dir = area_getorientation(sa1, sa2);
int dira = -1;
if (dir != -1) {
switch (dir) {
case 0: /* W */
dir = 'r';
dira = 'l';
break;
case 1: /* N */
dir = 'd';
dira = 'u';
break;
case 2: /* E */
dir = 'l';
dira = 'r';
break;
case 3: /* S */
dir = 'u';
dira = 'd';
break;
}
GPU_blend(true);
GPU_blend(true);
scrarea_draw_shape_dark(sa2, dir, pos);
scrarea_draw_shape_light(sa1, dira, pos);
scrarea_draw_shape_dark(sa2, dir, pos);
scrarea_draw_shape_light(sa1, dira, pos);
GPU_blend(false);
}
GPU_blend(false);
}
immUnbindProgram();
immUnbindProgram();
}
void ED_screen_draw_split_preview(ScrArea *sa, const int dir, const float fac)
{
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* splitpoint */
GPU_blend(true);
GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
/* splitpoint */
GPU_blend(true);
GPU_blend_set_func_separate(
GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
immUniformColor4ub(255, 255, 255, 100);
immUniformColor4ub(255, 255, 255, 100);
immBegin(GPU_PRIM_LINES, 2);
immBegin(GPU_PRIM_LINES, 2);
if (dir == 'h') {
const float y = (1 - fac) * sa->totrct.ymin + fac * sa->totrct.ymax;
if (dir == 'h') {
const float y = (1 - fac) * sa->totrct.ymin + fac * sa->totrct.ymax;
immVertex2f(pos, sa->totrct.xmin, y);
immVertex2f(pos, sa->totrct.xmax, y);
immVertex2f(pos, sa->totrct.xmin, y);
immVertex2f(pos, sa->totrct.xmax, y);
immEnd();
immEnd();
immUniformColor4ub(0, 0, 0, 100);
immUniformColor4ub(0, 0, 0, 100);
immBegin(GPU_PRIM_LINES, 2);
immBegin(GPU_PRIM_LINES, 2);
immVertex2f(pos, sa->totrct.xmin, y + 1);
immVertex2f(pos, sa->totrct.xmax, y + 1);
immVertex2f(pos, sa->totrct.xmin, y + 1);
immVertex2f(pos, sa->totrct.xmax, y + 1);
immEnd();
}
else {
BLI_assert(dir == 'v');
const float x = (1 - fac) * sa->totrct.xmin + fac * sa->totrct.xmax;
immEnd();
}
else {
BLI_assert(dir == 'v');
const float x = (1 - fac) * sa->totrct.xmin + fac * sa->totrct.xmax;
immVertex2f(pos, x, sa->totrct.ymin);
immVertex2f(pos, x, sa->totrct.ymax);
immVertex2f(pos, x, sa->totrct.ymin);
immVertex2f(pos, x, sa->totrct.ymax);
immEnd();
immEnd();
immUniformColor4ub(0, 0, 0, 100);
immUniformColor4ub(0, 0, 0, 100);
immBegin(GPU_PRIM_LINES, 2);
immBegin(GPU_PRIM_LINES, 2);
immVertex2f(pos, x + 1, sa->totrct.ymin);
immVertex2f(pos, x + 1, sa->totrct.ymax);
immVertex2f(pos, x + 1, sa->totrct.ymin);
immVertex2f(pos, x + 1, sa->totrct.ymax);
immEnd();
}
immEnd();
}
GPU_blend(false);
GPU_blend(false);
immUnbindProgram();
immUnbindProgram();
}
/* -------------------------------------------------------------------- */
/* Screen Thumbnail Preview */
@@ -540,65 +543,65 @@ void ED_screen_draw_split_preview(ScrArea *sa, const int dir, const float fac)
* Calculates a scale factor to squash the preview for \a screen into a rectangle of given size and aspect.
*/
static void screen_preview_scale_get(
const bScreen *screen, float size_x, float size_y,
const float asp[2],
float r_scale[2])
const bScreen *screen, float size_x, float size_y, const float asp[2], float r_scale[2])
{
float max_x = 0, max_y = 0;
float max_x = 0, max_y = 0;
for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
max_x = MAX2(max_x, sa->totrct.xmax);
max_y = MAX2(max_y, sa->totrct.ymax);
}
r_scale[0] = (size_x * asp[0]) / max_x;
r_scale[1] = (size_y * asp[1]) / max_y;
for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
max_x = MAX2(max_x, sa->totrct.xmax);
max_y = MAX2(max_y, sa->totrct.ymax);
}
r_scale[0] = (size_x * asp[0]) / max_x;
r_scale[1] = (size_y * asp[1]) / max_y;
}
static void screen_preview_draw_areas(const bScreen *screen, const float scale[2], const float col[4],
static void screen_preview_draw_areas(const bScreen *screen,
const float scale[2],
const float col[4],
const float ofs_between_areas)
{
const float ofs_h = ofs_between_areas * 0.5f;
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
const float ofs_h = ofs_between_areas * 0.5f;
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4fv(col);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4fv(col);
for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
rctf rect = {
.xmin = sa->totrct.xmin * scale[0] + ofs_h,
.xmax = sa->totrct.xmax * scale[0] - ofs_h,
.ymin = sa->totrct.ymin * scale[1] + ofs_h,
.ymax = sa->totrct.ymax * scale[1] - ofs_h,
};
for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
rctf rect = {
.xmin = sa->totrct.xmin * scale[0] + ofs_h,
.xmax = sa->totrct.xmax * scale[0] - ofs_h,
.ymin = sa->totrct.ymin * scale[1] + ofs_h,
.ymax = sa->totrct.ymax * scale[1] - ofs_h,
};
immBegin(GPU_PRIM_TRI_FAN, 4);
immVertex2f(pos, rect.xmin, rect.ymin);
immVertex2f(pos, rect.xmax, rect.ymin);
immVertex2f(pos, rect.xmax, rect.ymax);
immVertex2f(pos, rect.xmin, rect.ymax);
immEnd();
}
immBegin(GPU_PRIM_TRI_FAN, 4);
immVertex2f(pos, rect.xmin, rect.ymin);
immVertex2f(pos, rect.xmax, rect.ymin);
immVertex2f(pos, rect.xmax, rect.ymax);
immVertex2f(pos, rect.xmin, rect.ymax);
immEnd();
}
immUnbindProgram();
immUnbindProgram();
}
static void screen_preview_draw(const bScreen *screen, int size_x, int size_y)
{
const float asp[2] = {1.0f, 0.8f}; /* square previews look a bit ugly */
/* could use theme color (tui.wcol_menu_item.text), but then we'd need to regenerate all previews when changing */
const float col[4] = {1.0f, 1.0f, 1.0f, 1.0f};
float scale[2];
const float asp[2] = {1.0f, 0.8f}; /* square previews look a bit ugly */
/* could use theme color (tui.wcol_menu_item.text), but then we'd need to regenerate all previews when changing */
const float col[4] = {1.0f, 1.0f, 1.0f, 1.0f};
float scale[2];
wmOrtho2(0.0f, size_x, 0.0f, size_y);
/* center */
GPU_matrix_push();
GPU_matrix_identity_set();
GPU_matrix_translate_2f(size_x * (1.0f - asp[0]) * 0.5f, size_y * (1.0f - asp[1]) * 0.5f);
wmOrtho2(0.0f, size_x, 0.0f, size_y);
/* center */
GPU_matrix_push();
GPU_matrix_identity_set();
GPU_matrix_translate_2f(size_x * (1.0f - asp[0]) * 0.5f, size_y * (1.0f - asp[1]) * 0.5f);
screen_preview_scale_get(screen, size_x, size_y, asp, scale);
screen_preview_draw_areas(screen, scale, col, 1.5f);
screen_preview_scale_get(screen, size_x, size_y, asp, scale);
screen_preview_draw_areas(screen, scale, col, 1.5f);
GPU_matrix_pop();
GPU_matrix_pop();
}
/**
@@ -606,17 +609,17 @@ static void screen_preview_draw(const bScreen *screen, int size_x, int size_y)
*/
void ED_screen_preview_render(const bScreen *screen, int size_x, int size_y, unsigned int *r_rect)
{
char err_out[256] = "unknown";
GPUOffScreen *offscreen = GPU_offscreen_create(size_x, size_y, 0, true, false, err_out);
char err_out[256] = "unknown";
GPUOffScreen *offscreen = GPU_offscreen_create(size_x, size_y, 0, true, false, err_out);
GPU_offscreen_bind(offscreen, true);
GPU_clear_color(0.0, 0.0, 0.0, 0.0);
GPU_clear(GPU_COLOR_BIT | GPU_DEPTH_BIT);
GPU_offscreen_bind(offscreen, true);
GPU_clear_color(0.0, 0.0, 0.0, 0.0);
GPU_clear(GPU_COLOR_BIT | GPU_DEPTH_BIT);
screen_preview_draw(screen, size_x, size_y);
screen_preview_draw(screen, size_x, size_y);
GPU_offscreen_read_pixels(offscreen, GL_UNSIGNED_BYTE, r_rect);
GPU_offscreen_unbind(offscreen, true);
GPU_offscreen_read_pixels(offscreen, GL_UNSIGNED_BYTE, r_rect);
GPU_offscreen_unbind(offscreen, true);
GPU_offscreen_free(offscreen);
GPU_offscreen_free(offscreen);
}

File diff suppressed because it is too large Load Diff

View File

@@ -39,108 +39,108 @@
#include "screen_intern.h"
int screen_geom_area_height(const ScrArea *area)
{
return area->v2->vec.y - area->v1->vec.y + 1;
return area->v2->vec.y - area->v1->vec.y + 1;
}
int screen_geom_area_width(const ScrArea *area)
{
return area->v4->vec.x - area->v1->vec.x + 1;
return area->v4->vec.x - area->v1->vec.x + 1;
}
ScrVert *screen_geom_vertex_add_ex(ScrAreaMap *area_map, short x, short y)
{
ScrVert *sv = MEM_callocN(sizeof(ScrVert), "addscrvert");
sv->vec.x = x;
sv->vec.y = y;
ScrVert *sv = MEM_callocN(sizeof(ScrVert), "addscrvert");
sv->vec.x = x;
sv->vec.y = y;
BLI_addtail(&area_map->vertbase, sv);
return sv;
BLI_addtail(&area_map->vertbase, sv);
return sv;
}
ScrVert *screen_geom_vertex_add(bScreen *sc, short x, short y)
{
return screen_geom_vertex_add_ex(AREAMAP_FROM_SCREEN(sc), x, y);
return screen_geom_vertex_add_ex(AREAMAP_FROM_SCREEN(sc), x, y);
}
ScrEdge *screen_geom_edge_add_ex(ScrAreaMap *area_map, ScrVert *v1, ScrVert *v2)
{
ScrEdge *se = MEM_callocN(sizeof(ScrEdge), "addscredge");
ScrEdge *se = MEM_callocN(sizeof(ScrEdge), "addscredge");
BKE_screen_sort_scrvert(&v1, &v2);
se->v1 = v1;
se->v2 = v2;
BKE_screen_sort_scrvert(&v1, &v2);
se->v1 = v1;
se->v2 = v2;
BLI_addtail(&area_map->edgebase, se);
return se;
BLI_addtail(&area_map->edgebase, se);
return se;
}
ScrEdge *screen_geom_edge_add(bScreen *sc, ScrVert *v1, ScrVert *v2)
{
return screen_geom_edge_add_ex(AREAMAP_FROM_SCREEN(sc), v1, v2);
return screen_geom_edge_add_ex(AREAMAP_FROM_SCREEN(sc), v1, v2);
}
bool screen_geom_edge_is_horizontal(ScrEdge *se)
{
return (se->v1->vec.y == se->v2->vec.y);
return (se->v1->vec.y == se->v2->vec.y);
}
/**
* \param bounds_rect: Either window or screen bounds. Used to exclude edges along window/screen edges.
*/
ScrEdge *screen_geom_area_map_find_active_scredge(
const ScrAreaMap *area_map,
const rcti *bounds_rect,
const int mx, const int my)
ScrEdge *screen_geom_area_map_find_active_scredge(const ScrAreaMap *area_map,
const rcti *bounds_rect,
const int mx,
const int my)
{
int safety = U.widget_unit / 10;
int safety = U.widget_unit / 10;
CLAMP_MIN(safety, 2);
CLAMP_MIN(safety, 2);
for (ScrEdge *se = area_map->edgebase.first; se; se = se->next) {
if (screen_geom_edge_is_horizontal(se)) {
if ((se->v1->vec.y > bounds_rect->ymin) && (se->v1->vec.y < (bounds_rect->ymax - 1))) {
short min, max;
min = MIN2(se->v1->vec.x, se->v2->vec.x);
max = MAX2(se->v1->vec.x, se->v2->vec.x);
for (ScrEdge *se = area_map->edgebase.first; se; se = se->next) {
if (screen_geom_edge_is_horizontal(se)) {
if ((se->v1->vec.y > bounds_rect->ymin) && (se->v1->vec.y < (bounds_rect->ymax - 1))) {
short min, max;
min = MIN2(se->v1->vec.x, se->v2->vec.x);
max = MAX2(se->v1->vec.x, se->v2->vec.x);
if (abs(my - se->v1->vec.y) <= safety && mx >= min && mx <= max)
return se;
}
}
else {
if ((se->v1->vec.x > bounds_rect->xmin) && (se->v1->vec.x < (bounds_rect->xmax - 1))) {
short min, max;
min = MIN2(se->v1->vec.y, se->v2->vec.y);
max = MAX2(se->v1->vec.y, se->v2->vec.y);
if (abs(my - se->v1->vec.y) <= safety && mx >= min && mx <= max)
return se;
}
}
else {
if ((se->v1->vec.x > bounds_rect->xmin) && (se->v1->vec.x < (bounds_rect->xmax - 1))) {
short min, max;
min = MIN2(se->v1->vec.y, se->v2->vec.y);
max = MAX2(se->v1->vec.y, se->v2->vec.y);
if (abs(mx - se->v1->vec.x) <= safety && my >= min && my <= max)
return se;
}
}
}
if (abs(mx - se->v1->vec.x) <= safety && my >= min && my <= max)
return se;
}
}
}
return NULL;
return NULL;
}
/* need win size to make sure not to include edges along screen edge */
ScrEdge *screen_geom_find_active_scredge(
const wmWindow *win, const bScreen *screen,
const int mx, const int my)
ScrEdge *screen_geom_find_active_scredge(const wmWindow *win,
const bScreen *screen,
const int mx,
const int my)
{
/* Use layout size (screen excluding global areas) for screen-layout area edges */
rcti screen_rect;
ScrEdge *se;
/* Use layout size (screen excluding global areas) for screen-layout area edges */
rcti screen_rect;
ScrEdge *se;
WM_window_screen_rect_calc(win, &screen_rect);
se = screen_geom_area_map_find_active_scredge(AREAMAP_FROM_SCREEN(screen), &screen_rect, mx, my);
WM_window_screen_rect_calc(win, &screen_rect);
se = screen_geom_area_map_find_active_scredge(AREAMAP_FROM_SCREEN(screen), &screen_rect, mx, my);
if (!se) {
/* Use entire window size (screen including global areas) for global area edges */
rcti win_rect;
WM_window_rect_calc(win, &win_rect);
se = screen_geom_area_map_find_active_scredge(&win->global_areas, &win_rect, mx, my);
}
return se;
if (!se) {
/* Use entire window size (screen including global areas) for global area edges */
rcti win_rect;
WM_window_rect_calc(win, &win_rect);
se = screen_geom_area_map_find_active_scredge(&win->global_areas, &win_rect, mx, my);
}
return se;
}
/**
@@ -152,262 +152,261 @@ ScrEdge *screen_geom_find_active_scredge(
*/
void screen_geom_vertices_scale(const wmWindow *win, bScreen *sc)
{
/* clamp Y size of header sized areas when expanding windows
* avoids annoying empty space around file menu */
/* clamp Y size of header sized areas when expanding windows
* avoids annoying empty space around file menu */
#define USE_HEADER_SIZE_CLAMP
rcti window_rect, screen_rect;
rcti window_rect, screen_rect;
WM_window_rect_calc(win, &window_rect);
WM_window_screen_rect_calc(win, &screen_rect);
WM_window_rect_calc(win, &window_rect);
WM_window_screen_rect_calc(win, &screen_rect);
const int headery_init = ED_area_headersize();
const int screen_size_x = BLI_rcti_size_x(&screen_rect);
const int screen_size_y = BLI_rcti_size_y(&screen_rect);
ScrVert *sv = NULL;
ScrArea *sa;
int screen_size_x_prev, screen_size_y_prev;
float min[2], max[2];
const int headery_init = ED_area_headersize();
const int screen_size_x = BLI_rcti_size_x(&screen_rect);
const int screen_size_y = BLI_rcti_size_y(&screen_rect);
ScrVert *sv = NULL;
ScrArea *sa;
int screen_size_x_prev, screen_size_y_prev;
float min[2], max[2];
/* calculate size */
min[0] = min[1] = 20000.0f;
max[0] = max[1] = 0.0f;
/* calculate size */
min[0] = min[1] = 20000.0f;
max[0] = max[1] = 0.0f;
for (sv = sc->vertbase.first; sv; sv = sv->next) {
const float fv[2] = {(float)sv->vec.x, (float)sv->vec.y};
minmax_v2v2_v2(min, max, fv);
}
screen_size_x_prev = (max[0] - min[0]) + 1;
screen_size_y_prev = (max[1] - min[1]) + 1;
for (sv = sc->vertbase.first; sv; sv = sv->next) {
const float fv[2] = {(float)sv->vec.x, (float)sv->vec.y};
minmax_v2v2_v2(min, max, fv);
}
screen_size_x_prev = (max[0] - min[0]) + 1;
screen_size_y_prev = (max[1] - min[1]) + 1;
#ifdef USE_HEADER_SIZE_CLAMP
#define TEMP_BOTTOM 1
#define TEMP_TOP 2
# define TEMP_BOTTOM 1
# define TEMP_TOP 2
/* if the window's Y axis grows, clamp header sized areas */
if (screen_size_y_prev < screen_size_y) { /* growing? */
const int headery_margin_max = headery_init + 5;
for (sa = sc->areabase.first; sa; sa = sa->next) {
ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
sa->temp = 0;
/* if the window's Y axis grows, clamp header sized areas */
if (screen_size_y_prev < screen_size_y) { /* growing? */
const int headery_margin_max = headery_init + 5;
for (sa = sc->areabase.first; sa; sa = sa->next) {
ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
sa->temp = 0;
if (ar && !(ar->flag & RGN_FLAG_HIDDEN)) {
if (sa->v2->vec.y == max[1]) {
if (screen_geom_area_height(sa) < headery_margin_max) {
sa->temp = TEMP_TOP;
}
}
else if (sa->v1->vec.y == min[1]) {
if (screen_geom_area_height(sa) < headery_margin_max) {
sa->temp = TEMP_BOTTOM;
}
}
}
}
}
if (ar && !(ar->flag & RGN_FLAG_HIDDEN)) {
if (sa->v2->vec.y == max[1]) {
if (screen_geom_area_height(sa) < headery_margin_max) {
sa->temp = TEMP_TOP;
}
}
else if (sa->v1->vec.y == min[1]) {
if (screen_geom_area_height(sa) < headery_margin_max) {
sa->temp = TEMP_BOTTOM;
}
}
}
}
}
#endif
if (screen_size_x_prev != screen_size_x || screen_size_y_prev != screen_size_y) {
const float facx = ((float)screen_size_x - 1) / ((float)screen_size_x_prev - 1);
const float facy = ((float)screen_size_y - 1) / ((float)screen_size_y_prev - 1);
if (screen_size_x_prev != screen_size_x || screen_size_y_prev != screen_size_y) {
const float facx = ((float)screen_size_x - 1) / ((float)screen_size_x_prev - 1);
const float facy = ((float)screen_size_y - 1) / ((float)screen_size_y_prev - 1);
/* make sure it fits! */
for (sv = sc->vertbase.first; sv; sv = sv->next) {
sv->vec.x = screen_rect.xmin + round_fl_to_short((sv->vec.x - min[0]) * facx);
CLAMP(sv->vec.x, screen_rect.xmin, screen_rect.xmax - 1);
sv->vec.y = screen_rect.ymin + round_fl_to_short((sv->vec.y - min[1]) * facy);
CLAMP(sv->vec.y, screen_rect.ymin, screen_rect.ymax - 1);
}
}
/* make sure it fits! */
for (sv = sc->vertbase.first; sv; sv = sv->next) {
sv->vec.x = screen_rect.xmin + round_fl_to_short((sv->vec.x - min[0]) * facx);
CLAMP(sv->vec.x, screen_rect.xmin, screen_rect.xmax - 1);
sv->vec.y = screen_rect.ymin + round_fl_to_short((sv->vec.y - min[1]) * facy);
CLAMP(sv->vec.y, screen_rect.ymin, screen_rect.ymax - 1);
}
}
#ifdef USE_HEADER_SIZE_CLAMP
if (screen_size_y_prev < screen_size_y) { /* growing? */
for (sa = sc->areabase.first; sa; sa = sa->next) {
ScrEdge *se = NULL;
if (screen_size_y_prev < screen_size_y) { /* growing? */
for (sa = sc->areabase.first; sa; sa = sa->next) {
ScrEdge *se = NULL;
if (sa->temp == 0)
continue;
if (sa->temp == 0)
continue;
if (sa->v1 == sa->v2)
continue;
if (sa->v1 == sa->v2)
continue;
/* adjust headery if verts are along the edge of window */
if (sa->temp == TEMP_TOP) {
/* lower edge */
const int yval = sa->v2->vec.y - headery_init;
se = BKE_screen_find_edge(sc, sa->v4, sa->v1);
if (se != NULL) {
screen_geom_select_connected_edge(win, se);
}
for (sv = sc->vertbase.first; sv; sv = sv->next) {
if (sv != sa->v2 && sv != sa->v3) {
if (sv->flag) {
sv->vec.y = yval;
}
}
}
}
else {
/* upper edge */
const int yval = sa->v1->vec.y + headery_init;
se = BKE_screen_find_edge(sc, sa->v2, sa->v3);
if (se != NULL) {
screen_geom_select_connected_edge(win, se);
}
for (sv = sc->vertbase.first; sv; sv = sv->next) {
if (sv != sa->v1 && sv != sa->v4) {
if (sv->flag) {
sv->vec.y = yval;
}
}
}
}
}
}
/* adjust headery if verts are along the edge of window */
if (sa->temp == TEMP_TOP) {
/* lower edge */
const int yval = sa->v2->vec.y - headery_init;
se = BKE_screen_find_edge(sc, sa->v4, sa->v1);
if (se != NULL) {
screen_geom_select_connected_edge(win, se);
}
for (sv = sc->vertbase.first; sv; sv = sv->next) {
if (sv != sa->v2 && sv != sa->v3) {
if (sv->flag) {
sv->vec.y = yval;
}
}
}
}
else {
/* upper edge */
const int yval = sa->v1->vec.y + headery_init;
se = BKE_screen_find_edge(sc, sa->v2, sa->v3);
if (se != NULL) {
screen_geom_select_connected_edge(win, se);
}
for (sv = sc->vertbase.first; sv; sv = sv->next) {
if (sv != sa->v1 && sv != sa->v4) {
if (sv->flag) {
sv->vec.y = yval;
}
}
}
}
}
}
#undef USE_HEADER_SIZE_CLAMP
#undef TEMP_BOTTOM
#undef TEMP_TOP
# undef USE_HEADER_SIZE_CLAMP
# undef TEMP_BOTTOM
# undef TEMP_TOP
#endif
/* test for collapsed areas. This could happen in some blender version... */
/* ton: removed option now, it needs Context... */
/* test for collapsed areas. This could happen in some blender version... */
/* ton: removed option now, it needs Context... */
/* make each window at least ED_area_headersize() high */
for (sa = sc->areabase.first; sa; sa = sa->next) {
int headery = headery_init;
/* make each window at least ED_area_headersize() high */
for (sa = sc->areabase.first; sa; sa = sa->next) {
int headery = headery_init;
/* adjust headery if verts are along the edge of window */
if (sa->v1->vec.y > window_rect.ymin)
headery += U.pixelsize;
if (sa->v2->vec.y < (window_rect.ymax - 1))
headery += U.pixelsize;
/* adjust headery if verts are along the edge of window */
if (sa->v1->vec.y > window_rect.ymin)
headery += U.pixelsize;
if (sa->v2->vec.y < (window_rect.ymax - 1))
headery += U.pixelsize;
if (screen_geom_area_height(sa) < headery) {
/* lower edge */
ScrEdge *se = BKE_screen_find_edge(sc, sa->v4, sa->v1);
if (se && sa->v1 != sa->v2) {
const int yval = sa->v2->vec.y - headery + 1;
if (screen_geom_area_height(sa) < headery) {
/* lower edge */
ScrEdge *se = BKE_screen_find_edge(sc, sa->v4, sa->v1);
if (se && sa->v1 != sa->v2) {
const int yval = sa->v2->vec.y - headery + 1;
screen_geom_select_connected_edge(win, se);
screen_geom_select_connected_edge(win, se);
/* all selected vertices get the right offset */
for (sv = sc->vertbase.first; sv; sv = sv->next) {
/* if is a collapsed area */
if (sv != sa->v2 && sv != sa->v3) {
if (sv->flag) {
sv->vec.y = yval;
}
}
}
}
}
}
/* all selected vertices get the right offset */
for (sv = sc->vertbase.first; sv; sv = sv->next) {
/* if is a collapsed area */
if (sv != sa->v2 && sv != sa->v3) {
if (sv->flag) {
sv->vec.y = yval;
}
}
}
}
}
}
/* Global areas have a fixed size that only changes with the DPI. Here we ensure that exactly this size is set. */
for (ScrArea *area = win->global_areas.areabase.first; area; area = area->next) {
if (area->global->flag & GLOBAL_AREA_IS_HIDDEN) {
continue;
}
/* Global areas have a fixed size that only changes with the DPI. Here we ensure that exactly this size is set. */
for (ScrArea *area = win->global_areas.areabase.first; area; area = area->next) {
if (area->global->flag & GLOBAL_AREA_IS_HIDDEN) {
continue;
}
int height = ED_area_global_size_y(area) - 1;
int height = ED_area_global_size_y(area) - 1;
if (area->v1->vec.y > window_rect.ymin) {
height += U.pixelsize;
}
if (area->v2->vec.y < (window_rect.ymax - 1)) {
height += U.pixelsize;
}
if (area->v1->vec.y > window_rect.ymin) {
height += U.pixelsize;
}
if (area->v2->vec.y < (window_rect.ymax - 1)) {
height += U.pixelsize;
}
/* width */
area->v1->vec.x = area->v2->vec.x = window_rect.xmin;
area->v3->vec.x = area->v4->vec.x = window_rect.xmax - 1;
/* height */
area->v1->vec.y = area->v4->vec.y = window_rect.ymin;
area->v2->vec.y = area->v3->vec.y = window_rect.ymax - 1;
/* width */
area->v1->vec.x = area->v2->vec.x = window_rect.xmin;
area->v3->vec.x = area->v4->vec.x = window_rect.xmax - 1;
/* height */
area->v1->vec.y = area->v4->vec.y = window_rect.ymin;
area->v2->vec.y = area->v3->vec.y = window_rect.ymax - 1;
switch (area->global->align) {
case GLOBAL_AREA_ALIGN_TOP:
area->v1->vec.y = area->v4->vec.y = area->v2->vec.y - height;
break;
case GLOBAL_AREA_ALIGN_BOTTOM:
area->v2->vec.y = area->v3->vec.y = area->v1->vec.y + height;
break;
}
}
switch (area->global->align) {
case GLOBAL_AREA_ALIGN_TOP:
area->v1->vec.y = area->v4->vec.y = area->v2->vec.y - height;
break;
case GLOBAL_AREA_ALIGN_BOTTOM:
area->v2->vec.y = area->v3->vec.y = area->v1->vec.y + height;
break;
}
}
}
/**
* \return 0 if no split is possible, otherwise the screen-coordinate at which to split.
*/
short screen_geom_find_area_split_point(const ScrArea *sa, const rcti *window_rect, char dir, float fac)
short screen_geom_find_area_split_point(const ScrArea *sa,
const rcti *window_rect,
char dir,
float fac)
{
short x, y;
const int cur_area_width = screen_geom_area_width(sa);
const int cur_area_height = screen_geom_area_height(sa);
const short area_min_x = AREAMINX;
const short area_min_y = ED_area_headersize();
int area_min;
short x, y;
const int cur_area_width = screen_geom_area_width(sa);
const int cur_area_height = screen_geom_area_height(sa);
const short area_min_x = AREAMINX;
const short area_min_y = ED_area_headersize();
int area_min;
// area big enough?
if ((dir == 'v') && (cur_area_width <= 2 * area_min_x)) {
return 0;
}
if ((dir == 'h') && (cur_area_height <= 2 * area_min_y)) {
return 0;
}
// area big enough?
if ((dir == 'v') && (cur_area_width <= 2 * area_min_x)) {
return 0;
}
if ((dir == 'h') && (cur_area_height <= 2 * area_min_y)) {
return 0;
}
// to be sure
CLAMP(fac, 0.0f, 1.0f);
// to be sure
CLAMP(fac, 0.0f, 1.0f);
if (dir == 'h') {
y = sa->v1->vec.y + round_fl_to_short(fac * cur_area_height);
if (dir == 'h') {
y = sa->v1->vec.y + round_fl_to_short(fac * cur_area_height);
area_min = area_min_y;
area_min = area_min_y;
if (sa->v1->vec.y > window_rect->ymin) {
area_min += U.pixelsize;
}
if (sa->v2->vec.y < (window_rect->ymax - 1)) {
area_min += U.pixelsize;
}
if (sa->v1->vec.y > window_rect->ymin) {
area_min += U.pixelsize;
}
if (sa->v2->vec.y < (window_rect->ymax - 1)) {
area_min += U.pixelsize;
}
if (y - sa->v1->vec.y < area_min) {
y = sa->v1->vec.y + area_min;
}
else if (sa->v2->vec.y - y < area_min) {
y = sa->v2->vec.y - area_min;
}
if (y - sa->v1->vec.y < area_min) {
y = sa->v1->vec.y + area_min;
}
else if (sa->v2->vec.y - y < area_min) {
y = sa->v2->vec.y - area_min;
}
return y;
}
else {
x = sa->v1->vec.x + round_fl_to_short(fac * cur_area_width);
return y;
}
else {
x = sa->v1->vec.x + round_fl_to_short(fac * cur_area_width);
area_min = area_min_x;
area_min = area_min_x;
if (sa->v1->vec.x > window_rect->xmin) {
area_min += U.pixelsize;
}
if (sa->v4->vec.x < (window_rect->xmax - 1)) {
area_min += U.pixelsize;
}
if (sa->v1->vec.x > window_rect->xmin) {
area_min += U.pixelsize;
}
if (sa->v4->vec.x < (window_rect->xmax - 1)) {
area_min += U.pixelsize;
}
if (x - sa->v1->vec.x < area_min) {
x = sa->v1->vec.x + area_min;
}
else if (sa->v4->vec.x - x < area_min) {
x = sa->v4->vec.x - area_min;
}
if (x - sa->v1->vec.x < area_min) {
x = sa->v1->vec.x + area_min;
}
else if (sa->v4->vec.x - x < area_min) {
x = sa->v4->vec.x - area_min;
}
return x;
}
return x;
}
}
/**
@@ -415,44 +414,45 @@ short screen_geom_find_area_split_point(const ScrArea *sa, const rcti *window_re
*/
void screen_geom_select_connected_edge(const wmWindow *win, ScrEdge *edge)
{
bScreen *sc = WM_window_get_active_screen(win);
bool oneselected = true;
char dir;
bScreen *sc = WM_window_get_active_screen(win);
bool oneselected = true;
char dir;
/* select connected, only in the right direction */
/* 'dir' is the direction of EDGE */
/* select connected, only in the right direction */
/* 'dir' is the direction of EDGE */
if (edge->v1->vec.x == edge->v2->vec.x) {
dir = 'v';
}
else {
dir = 'h';
}
if (edge->v1->vec.x == edge->v2->vec.x) {
dir = 'v';
}
else {
dir = 'h';
}
ED_screen_verts_iter(win, sc, sv) {
sv->flag = 0;
}
ED_screen_verts_iter(win, sc, sv)
{
sv->flag = 0;
}
edge->v1->flag = 1;
edge->v2->flag = 1;
edge->v1->flag = 1;
edge->v2->flag = 1;
while (oneselected) {
oneselected = false;
for (ScrEdge *se = sc->edgebase.first; se; se = se->next) {
if (se->v1->flag + se->v2->flag == 1) {
if (dir == 'h') {
if (se->v1->vec.y == se->v2->vec.y) {
se->v1->flag = se->v2->flag = 1;
oneselected = true;
}
}
if (dir == 'v') {
if (se->v1->vec.x == se->v2->vec.x) {
se->v1->flag = se->v2->flag = 1;
oneselected = true;
}
}
}
}
}
while (oneselected) {
oneselected = false;
for (ScrEdge *se = sc->edgebase.first; se; se = se->next) {
if (se->v1->flag + se->v2->flag == 1) {
if (dir == 'h') {
if (se->v1->vec.y == se->v2->vec.y) {
se->v1->flag = se->v2->flag = 1;
oneselected = true;
}
}
if (dir == 'v') {
if (se->v1->vec.x == se->v2->vec.x) {
se->v1->flag = se->v2->flag = 1;
oneselected = true;
}
}
}
}
}
}

View File

@@ -30,62 +30,69 @@ struct bContextDataResult;
/* internal exports only */
#define AZONESPOTW UI_HEADER_OFFSET /* width of corner azone - max */
#define AZONESPOTH (0.6f * U.widget_unit) /* height of corner azone */
#define AZONEFADEIN (5.0f * U.widget_unit) /* when azone is totally visible */
#define AZONEFADEOUT (6.5f * U.widget_unit) /* when we start seeing the azone */
#define AZONESPOTW UI_HEADER_OFFSET /* width of corner azone - max */
#define AZONESPOTH (0.6f * U.widget_unit) /* height of corner azone */
#define AZONEFADEIN (5.0f * U.widget_unit) /* when azone is totally visible */
#define AZONEFADEOUT (6.5f * U.widget_unit) /* when we start seeing the azone */
/* area.c */
void ED_area_data_copy(ScrArea *sa_dst, ScrArea *sa_src, const bool do_free);
void ED_area_data_swap(ScrArea *sa1, ScrArea *sa2);
void region_toggle_hidden(struct bContext *C, ARegion *ar, const bool do_fade);
void ED_area_data_copy(ScrArea *sa_dst, ScrArea *sa_src, const bool do_free);
void ED_area_data_swap(ScrArea *sa1, ScrArea *sa2);
void region_toggle_hidden(struct bContext *C, ARegion *ar, const bool do_fade);
/* screen_edit.c */
bScreen *screen_add(struct Main *bmain, const char *name, const rcti *rect);
void screen_data_copy(bScreen *to, bScreen *from);
void screen_new_activate_prepare(const wmWindow *win, bScreen *screen_new);
void screen_change_update(struct bContext *C, wmWindow *win, bScreen *sc);
bScreen *screen_change_prepare(bScreen *screen_old, bScreen *screen_new, struct Main *bmain, struct bContext *C, wmWindow *win);
ScrArea *area_split(const wmWindow *win, bScreen *sc, ScrArea *sa, char dir, float fac, int merge);
int screen_area_join(struct bContext *C, bScreen *scr, ScrArea *sa1, ScrArea *sa2);
int area_getorientation(ScrArea *sa, ScrArea *sb);
bScreen *screen_add(struct Main *bmain, const char *name, const rcti *rect);
void screen_data_copy(bScreen *to, bScreen *from);
void screen_new_activate_prepare(const wmWindow *win, bScreen *screen_new);
void screen_change_update(struct bContext *C, wmWindow *win, bScreen *sc);
bScreen *screen_change_prepare(bScreen *screen_old,
bScreen *screen_new,
struct Main *bmain,
struct bContext *C,
wmWindow *win);
ScrArea *area_split(const wmWindow *win, bScreen *sc, ScrArea *sa, char dir, float fac, int merge);
int screen_area_join(struct bContext *C, bScreen *scr, ScrArea *sa1, ScrArea *sa2);
int area_getorientation(ScrArea *sa, ScrArea *sb);
struct AZone *ED_area_actionzone_find_xy(ScrArea *sa, const int xy[2]);
/* screen_geometry.c */
int screen_geom_area_height(const ScrArea *area);
int screen_geom_area_width(const ScrArea *area);
ScrVert *screen_geom_vertex_add_ex(ScrAreaMap *area_map, short x, short y);
ScrVert *screen_geom_vertex_add(bScreen *sc, short x, short y);
ScrEdge *screen_geom_edge_add_ex(ScrAreaMap *area_map, ScrVert *v1, ScrVert *v2);
ScrEdge *screen_geom_edge_add(bScreen *sc, ScrVert *v1, ScrVert *v2);
bool screen_geom_edge_is_horizontal(ScrEdge *se);
ScrEdge *screen_geom_area_map_find_active_scredge(
const struct ScrAreaMap *area_map,
const rcti *bounds_rect,
const int mx, const int my);
ScrEdge *screen_geom_find_active_scredge(
const wmWindow *win, const bScreen *screen,
const int mx, const int my);
void screen_geom_vertices_scale(const wmWindow *win, bScreen *sc);
short screen_geom_find_area_split_point(const ScrArea *sa, const rcti *window_rect, char dir, float fac);
void screen_geom_select_connected_edge(const wmWindow *win, ScrEdge *edge);
int screen_geom_area_height(const ScrArea *area);
int screen_geom_area_width(const ScrArea *area);
ScrVert *screen_geom_vertex_add_ex(ScrAreaMap *area_map, short x, short y);
ScrVert *screen_geom_vertex_add(bScreen *sc, short x, short y);
ScrEdge *screen_geom_edge_add_ex(ScrAreaMap *area_map, ScrVert *v1, ScrVert *v2);
ScrEdge *screen_geom_edge_add(bScreen *sc, ScrVert *v1, ScrVert *v2);
bool screen_geom_edge_is_horizontal(ScrEdge *se);
ScrEdge *screen_geom_area_map_find_active_scredge(const struct ScrAreaMap *area_map,
const rcti *bounds_rect,
const int mx,
const int my);
ScrEdge *screen_geom_find_active_scredge(const wmWindow *win,
const bScreen *screen,
const int mx,
const int my);
void screen_geom_vertices_scale(const wmWindow *win, bScreen *sc);
short screen_geom_find_area_split_point(const ScrArea *sa,
const rcti *window_rect,
char dir,
float fac);
void screen_geom_select_connected_edge(const wmWindow *win, ScrEdge *edge);
/* screen_context.c */
int ed_screen_context(
const struct bContext *C, const char *member, struct bContextDataResult *result);
int ed_screen_context(const struct bContext *C,
const char *member,
struct bContextDataResult *result);
extern const char *screen_context_dir[]; /* doc access */
/* screendump.c */
void SCREEN_OT_screenshot(struct wmOperatorType *ot);
void SCREEN_OT_screenshot(struct wmOperatorType *ot);
/* screen_ops.c */
void region_blend_start(struct bContext *C, struct ScrArea *sa, struct ARegion *ar);
void region_blend_start(struct bContext *C, struct ScrArea *sa, struct ARegion *ar);
/* workspace_layout_edit.c */
bool workspace_layout_set_poll(const struct WorkSpaceLayout *layout);
#endif /* __SCREEN_INTERN_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -57,29 +57,33 @@
bUserMenu **ED_screen_user_menus_find(const bContext *C, uint *r_len)
{
SpaceLink *sl = CTX_wm_space_data(C);
const char *context = CTX_data_mode_string(C);
SpaceLink *sl = CTX_wm_space_data(C);
const char *context = CTX_data_mode_string(C);
if (sl == NULL) {
*r_len = 0;
return NULL;
}
if (sl == NULL) {
*r_len = 0;
return NULL;
}
uint array_len = 3;
bUserMenu **um_array = MEM_calloc_arrayN(array_len, sizeof(*um_array), __func__);
um_array[0] = BKE_blender_user_menu_find(&U.user_menus, sl->spacetype, context);
um_array[1] = (sl->spacetype != SPACE_TOPBAR) ? BKE_blender_user_menu_find(&U.user_menus, SPACE_TOPBAR, context) : NULL;
um_array[2] = (sl->spacetype == SPACE_VIEW3D) ? BKE_blender_user_menu_find(&U.user_menus, SPACE_PROPERTIES, context) : NULL;
uint array_len = 3;
bUserMenu **um_array = MEM_calloc_arrayN(array_len, sizeof(*um_array), __func__);
um_array[0] = BKE_blender_user_menu_find(&U.user_menus, sl->spacetype, context);
um_array[1] = (sl->spacetype != SPACE_TOPBAR) ?
BKE_blender_user_menu_find(&U.user_menus, SPACE_TOPBAR, context) :
NULL;
um_array[2] = (sl->spacetype == SPACE_VIEW3D) ?
BKE_blender_user_menu_find(&U.user_menus, SPACE_PROPERTIES, context) :
NULL;
*r_len = array_len;
return um_array;
*r_len = array_len;
return um_array;
}
bUserMenu *ED_screen_user_menu_ensure(bContext *C)
{
SpaceLink *sl = CTX_wm_space_data(C);
const char *context = CTX_data_mode_string(C);
return BKE_blender_user_menu_ensure(&U.user_menus, sl->spacetype, context);
SpaceLink *sl = CTX_wm_space_data(C);
const char *context = CTX_data_mode_string(C);
return BKE_blender_user_menu_ensure(&U.user_menus, sl->spacetype, context);
}
/** \} */
@@ -88,96 +92,98 @@ bUserMenu *ED_screen_user_menu_ensure(bContext *C)
/** \name Menu Item
* \{ */
bUserMenuItem_Op *ED_screen_user_menu_item_find_operator(
ListBase *lb,
const wmOperatorType *ot, IDProperty *prop, short opcontext)
bUserMenuItem_Op *ED_screen_user_menu_item_find_operator(ListBase *lb,
const wmOperatorType *ot,
IDProperty *prop,
short opcontext)
{
for (bUserMenuItem *umi = lb->first; umi; umi = umi->next) {
if (umi->type == USER_MENU_TYPE_OPERATOR) {
bUserMenuItem_Op *umi_op = (bUserMenuItem_Op *)umi;
if (STREQ(ot->idname, umi_op->op_idname) &&
(opcontext == umi_op->opcontext) &&
(IDP_EqualsProperties(prop, umi_op->prop)))
{
return umi_op;
}
}
}
return NULL;
for (bUserMenuItem *umi = lb->first; umi; umi = umi->next) {
if (umi->type == USER_MENU_TYPE_OPERATOR) {
bUserMenuItem_Op *umi_op = (bUserMenuItem_Op *)umi;
if (STREQ(ot->idname, umi_op->op_idname) && (opcontext == umi_op->opcontext) &&
(IDP_EqualsProperties(prop, umi_op->prop))) {
return umi_op;
}
}
}
return NULL;
}
struct bUserMenuItem_Menu *ED_screen_user_menu_item_find_menu(
struct ListBase *lb,
const struct MenuType *mt)
struct bUserMenuItem_Menu *ED_screen_user_menu_item_find_menu(struct ListBase *lb,
const struct MenuType *mt)
{
for (bUserMenuItem *umi = lb->first; umi; umi = umi->next) {
if (umi->type == USER_MENU_TYPE_MENU) {
bUserMenuItem_Menu *umi_mt = (bUserMenuItem_Menu *)umi;
if (STREQ(mt->idname, umi_mt->mt_idname)) {
return umi_mt;
}
}
}
return NULL;
for (bUserMenuItem *umi = lb->first; umi; umi = umi->next) {
if (umi->type == USER_MENU_TYPE_MENU) {
bUserMenuItem_Menu *umi_mt = (bUserMenuItem_Menu *)umi;
if (STREQ(mt->idname, umi_mt->mt_idname)) {
return umi_mt;
}
}
}
return NULL;
}
struct bUserMenuItem_Prop *ED_screen_user_menu_item_find_prop(
struct ListBase *lb,
const char *context_data_path, const char *prop_id, int prop_index)
struct bUserMenuItem_Prop *ED_screen_user_menu_item_find_prop(struct ListBase *lb,
const char *context_data_path,
const char *prop_id,
int prop_index)
{
for (bUserMenuItem *umi = lb->first; umi; umi = umi->next) {
if (umi->type == USER_MENU_TYPE_PROP) {
bUserMenuItem_Prop *umi_pr = (bUserMenuItem_Prop *)umi;
if (STREQ(context_data_path, umi_pr->context_data_path) &&
STREQ(prop_id, umi_pr->prop_id) &&
(prop_index == umi_pr->prop_index))
{
return umi_pr;
}
}
}
return NULL;
for (bUserMenuItem *umi = lb->first; umi; umi = umi->next) {
if (umi->type == USER_MENU_TYPE_PROP) {
bUserMenuItem_Prop *umi_pr = (bUserMenuItem_Prop *)umi;
if (STREQ(context_data_path, umi_pr->context_data_path) && STREQ(prop_id, umi_pr->prop_id) &&
(prop_index == umi_pr->prop_index)) {
return umi_pr;
}
}
}
return NULL;
}
void ED_screen_user_menu_item_add_operator(
ListBase *lb, const char *ui_name,
const wmOperatorType *ot, const IDProperty *prop, short opcontext)
void ED_screen_user_menu_item_add_operator(ListBase *lb,
const char *ui_name,
const wmOperatorType *ot,
const IDProperty *prop,
short opcontext)
{
bUserMenuItem_Op *umi_op = (bUserMenuItem_Op *)BKE_blender_user_menu_item_add(lb, USER_MENU_TYPE_OPERATOR);
umi_op->opcontext = opcontext;
if (!STREQ(ui_name, ot->name)) {
STRNCPY(umi_op->item.ui_name, ui_name);
}
STRNCPY(umi_op->op_idname, ot->idname);
umi_op->prop = prop ? IDP_CopyProperty(prop) : NULL;
bUserMenuItem_Op *umi_op = (bUserMenuItem_Op *)BKE_blender_user_menu_item_add(
lb, USER_MENU_TYPE_OPERATOR);
umi_op->opcontext = opcontext;
if (!STREQ(ui_name, ot->name)) {
STRNCPY(umi_op->item.ui_name, ui_name);
}
STRNCPY(umi_op->op_idname, ot->idname);
umi_op->prop = prop ? IDP_CopyProperty(prop) : NULL;
}
void ED_screen_user_menu_item_add_menu(
ListBase *lb, const char *ui_name,
const MenuType *mt)
void ED_screen_user_menu_item_add_menu(ListBase *lb, const char *ui_name, const MenuType *mt)
{
bUserMenuItem_Menu *umi_mt = (bUserMenuItem_Menu *)BKE_blender_user_menu_item_add(lb, USER_MENU_TYPE_MENU);
if (!STREQ(ui_name, mt->label)) {
STRNCPY(umi_mt->item.ui_name, ui_name);
}
STRNCPY(umi_mt->mt_idname, mt->idname);
bUserMenuItem_Menu *umi_mt = (bUserMenuItem_Menu *)BKE_blender_user_menu_item_add(
lb, USER_MENU_TYPE_MENU);
if (!STREQ(ui_name, mt->label)) {
STRNCPY(umi_mt->item.ui_name, ui_name);
}
STRNCPY(umi_mt->mt_idname, mt->idname);
}
void ED_screen_user_menu_item_add_prop(
ListBase *lb, const char *ui_name,
const char *context_data_path, const char *prop_id, int prop_index)
void ED_screen_user_menu_item_add_prop(ListBase *lb,
const char *ui_name,
const char *context_data_path,
const char *prop_id,
int prop_index)
{
bUserMenuItem_Prop *umi_pr = (bUserMenuItem_Prop *)BKE_blender_user_menu_item_add(lb, USER_MENU_TYPE_PROP);
STRNCPY(umi_pr->item.ui_name, ui_name);
STRNCPY(umi_pr->context_data_path, context_data_path);
STRNCPY(umi_pr->prop_id, prop_id);
umi_pr->prop_index = prop_index;
bUserMenuItem_Prop *umi_pr = (bUserMenuItem_Prop *)BKE_blender_user_menu_item_add(
lb, USER_MENU_TYPE_PROP);
STRNCPY(umi_pr->item.ui_name, ui_name);
STRNCPY(umi_pr->context_data_path, context_data_path);
STRNCPY(umi_pr->prop_id, prop_id);
umi_pr->prop_index = prop_index;
}
void ED_screen_user_menu_item_remove(ListBase *lb, bUserMenuItem *umi)
{
BLI_remlink(lb, umi);
BKE_blender_user_menu_item_free(umi);
BLI_remlink(lb, umi);
BKE_blender_user_menu_item_free(umi);
}
/** \} */
@@ -188,95 +194,92 @@ void ED_screen_user_menu_item_remove(ListBase *lb, bUserMenuItem *umi)
static void screen_user_menu_draw(const bContext *C, Menu *menu)
{
uint um_array_len;
bUserMenu **um_array = ED_screen_user_menus_find(C, &um_array_len);
bool is_empty = true;
for (int um_index = 0; um_index < um_array_len; um_index++) {
bUserMenu *um = um_array[um_index];
if (um == NULL) {
continue;
}
for (bUserMenuItem *umi = um->items.first; umi; umi = umi->next) {
const char *ui_name = umi->ui_name[0] ? umi->ui_name : NULL;
if (umi->type == USER_MENU_TYPE_OPERATOR) {
bUserMenuItem_Op *umi_op = (bUserMenuItem_Op *)umi;
IDProperty *prop = umi_op->prop ? IDP_CopyProperty(umi_op->prop) : NULL;
uiItemFullO(
menu->layout, umi_op->op_idname, ui_name,
ICON_NONE, prop, umi_op->opcontext, 0, NULL);
is_empty = false;
}
else if (umi->type == USER_MENU_TYPE_MENU) {
bUserMenuItem_Menu *umi_mt = (bUserMenuItem_Menu *)umi;
uiItemM(menu->layout, umi_mt->mt_idname, ui_name,
ICON_NONE);
is_empty = false;
}
else if (umi->type == USER_MENU_TYPE_PROP) {
bUserMenuItem_Prop *umi_pr = (bUserMenuItem_Prop *)umi;
uint um_array_len;
bUserMenu **um_array = ED_screen_user_menus_find(C, &um_array_len);
bool is_empty = true;
for (int um_index = 0; um_index < um_array_len; um_index++) {
bUserMenu *um = um_array[um_index];
if (um == NULL) {
continue;
}
for (bUserMenuItem *umi = um->items.first; umi; umi = umi->next) {
const char *ui_name = umi->ui_name[0] ? umi->ui_name : NULL;
if (umi->type == USER_MENU_TYPE_OPERATOR) {
bUserMenuItem_Op *umi_op = (bUserMenuItem_Op *)umi;
IDProperty *prop = umi_op->prop ? IDP_CopyProperty(umi_op->prop) : NULL;
uiItemFullO(
menu->layout, umi_op->op_idname, ui_name, ICON_NONE, prop, umi_op->opcontext, 0, NULL);
is_empty = false;
}
else if (umi->type == USER_MENU_TYPE_MENU) {
bUserMenuItem_Menu *umi_mt = (bUserMenuItem_Menu *)umi;
uiItemM(menu->layout, umi_mt->mt_idname, ui_name, ICON_NONE);
is_empty = false;
}
else if (umi->type == USER_MENU_TYPE_PROP) {
bUserMenuItem_Prop *umi_pr = (bUserMenuItem_Prop *)umi;
char *data_path = strchr(umi_pr->context_data_path, '.');
if (data_path) {
*data_path = '\0';
}
PointerRNA ptr = CTX_data_pointer_get(C, umi_pr->context_data_path);
if (ptr.type == NULL) {
PointerRNA ctx_ptr;
RNA_pointer_create(NULL, &RNA_Context, (void *)C, &ctx_ptr);
if (!RNA_path_resolve_full(&ctx_ptr, umi_pr->context_data_path, &ptr, NULL, NULL)) {
ptr.type = NULL;
}
}
if (data_path) {
*data_path = '.';
data_path += 1;
}
char *data_path = strchr(umi_pr->context_data_path, '.');
if (data_path) {
*data_path = '\0';
}
PointerRNA ptr = CTX_data_pointer_get(C, umi_pr->context_data_path);
if (ptr.type == NULL) {
PointerRNA ctx_ptr;
RNA_pointer_create(NULL, &RNA_Context, (void *)C, &ctx_ptr);
if (!RNA_path_resolve_full(&ctx_ptr, umi_pr->context_data_path, &ptr, NULL, NULL)) {
ptr.type = NULL;
}
}
if (data_path) {
*data_path = '.';
data_path += 1;
}
bool ok = false;
if (ptr.type != NULL) {
PropertyRNA *prop = NULL;
PointerRNA prop_ptr = ptr;
if ((data_path == NULL) || RNA_path_resolve_full(&ptr, data_path, &prop_ptr, NULL, NULL)) {
prop = RNA_struct_find_property(&prop_ptr, umi_pr->prop_id);
if (prop) {
ok = true;
uiItemFullR(
menu->layout,
&prop_ptr, prop, umi_pr->prop_index,
0, 0, ui_name, ICON_NONE);
is_empty = false;
}
}
}
if (!ok) {
char label[512];
SNPRINTF(label, "Missing: %s.%s", umi_pr->context_data_path, umi_pr->prop_id);
uiItemL(menu->layout, label, ICON_NONE);
}
}
else if (umi->type == USER_MENU_TYPE_SEP) {
uiItemS(menu->layout);
}
}
}
if (um_array) {
MEM_freeN(um_array);
}
bool ok = false;
if (ptr.type != NULL) {
PropertyRNA *prop = NULL;
PointerRNA prop_ptr = ptr;
if ((data_path == NULL) ||
RNA_path_resolve_full(&ptr, data_path, &prop_ptr, NULL, NULL)) {
prop = RNA_struct_find_property(&prop_ptr, umi_pr->prop_id);
if (prop) {
ok = true;
uiItemFullR(
menu->layout, &prop_ptr, prop, umi_pr->prop_index, 0, 0, ui_name, ICON_NONE);
is_empty = false;
}
}
}
if (!ok) {
char label[512];
SNPRINTF(label, "Missing: %s.%s", umi_pr->context_data_path, umi_pr->prop_id);
uiItemL(menu->layout, label, ICON_NONE);
}
}
else if (umi->type == USER_MENU_TYPE_SEP) {
uiItemS(menu->layout);
}
}
}
if (um_array) {
MEM_freeN(um_array);
}
if (is_empty) {
uiItemL(menu->layout, IFACE_("No menu items found"), ICON_NONE);
uiItemL(menu->layout, IFACE_("Right click on buttons to add them to this menu"), ICON_NONE);
}
if (is_empty) {
uiItemL(menu->layout, IFACE_("No menu items found"), ICON_NONE);
uiItemL(menu->layout, IFACE_("Right click on buttons to add them to this menu"), ICON_NONE);
}
}
void ED_screen_user_menu_register(void)
{
MenuType *mt = MEM_callocN(sizeof(MenuType), __func__);
strcpy(mt->idname, "SCREEN_MT_user_menu");
strcpy(mt->label, "Quick Favorites");
strcpy(mt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
mt->draw = screen_user_menu_draw;
WM_menutype_add(mt);
MenuType *mt = MEM_callocN(sizeof(MenuType), __func__);
strcpy(mt->idname, "SCREEN_MT_user_menu");
strcpy(mt->label, "Quick Favorites");
strcpy(mt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
mt->draw = screen_user_menu_draw;
WM_menutype_add(mt);
}
/** \} */

View File

@@ -22,7 +22,6 @@
* \ingroup edscr
*/
#include <string.h>
#include <errno.h>
@@ -57,239 +56,249 @@
#include "screen_intern.h"
typedef struct ScreenshotData {
unsigned int *dumprect;
int dumpsx, dumpsy;
rcti crop;
unsigned int *dumprect;
int dumpsx, dumpsy;
rcti crop;
ImageFormatData im_format;
ImageFormatData im_format;
} ScreenshotData;
static void screenshot_read_pixels(int x, int y, int w, int h, unsigned char *rect)
{
int i;
int i;
glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, rect);
glFinish();
glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, rect);
glFinish();
/* clear alpha, it is not set to a meaningful value in opengl */
for (i = 0, rect += 3; i < w * h; i++, rect += 4)
*rect = 255;
/* clear alpha, it is not set to a meaningful value in opengl */
for (i = 0, rect += 3; i < w * h; i++, rect += 4)
*rect = 255;
}
/* get shot from frontbuffer */
static unsigned int *screenshot(bContext *C, int *dumpsx, int *dumpsy)
{
wmWindow *win = CTX_wm_window(C);
int x = 0, y = 0;
unsigned int *dumprect = NULL;
wmWindow *win = CTX_wm_window(C);
int x = 0, y = 0;
unsigned int *dumprect = NULL;
x = 0;
y = 0;
*dumpsx = WM_window_pixels_x(win);
*dumpsy = WM_window_pixels_y(win);
x = 0;
y = 0;
*dumpsx = WM_window_pixels_x(win);
*dumpsy = WM_window_pixels_y(win);
if (*dumpsx && *dumpsy) {
if (*dumpsx && *dumpsy) {
dumprect = MEM_mallocN(sizeof(int) * (*dumpsx) * (*dumpsy), "dumprect");
glReadBuffer(GL_FRONT);
screenshot_read_pixels(x, y, *dumpsx, *dumpsy, (unsigned char *)dumprect);
glReadBuffer(GL_BACK);
}
dumprect = MEM_mallocN(sizeof(int) * (*dumpsx) * (*dumpsy), "dumprect");
glReadBuffer(GL_FRONT);
screenshot_read_pixels(x, y, *dumpsx, *dumpsy, (unsigned char *)dumprect);
glReadBuffer(GL_BACK);
}
return dumprect;
return dumprect;
}
/* call from both exec and invoke */
static int screenshot_data_create(bContext *C, wmOperator *op)
{
unsigned int *dumprect;
int dumpsx, dumpsy;
unsigned int *dumprect;
int dumpsx, dumpsy;
/* do redraw so we don't show popups/menus */
WM_redraw_windows(C);
/* do redraw so we don't show popups/menus */
WM_redraw_windows(C);
dumprect = screenshot(C, &dumpsx, &dumpsy);
dumprect = screenshot(C, &dumpsx, &dumpsy);
if (dumprect) {
ScreenshotData *scd = MEM_callocN(sizeof(ScreenshotData), "screenshot");
ScrArea *sa = CTX_wm_area(C);
if (dumprect) {
ScreenshotData *scd = MEM_callocN(sizeof(ScreenshotData), "screenshot");
ScrArea *sa = CTX_wm_area(C);
scd->dumpsx = dumpsx;
scd->dumpsy = dumpsy;
scd->dumprect = dumprect;
if (sa) {
scd->crop = sa->totrct;
}
scd->dumpsx = dumpsx;
scd->dumpsy = dumpsy;
scd->dumprect = dumprect;
if (sa) {
scd->crop = sa->totrct;
}
BKE_imformat_defaults(&scd->im_format);
BKE_imformat_defaults(&scd->im_format);
op->customdata = scd;
op->customdata = scd;
return true;
}
else {
op->customdata = NULL;
return false;
}
return true;
}
else {
op->customdata = NULL;
return false;
}
}
static void screenshot_data_free(wmOperator *op)
{
ScreenshotData *scd = op->customdata;
ScreenshotData *scd = op->customdata;
if (scd) {
if (scd->dumprect)
MEM_freeN(scd->dumprect);
MEM_freeN(scd);
op->customdata = NULL;
}
if (scd) {
if (scd->dumprect)
MEM_freeN(scd->dumprect);
MEM_freeN(scd);
op->customdata = NULL;
}
}
static void screenshot_crop(ImBuf *ibuf, rcti crop)
{
unsigned int *to = ibuf->rect;
unsigned int *from = ibuf->rect + crop.ymin * ibuf->x + crop.xmin;
int crop_x = BLI_rcti_size_x(&crop);
int crop_y = BLI_rcti_size_y(&crop);
int y;
unsigned int *to = ibuf->rect;
unsigned int *from = ibuf->rect + crop.ymin * ibuf->x + crop.xmin;
int crop_x = BLI_rcti_size_x(&crop);
int crop_y = BLI_rcti_size_y(&crop);
int y;
if (crop_x > 0 && crop_y > 0) {
for (y = 0; y < crop_y; y++, to += crop_x, from += ibuf->x)
memmove(to, from, sizeof(unsigned int) * crop_x);
if (crop_x > 0 && crop_y > 0) {
for (y = 0; y < crop_y; y++, to += crop_x, from += ibuf->x)
memmove(to, from, sizeof(unsigned int) * crop_x);
ibuf->x = crop_x;
ibuf->y = crop_y;
}
ibuf->x = crop_x;
ibuf->y = crop_y;
}
}
static int screenshot_exec(bContext *C, wmOperator *op)
{
ScreenshotData *scd = op->customdata;
bool ok = false;
ScreenshotData *scd = op->customdata;
bool ok = false;
if (scd == NULL) {
/* when running exec directly */
screenshot_data_create(C, op);
scd = op->customdata;
}
if (scd == NULL) {
/* when running exec directly */
screenshot_data_create(C, op);
scd = op->customdata;
}
if (scd) {
if (scd->dumprect) {
ImBuf *ibuf;
char path[FILE_MAX];
if (scd) {
if (scd->dumprect) {
ImBuf *ibuf;
char path[FILE_MAX];
RNA_string_get(op->ptr, "filepath", path);
BLI_path_abs(path, BKE_main_blendfile_path_from_global());
RNA_string_get(op->ptr, "filepath", path);
BLI_path_abs(path, BKE_main_blendfile_path_from_global());
/* operator ensures the extension */
ibuf = IMB_allocImBuf(scd->dumpsx, scd->dumpsy, 24, 0);
ibuf->rect = scd->dumprect;
/* operator ensures the extension */
ibuf = IMB_allocImBuf(scd->dumpsx, scd->dumpsy, 24, 0);
ibuf->rect = scd->dumprect;
/* crop to show only single editor */
if (!RNA_boolean_get(op->ptr, "full"))
screenshot_crop(ibuf, scd->crop);
/* crop to show only single editor */
if (!RNA_boolean_get(op->ptr, "full"))
screenshot_crop(ibuf, scd->crop);
if (scd->im_format.planes == R_IMF_PLANES_BW) {
/* bw screenshot? - users will notice if it fails! */
IMB_color_to_bw(ibuf);
}
if (BKE_imbuf_write(ibuf, path, &scd->im_format)) {
ok = true;
}
else {
BKE_reportf(op->reports, RPT_ERROR, "Could not write image: %s", strerror(errno));
}
if (scd->im_format.planes == R_IMF_PLANES_BW) {
/* bw screenshot? - users will notice if it fails! */
IMB_color_to_bw(ibuf);
}
if (BKE_imbuf_write(ibuf, path, &scd->im_format)) {
ok = true;
}
else {
BKE_reportf(op->reports, RPT_ERROR, "Could not write image: %s", strerror(errno));
}
IMB_freeImBuf(ibuf);
}
}
IMB_freeImBuf(ibuf);
}
}
screenshot_data_free(op);
screenshot_data_free(op);
return ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
return ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
static int screenshot_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (screenshot_data_create(C, op)) {
if (RNA_struct_property_is_set(op->ptr, "filepath"))
return screenshot_exec(C, op);
if (screenshot_data_create(C, op)) {
if (RNA_struct_property_is_set(op->ptr, "filepath"))
return screenshot_exec(C, op);
/* extension is added by 'screenshot_check' after */
char filepath[FILE_MAX] = "//screen";
if (G.relbase_valid) {
BLI_strncpy(filepath, BKE_main_blendfile_path_from_global(), sizeof(filepath));
BLI_path_extension_replace(filepath, sizeof(filepath), ""); /* strip '.blend' */
}
RNA_string_set(op->ptr, "filepath", filepath);
/* extension is added by 'screenshot_check' after */
char filepath[FILE_MAX] = "//screen";
if (G.relbase_valid) {
BLI_strncpy(filepath, BKE_main_blendfile_path_from_global(), sizeof(filepath));
BLI_path_extension_replace(filepath, sizeof(filepath), ""); /* strip '.blend' */
}
RNA_string_set(op->ptr, "filepath", filepath);
WM_event_add_fileselect(C, op);
WM_event_add_fileselect(C, op);
return OPERATOR_RUNNING_MODAL;
}
return OPERATOR_CANCELLED;
return OPERATOR_RUNNING_MODAL;
}
return OPERATOR_CANCELLED;
}
static bool screenshot_check(bContext *UNUSED(C), wmOperator *op)
{
ScreenshotData *scd = op->customdata;
return WM_operator_filesel_ensure_ext_imtype(op, &scd->im_format);
ScreenshotData *scd = op->customdata;
return WM_operator_filesel_ensure_ext_imtype(op, &scd->im_format);
}
static void screenshot_cancel(bContext *UNUSED(C), wmOperator *op)
{
screenshot_data_free(op);
screenshot_data_free(op);
}
static bool screenshot_draw_check_prop(PointerRNA *UNUSED(ptr), PropertyRNA *prop, void *UNUSED(user_data))
static bool screenshot_draw_check_prop(PointerRNA *UNUSED(ptr),
PropertyRNA *prop,
void *UNUSED(user_data))
{
const char *prop_id = RNA_property_identifier(prop);
const char *prop_id = RNA_property_identifier(prop);
return !(STREQ(prop_id, "filepath"));
return !(STREQ(prop_id, "filepath"));
}
static void screenshot_draw(bContext *UNUSED(C), wmOperator *op)
{
uiLayout *layout = op->layout;
ScreenshotData *scd = op->customdata;
PointerRNA ptr;
uiLayout *layout = op->layout;
ScreenshotData *scd = op->customdata;
PointerRNA ptr;
/* image template */
RNA_pointer_create(NULL, &RNA_ImageFormatSettings, &scd->im_format, &ptr);
uiTemplateImageSettings(layout, &ptr, false);
/* image template */
RNA_pointer_create(NULL, &RNA_ImageFormatSettings, &scd->im_format, &ptr);
uiTemplateImageSettings(layout, &ptr, false);
/* main draw call */
RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
uiDefAutoButsRNA(layout, &ptr, screenshot_draw_check_prop, NULL, NULL, UI_BUT_LABEL_ALIGN_NONE, false);
/* main draw call */
RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
uiDefAutoButsRNA(
layout, &ptr, screenshot_draw_check_prop, NULL, NULL, UI_BUT_LABEL_ALIGN_NONE, false);
}
static bool screenshot_poll(bContext *C)
{
if (G.background)
return false;
if (G.background)
return false;
return WM_operator_winactive(C);
return WM_operator_winactive(C);
}
void SCREEN_OT_screenshot(wmOperatorType *ot)
{
/* weak: opname starting with 'save' makes filewindow give save-over */
ot->name = "Save Screenshot";
ot->idname = "SCREEN_OT_screenshot";
ot->description = "Capture a picture of the active area or whole Blender window";
/* weak: opname starting with 'save' makes filewindow give save-over */
ot->name = "Save Screenshot";
ot->idname = "SCREEN_OT_screenshot";
ot->description = "Capture a picture of the active area or whole Blender window";
ot->invoke = screenshot_invoke;
ot->check = screenshot_check;
ot->exec = screenshot_exec;
ot->cancel = screenshot_cancel;
ot->ui = screenshot_draw;
ot->poll = screenshot_poll;
ot->invoke = screenshot_invoke;
ot->check = screenshot_check;
ot->exec = screenshot_exec;
ot->cancel = screenshot_cancel;
ot->ui = screenshot_draw;
ot->poll = screenshot_poll;
ot->flag = 0;
ot->flag = 0;
WM_operator_properties_filesel(
ot, FILE_TYPE_FOLDER | FILE_TYPE_IMAGE, FILE_SPECIAL, FILE_SAVE,
WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
RNA_def_boolean(ot->srna, "full", 1, "Full Screen",
"Capture the whole window (otherwise only capture the active area)");
WM_operator_properties_filesel(ot,
FILE_TYPE_FOLDER | FILE_TYPE_IMAGE,
FILE_SPECIAL,
FILE_SAVE,
WM_FILESEL_FILEPATH,
FILE_DEFAULTDISPLAY,
FILE_SORT_ALPHA);
RNA_def_boolean(ot->srna,
"full",
1,
"Full Screen",
"Capture the whole window (otherwise only capture the active area)");
}

View File

@@ -67,7 +67,6 @@
#include "screen_intern.h"
/** \name Workspace API
*
* \brief API for managing workspaces and their data.
@@ -75,69 +74,70 @@
WorkSpace *ED_workspace_add(Main *bmain, const char *name)
{
return BKE_workspace_add(bmain, name);
return BKE_workspace_add(bmain, name);
}
/**
* Changes the object mode (if needed) to the one set in \a workspace_new.
* Object mode is still stored on object level. In future it should all be workspace level instead.
*/
static void workspace_change_update(
WorkSpace *workspace_new, const WorkSpace *workspace_old,
bContext *C, wmWindowManager *wm)
static void workspace_change_update(WorkSpace *workspace_new,
const WorkSpace *workspace_old,
bContext *C,
wmWindowManager *wm)
{
/* needs to be done before changing mode! (to ensure right context) */
UNUSED_VARS(workspace_old, workspace_new, C, wm);
/* needs to be done before changing mode! (to ensure right context) */
UNUSED_VARS(workspace_old, workspace_new, C, wm);
#if 0
Object *ob_act = CTX_data_active_object(C)
eObjectMode mode_old = workspace_old->object_mode;
eObjectMode mode_new = workspace_new->object_mode;
Object *ob_act = CTX_data_active_object(C)
eObjectMode mode_old = workspace_old->object_mode;
eObjectMode mode_new = workspace_new->object_mode;
if (mode_old != mode_new) {
ED_object_mode_compat_set(C, ob_act, mode_new, &wm->reports);
ED_object_mode_toggle(C, mode_new);
}
if (mode_old != mode_new) {
ED_object_mode_compat_set(C, ob_act, mode_new, &wm->reports);
ED_object_mode_toggle(C, mode_new);
}
#endif
}
static bool workspace_change_find_new_layout_cb(const WorkSpaceLayout *layout, void *UNUSED(arg))
{
/* return false to stop the iterator if we've found a layout that can be activated */
return workspace_layout_set_poll(layout) ? false : true;
/* return false to stop the iterator if we've found a layout that can be activated */
return workspace_layout_set_poll(layout) ? false : true;
}
static WorkSpaceLayout *workspace_change_get_new_layout(
Main *bmain, WorkSpace *workspace_new, wmWindow *win)
static WorkSpaceLayout *workspace_change_get_new_layout(Main *bmain,
WorkSpace *workspace_new,
wmWindow *win)
{
/* ED_workspace_duplicate may have stored a layout to activate once the workspace gets activated. */
WorkSpaceLayout *layout_old = WM_window_get_active_layout(win);
WorkSpaceLayout *layout_new;
bScreen *screen_new;
/* ED_workspace_duplicate may have stored a layout to activate once the workspace gets activated. */
WorkSpaceLayout *layout_old = WM_window_get_active_layout(win);
WorkSpaceLayout *layout_new;
bScreen *screen_new;
if (win->workspace_hook->temp_workspace_store) {
layout_new = win->workspace_hook->temp_layout_store;
}
else {
layout_new = BKE_workspace_hook_layout_for_workspace_get(win->workspace_hook, workspace_new);
if (!layout_new) {
layout_new = BKE_workspace_layouts_get(workspace_new)->first;
}
}
screen_new = BKE_workspace_layout_screen_get(layout_new);
if (win->workspace_hook->temp_workspace_store) {
layout_new = win->workspace_hook->temp_layout_store;
}
else {
layout_new = BKE_workspace_hook_layout_for_workspace_get(win->workspace_hook, workspace_new);
if (!layout_new) {
layout_new = BKE_workspace_layouts_get(workspace_new)->first;
}
}
screen_new = BKE_workspace_layout_screen_get(layout_new);
if (screen_new->winid) {
/* screen is already used, try to find a free one */
WorkSpaceLayout *layout_temp = BKE_workspace_layout_iter_circular(
workspace_new, layout_new, workspace_change_find_new_layout_cb,
NULL, false);
if (!layout_temp) {
/* fallback solution: duplicate layout from old workspace */
layout_temp = ED_workspace_layout_duplicate(bmain, workspace_new, layout_old, win);
}
layout_new = layout_temp;
}
if (screen_new->winid) {
/* screen is already used, try to find a free one */
WorkSpaceLayout *layout_temp = BKE_workspace_layout_iter_circular(
workspace_new, layout_new, workspace_change_find_new_layout_cb, NULL, false);
if (!layout_temp) {
/* fallback solution: duplicate layout from old workspace */
layout_temp = ED_workspace_layout_duplicate(bmain, workspace_new, layout_old, win);
}
layout_new = layout_temp;
}
return layout_new;
return layout_new;
}
/**
@@ -149,464 +149,472 @@ static WorkSpaceLayout *workspace_change_get_new_layout(
* \warning Do NOT call in area/region queues!
* \returns if workspace changing was successful.
*/
bool ED_workspace_change(
WorkSpace *workspace_new, bContext *C, wmWindowManager *wm, wmWindow *win)
bool ED_workspace_change(WorkSpace *workspace_new, bContext *C, wmWindowManager *wm, wmWindow *win)
{
Main *bmain = CTX_data_main(C);
WorkSpace *workspace_old = WM_window_get_active_workspace(win);
WorkSpaceLayout *layout_new = workspace_change_get_new_layout(bmain, workspace_new, win);
bScreen *screen_new = BKE_workspace_layout_screen_get(layout_new);
bScreen *screen_old = BKE_workspace_active_screen_get(win->workspace_hook);
Main *bmain = CTX_data_main(C);
WorkSpace *workspace_old = WM_window_get_active_workspace(win);
WorkSpaceLayout *layout_new = workspace_change_get_new_layout(bmain, workspace_new, win);
bScreen *screen_new = BKE_workspace_layout_screen_get(layout_new);
bScreen *screen_old = BKE_workspace_active_screen_get(win->workspace_hook);
win->workspace_hook->temp_layout_store = NULL;
if (workspace_old == workspace_new) {
/* Could also return true, everything that needs to be done was done (nothing :P), but nothing changed */
return false;
}
win->workspace_hook->temp_layout_store = NULL;
if (workspace_old == workspace_new) {
/* Could also return true, everything that needs to be done was done (nothing :P), but nothing changed */
return false;
}
screen_new = screen_change_prepare(screen_old, screen_new, bmain, C, win);
BLI_assert(BKE_workspace_layout_screen_get(layout_new) == screen_new);
screen_new = screen_change_prepare(screen_old, screen_new, bmain, C, win);
BLI_assert(BKE_workspace_layout_screen_get(layout_new) == screen_new);
if (screen_new == NULL) {
return false;
}
if (screen_new == NULL) {
return false;
}
BKE_workspace_hook_layout_for_workspace_set(win->workspace_hook, workspace_new, layout_new);
BKE_workspace_active_set(win->workspace_hook, workspace_new);
BKE_workspace_hook_layout_for_workspace_set(win->workspace_hook, workspace_new, layout_new);
BKE_workspace_active_set(win->workspace_hook, workspace_new);
/* update screen *after* changing workspace - which also causes the
* actual screen change and updates context (including CTX_wm_workspace) */
screen_change_update(C, win, screen_new);
workspace_change_update(workspace_new, workspace_old, C, wm);
/* update screen *after* changing workspace - which also causes the
* actual screen change and updates context (including CTX_wm_workspace) */
screen_change_update(C, win, screen_new);
workspace_change_update(workspace_new, workspace_old, C, wm);
BLI_assert(CTX_wm_workspace(C) == workspace_new);
BLI_assert(CTX_wm_workspace(C) == workspace_new);
WM_toolsystem_unlink_all(C, workspace_old);
/* Area initialization will initialize based on the new workspace. */
WM_toolsystem_unlink_all(C, workspace_old);
/* Area initialization will initialize based on the new workspace. */
/* Automatic mode switching. */
if (workspace_new->object_mode != workspace_old->object_mode) {
ED_object_mode_generic_enter(C, workspace_new->object_mode);
}
/* Automatic mode switching. */
if (workspace_new->object_mode != workspace_old->object_mode) {
ED_object_mode_generic_enter(C, workspace_new->object_mode);
}
return true;
return true;
}
/**
* Duplicate a workspace including its layouts. Does not activate the workspace, but
* it stores the screen-layout to be activated (BKE_workspace_temp_layout_store)
*/
WorkSpace *ED_workspace_duplicate(
WorkSpace *workspace_old, Main *bmain, wmWindow *win)
WorkSpace *ED_workspace_duplicate(WorkSpace *workspace_old, Main *bmain, wmWindow *win)
{
WorkSpaceLayout *layout_active_old = BKE_workspace_active_layout_get(win->workspace_hook);
ListBase *layouts_old = BKE_workspace_layouts_get(workspace_old);
WorkSpace *workspace_new = ED_workspace_add(bmain, workspace_old->id.name + 2);
WorkSpaceLayout *layout_active_old = BKE_workspace_active_layout_get(win->workspace_hook);
ListBase *layouts_old = BKE_workspace_layouts_get(workspace_old);
WorkSpace *workspace_new = ED_workspace_add(bmain, workspace_old->id.name + 2);
workspace_new->flags = workspace_old->flags;
BLI_duplicatelist(&workspace_new->owner_ids, &workspace_old->owner_ids);
workspace_new->flags = workspace_old->flags;
BLI_duplicatelist(&workspace_new->owner_ids, &workspace_old->owner_ids);
/* TODO(campbell): tools */
/* TODO(campbell): tools */
for (WorkSpaceLayout *layout_old = layouts_old->first; layout_old; layout_old = layout_old->next) {
WorkSpaceLayout *layout_new = ED_workspace_layout_duplicate(bmain, workspace_new, layout_old, win);
for (WorkSpaceLayout *layout_old = layouts_old->first; layout_old;
layout_old = layout_old->next) {
WorkSpaceLayout *layout_new = ED_workspace_layout_duplicate(
bmain, workspace_new, layout_old, win);
if (layout_active_old == layout_old) {
win->workspace_hook->temp_layout_store = layout_new;
}
}
return workspace_new;
if (layout_active_old == layout_old) {
win->workspace_hook->temp_layout_store = layout_new;
}
}
return workspace_new;
}
/**
* \return if succeeded.
*/
bool ED_workspace_delete(
WorkSpace *workspace, Main *bmain, bContext *C, wmWindowManager *wm)
bool ED_workspace_delete(WorkSpace *workspace, Main *bmain, bContext *C, wmWindowManager *wm)
{
if (BLI_listbase_is_single(&bmain->workspaces)) {
return false;
}
if (BLI_listbase_is_single(&bmain->workspaces)) {
return false;
}
ListBase ordered;
BKE_id_ordered_list(&ordered, &bmain->workspaces);
WorkSpace *prev = NULL, *next = NULL;
for (LinkData *link = ordered.first; link; link = link->next) {
if (link->data == workspace) {
prev = link->prev ? link->prev->data : NULL;
next = link->next ? link->next->data : NULL;
break;
}
}
BLI_freelistN(&ordered);
BLI_assert((prev != NULL) || (next != NULL));
ListBase ordered;
BKE_id_ordered_list(&ordered, &bmain->workspaces);
WorkSpace *prev = NULL, *next = NULL;
for (LinkData *link = ordered.first; link; link = link->next) {
if (link->data == workspace) {
prev = link->prev ? link->prev->data : NULL;
next = link->next ? link->next->data : NULL;
break;
}
}
BLI_freelistN(&ordered);
BLI_assert((prev != NULL) || (next != NULL));
for (wmWindow *win = wm->windows.first; win; win = win->next) {
WorkSpace *workspace_active = WM_window_get_active_workspace(win);
if (workspace_active == workspace) {
ED_workspace_change((prev != NULL) ? prev : next, C, wm, win);
}
}
for (wmWindow *win = wm->windows.first; win; win = win->next) {
WorkSpace *workspace_active = WM_window_get_active_workspace(win);
if (workspace_active == workspace) {
ED_workspace_change((prev != NULL) ? prev : next, C, wm, win);
}
}
BKE_id_free(bmain, &workspace->id);
return true;
BKE_id_free(bmain, &workspace->id);
return true;
}
/**
* Some editor data may need to be synced with scene data (3D View camera and layers).
* This function ensures data is synced for editors in active layout of \a workspace.
*/
void ED_workspace_scene_data_sync(
WorkSpaceInstanceHook *hook, Scene *scene)
void ED_workspace_scene_data_sync(WorkSpaceInstanceHook *hook, Scene *scene)
{
bScreen *screen = BKE_workspace_active_screen_get(hook);
BKE_screen_view3d_scene_sync(screen, scene);
bScreen *screen = BKE_workspace_active_screen_get(hook);
BKE_screen_view3d_scene_sync(screen, scene);
}
/** \} Workspace API */
/** \name Workspace Operators
*
* \{ */
static WorkSpace *workspace_context_get(bContext *C)
{
ID *id = UI_context_active_but_get_tab_ID(C);
if (id && GS(id->name) == ID_WS) {
return (WorkSpace *)id;
}
ID *id = UI_context_active_but_get_tab_ID(C);
if (id && GS(id->name) == ID_WS) {
return (WorkSpace *)id;
}
wmWindow *win = CTX_wm_window(C);
return WM_window_get_active_workspace(win);
wmWindow *win = CTX_wm_window(C);
return WM_window_get_active_workspace(win);
}
static bool workspace_context_poll(bContext *C)
{
return workspace_context_get(C) != NULL;
return workspace_context_get(C) != NULL;
}
static int workspace_new_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
wmWindow *win = CTX_wm_window(C);
WorkSpace *workspace = workspace_context_get(C);
Main *bmain = CTX_data_main(C);
wmWindow *win = CTX_wm_window(C);
WorkSpace *workspace = workspace_context_get(C);
workspace = ED_workspace_duplicate(workspace, bmain, win);
workspace = ED_workspace_duplicate(workspace, bmain, win);
WM_event_add_notifier(C, NC_SCREEN | ND_WORKSPACE_SET, workspace);
WM_event_add_notifier(C, NC_SCREEN | ND_WORKSPACE_SET, workspace);
return OPERATOR_FINISHED;
return OPERATOR_FINISHED;
}
static void WORKSPACE_OT_duplicate(wmOperatorType *ot)
{
/* identifiers */
ot->name = "New Workspace";
ot->description = "Add a new workspace";
ot->idname = "WORKSPACE_OT_duplicate";
/* identifiers */
ot->name = "New Workspace";
ot->description = "Add a new workspace";
ot->idname = "WORKSPACE_OT_duplicate";
/* api callbacks */
ot->poll = workspace_context_poll;
ot->exec = workspace_new_exec;
/* api callbacks */
ot->poll = workspace_context_poll;
ot->exec = workspace_new_exec;
}
static int workspace_delete_exec(bContext *C, wmOperator *UNUSED(op))
{
WorkSpace *workspace = workspace_context_get(C);
WM_event_add_notifier(C, NC_SCREEN | ND_WORKSPACE_DELETE, workspace);
WM_event_add_notifier(C, NC_WINDOW, NULL);
WorkSpace *workspace = workspace_context_get(C);
WM_event_add_notifier(C, NC_SCREEN | ND_WORKSPACE_DELETE, workspace);
WM_event_add_notifier(C, NC_WINDOW, NULL);
return OPERATOR_FINISHED;
return OPERATOR_FINISHED;
}
static void WORKSPACE_OT_delete(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Delete Workspace";
ot->description = "Delete the active workspace";
ot->idname = "WORKSPACE_OT_delete";
/* identifiers */
ot->name = "Delete Workspace";
ot->description = "Delete the active workspace";
ot->idname = "WORKSPACE_OT_delete";
/* api callbacks */
ot->poll = workspace_context_poll;
ot->exec = workspace_delete_exec;
/* api callbacks */
ot->poll = workspace_context_poll;
ot->exec = workspace_delete_exec;
}
static bool workspace_append_activate_poll(bContext *C)
{
wmOperatorType *ot = WM_operatortype_find("WM_OT_append", false);
return WM_operator_poll(C, ot);
wmOperatorType *ot = WM_operatortype_find("WM_OT_append", false);
return WM_operator_poll(C, ot);
}
static int workspace_append(bContext *C, const char *directory, const char *idname)
{
wmOperatorType *ot = WM_operatortype_find("WM_OT_append", false);
PointerRNA opptr;
int retval;
wmOperatorType *ot = WM_operatortype_find("WM_OT_append", false);
PointerRNA opptr;
int retval;
WM_operator_properties_create_ptr(&opptr, ot);
RNA_string_set(&opptr, "directory", directory);
RNA_string_set(&opptr, "filename", idname);
RNA_boolean_set(&opptr, "autoselect", false);
WM_operator_properties_create_ptr(&opptr, ot);
RNA_string_set(&opptr, "directory", directory);
RNA_string_set(&opptr, "filename", idname);
RNA_boolean_set(&opptr, "autoselect", false);
retval = WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &opptr);
retval = WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &opptr);
WM_operator_properties_free(&opptr);
WM_operator_properties_free(&opptr);
return retval;
return retval;
}
static int workspace_append_activate_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
char idname[MAX_ID_NAME - 2], filepath[FILE_MAX];
Main *bmain = CTX_data_main(C);
char idname[MAX_ID_NAME - 2], filepath[FILE_MAX];
if (!RNA_struct_property_is_set(op->ptr, "idname") ||
!RNA_struct_property_is_set(op->ptr, "filepath"))
{
return OPERATOR_CANCELLED;
}
RNA_string_get(op->ptr, "idname", idname);
RNA_string_get(op->ptr, "filepath", filepath);
if (!RNA_struct_property_is_set(op->ptr, "idname") ||
!RNA_struct_property_is_set(op->ptr, "filepath")) {
return OPERATOR_CANCELLED;
}
RNA_string_get(op->ptr, "idname", idname);
RNA_string_get(op->ptr, "filepath", filepath);
if (workspace_append(C, filepath, idname) != OPERATOR_CANCELLED) {
WorkSpace *appended_workspace = BLI_findstring(&bmain->workspaces, idname, offsetof(ID, name) + 2);
BLI_assert(appended_workspace != NULL);
if (workspace_append(C, filepath, idname) != OPERATOR_CANCELLED) {
WorkSpace *appended_workspace = BLI_findstring(
&bmain->workspaces, idname, offsetof(ID, name) + 2);
BLI_assert(appended_workspace != NULL);
/* Reorder to last position. */
BKE_id_reorder(&bmain->workspaces, &appended_workspace->id, NULL, true);
/* Reorder to last position. */
BKE_id_reorder(&bmain->workspaces, &appended_workspace->id, NULL, true);
/* Changing workspace changes context. Do delayed! */
WM_event_add_notifier(C, NC_SCREEN | ND_WORKSPACE_SET, appended_workspace);
/* Changing workspace changes context. Do delayed! */
WM_event_add_notifier(C, NC_SCREEN | ND_WORKSPACE_SET, appended_workspace);
return OPERATOR_FINISHED;
}
return OPERATOR_FINISHED;
}
return OPERATOR_CANCELLED;
return OPERATOR_CANCELLED;
}
static void WORKSPACE_OT_append_activate(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Append and Activate Workspace";
ot->description = "Append a workspace and make it the active one in the current window";
ot->idname = "WORKSPACE_OT_append_activate";
/* identifiers */
ot->name = "Append and Activate Workspace";
ot->description = "Append a workspace and make it the active one in the current window";
ot->idname = "WORKSPACE_OT_append_activate";
/* api callbacks */
ot->exec = workspace_append_activate_exec;
ot->poll = workspace_append_activate_poll;
/* api callbacks */
ot->exec = workspace_append_activate_exec;
ot->poll = workspace_append_activate_poll;
RNA_def_string(ot->srna, "idname", NULL, MAX_ID_NAME - 2, "Identifier",
"Name of the workspace to append and activate");
RNA_def_string(ot->srna, "filepath", NULL, FILE_MAX, "Filepath",
"Path to the library");
RNA_def_string(ot->srna,
"idname",
NULL,
MAX_ID_NAME - 2,
"Identifier",
"Name of the workspace to append and activate");
RNA_def_string(ot->srna, "filepath", NULL, FILE_MAX, "Filepath", "Path to the library");
}
static WorkspaceConfigFileData *workspace_config_file_read(const char *app_template)
{
const char *cfgdir = BKE_appdir_folder_id(BLENDER_USER_CONFIG, app_template);
char startup_file_path[FILE_MAX] = {0};
const char *cfgdir = BKE_appdir_folder_id(BLENDER_USER_CONFIG, app_template);
char startup_file_path[FILE_MAX] = {0};
if (cfgdir) {
BLI_join_dirfile(startup_file_path, sizeof(startup_file_path), cfgdir, BLENDER_STARTUP_FILE);
}
if (cfgdir) {
BLI_join_dirfile(startup_file_path, sizeof(startup_file_path), cfgdir, BLENDER_STARTUP_FILE);
}
bool has_path = BLI_exists(startup_file_path);
return (has_path) ? BKE_blendfile_workspace_config_read(startup_file_path, NULL, 0, NULL) : NULL;
bool has_path = BLI_exists(startup_file_path);
return (has_path) ? BKE_blendfile_workspace_config_read(startup_file_path, NULL, 0, NULL) : NULL;
}
static WorkspaceConfigFileData *workspace_system_file_read(const char *app_template)
{
if (app_template == NULL) {
return BKE_blendfile_workspace_config_read(NULL, datatoc_startup_blend, datatoc_startup_blend_size, NULL);
}
if (app_template == NULL) {
return BKE_blendfile_workspace_config_read(
NULL, datatoc_startup_blend, datatoc_startup_blend_size, NULL);
}
char template_dir[FILE_MAX];
if (!BKE_appdir_app_template_id_search(app_template, template_dir, sizeof(template_dir))) {
return NULL;
}
char template_dir[FILE_MAX];
if (!BKE_appdir_app_template_id_search(app_template, template_dir, sizeof(template_dir))) {
return NULL;
}
char startup_file_path[FILE_MAX];
BLI_join_dirfile(startup_file_path, sizeof(startup_file_path), template_dir, BLENDER_STARTUP_FILE);
char startup_file_path[FILE_MAX];
BLI_join_dirfile(
startup_file_path, sizeof(startup_file_path), template_dir, BLENDER_STARTUP_FILE);
bool has_path = BLI_exists(startup_file_path);
return (has_path) ? BKE_blendfile_workspace_config_read(startup_file_path, NULL, 0, NULL) : NULL;
bool has_path = BLI_exists(startup_file_path);
return (has_path) ? BKE_blendfile_workspace_config_read(startup_file_path, NULL, 0, NULL) : NULL;
}
static void workspace_append_button(
uiLayout *layout, wmOperatorType *ot_append, const WorkSpace *workspace, const Main *from_main)
static void workspace_append_button(uiLayout *layout,
wmOperatorType *ot_append,
const WorkSpace *workspace,
const Main *from_main)
{
const ID *id = (ID *)workspace;
PointerRNA opptr;
char lib_path[FILE_MAX_LIBEXTRA];
const char *filepath = from_main->name;
const ID *id = (ID *)workspace;
PointerRNA opptr;
char lib_path[FILE_MAX_LIBEXTRA];
const char *filepath = from_main->name;
if (strlen(filepath) == 0) {
filepath = BLO_EMBEDDED_STARTUP_BLEND;
}
if (strlen(filepath) == 0) {
filepath = BLO_EMBEDDED_STARTUP_BLEND;
}
BLI_path_join(
lib_path, sizeof(lib_path), filepath, BKE_idcode_to_name(GS(id->name)), NULL);
BLI_path_join(lib_path, sizeof(lib_path), filepath, BKE_idcode_to_name(GS(id->name)), NULL);
BLI_assert(STREQ(ot_append->idname, "WORKSPACE_OT_append_activate"));
uiItemFullO_ptr(
layout, ot_append, workspace->id.name + 2, ICON_NONE, NULL,
WM_OP_EXEC_DEFAULT, 0, &opptr);
RNA_string_set(&opptr, "idname", id->name + 2);
RNA_string_set(&opptr, "filepath", lib_path);
BLI_assert(STREQ(ot_append->idname, "WORKSPACE_OT_append_activate"));
uiItemFullO_ptr(
layout, ot_append, workspace->id.name + 2, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &opptr);
RNA_string_set(&opptr, "idname", id->name + 2);
RNA_string_set(&opptr, "filepath", lib_path);
}
static void workspace_add_menu(bContext *C, uiLayout *layout, void *template_v)
{
Main *bmain = CTX_data_main(C);
const char *app_template = template_v;
bool has_startup_items = false;
Main *bmain = CTX_data_main(C);
const char *app_template = template_v;
bool has_startup_items = false;
wmOperatorType *ot_append = WM_operatortype_find("WORKSPACE_OT_append_activate", true);
WorkspaceConfigFileData *startup_config = workspace_config_file_read(app_template);
WorkspaceConfigFileData *builtin_config = workspace_system_file_read(app_template);
wmOperatorType *ot_append = WM_operatortype_find("WORKSPACE_OT_append_activate", true);
WorkspaceConfigFileData *startup_config = workspace_config_file_read(app_template);
WorkspaceConfigFileData *builtin_config = workspace_system_file_read(app_template);
if (startup_config) {
for (WorkSpace *workspace = startup_config->workspaces.first; workspace; workspace = workspace->id.next) {
uiLayout *row = uiLayoutRow(layout, false);
if (BLI_findstring(&bmain->workspaces, workspace->id.name, offsetof(ID, name))) {
uiLayoutSetActive(row, false);
}
if (startup_config) {
for (WorkSpace *workspace = startup_config->workspaces.first; workspace;
workspace = workspace->id.next) {
uiLayout *row = uiLayoutRow(layout, false);
if (BLI_findstring(&bmain->workspaces, workspace->id.name, offsetof(ID, name))) {
uiLayoutSetActive(row, false);
}
workspace_append_button(row, ot_append, workspace, startup_config->main);
has_startup_items = true;
}
}
workspace_append_button(row, ot_append, workspace, startup_config->main);
has_startup_items = true;
}
}
if (builtin_config) {
bool has_title = false;
if (builtin_config) {
bool has_title = false;
for (WorkSpace *workspace = builtin_config->workspaces.first; workspace; workspace = workspace->id.next) {
if (startup_config && BLI_findstring(&startup_config->workspaces, workspace->id.name, offsetof(ID, name))) {
continue;
}
for (WorkSpace *workspace = builtin_config->workspaces.first; workspace;
workspace = workspace->id.next) {
if (startup_config &&
BLI_findstring(&startup_config->workspaces, workspace->id.name, offsetof(ID, name))) {
continue;
}
if (!has_title) {
if (has_startup_items) {
uiItemS(layout);
}
has_title = true;
}
if (!has_title) {
if (has_startup_items) {
uiItemS(layout);
}
has_title = true;
}
uiLayout *row = uiLayoutRow(layout, false);
if (BLI_findstring(&bmain->workspaces, workspace->id.name, offsetof(ID, name))) {
uiLayoutSetActive(row, false);
}
uiLayout *row = uiLayoutRow(layout, false);
if (BLI_findstring(&bmain->workspaces, workspace->id.name, offsetof(ID, name))) {
uiLayoutSetActive(row, false);
}
workspace_append_button(row, ot_append, workspace, builtin_config->main);
}
}
workspace_append_button(row, ot_append, workspace, builtin_config->main);
}
}
if (startup_config) {
BKE_blendfile_workspace_config_data_free(startup_config);
}
if (builtin_config) {
BKE_blendfile_workspace_config_data_free(builtin_config);
}
if (startup_config) {
BKE_blendfile_workspace_config_data_free(startup_config);
}
if (builtin_config) {
BKE_blendfile_workspace_config_data_free(builtin_config);
}
}
static int workspace_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
uiPopupMenu *pup = UI_popup_menu_begin(C, op->type->name, ICON_ADD);
uiLayout *layout = UI_popup_menu_layout(pup);
uiPopupMenu *pup = UI_popup_menu_begin(C, op->type->name, ICON_ADD);
uiLayout *layout = UI_popup_menu_layout(pup);
uiItemMenuF(layout, IFACE_("General"), ICON_NONE, workspace_add_menu, NULL);
uiItemMenuF(layout, IFACE_("General"), ICON_NONE, workspace_add_menu, NULL);
ListBase templates;
BKE_appdir_app_templates(&templates);
ListBase templates;
BKE_appdir_app_templates(&templates);
for (LinkData *link = templates.first; link; link = link->next) {
char *template = link->data;
char display_name[FILE_MAX];
for (LinkData *link = templates.first; link; link = link->next) {
char *template = link->data;
char display_name[FILE_MAX];
BLI_path_to_display_name(display_name, sizeof(display_name), template);
BLI_path_to_display_name(display_name, sizeof(display_name), template);
/* Steals ownership of link data string. */
uiItemMenuFN(layout, display_name, ICON_NONE, workspace_add_menu, template);
}
/* Steals ownership of link data string. */
uiItemMenuFN(layout, display_name, ICON_NONE, workspace_add_menu, template);
}
BLI_freelistN(&templates);
BLI_freelistN(&templates);
uiItemS(layout);
uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Duplicate Current"), ICON_DUPLICATE,
"WORKSPACE_OT_duplicate");
uiItemS(layout);
uiItemO(layout,
CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Duplicate Current"),
ICON_DUPLICATE,
"WORKSPACE_OT_duplicate");
UI_popup_menu_end(C, pup);
UI_popup_menu_end(C, pup);
return OPERATOR_INTERFACE;
return OPERATOR_INTERFACE;
}
static void WORKSPACE_OT_add(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Add Workspace";
ot->description = "Add a new workspace by duplicating the current one or appending one "
"from the user configuration";
ot->idname = "WORKSPACE_OT_add";
/* identifiers */
ot->name = "Add Workspace";
ot->description =
"Add a new workspace by duplicating the current one or appending one "
"from the user configuration";
ot->idname = "WORKSPACE_OT_add";
/* api callbacks */
ot->invoke = workspace_add_invoke;
/* api callbacks */
ot->invoke = workspace_add_invoke;
}
static int workspace_reorder_to_back_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
WorkSpace *workspace = workspace_context_get(C);
Main *bmain = CTX_data_main(C);
WorkSpace *workspace = workspace_context_get(C);
BKE_id_reorder(&bmain->workspaces, &workspace->id, NULL, true);
WM_event_add_notifier(C, NC_WINDOW, NULL);
BKE_id_reorder(&bmain->workspaces, &workspace->id, NULL, true);
WM_event_add_notifier(C, NC_WINDOW, NULL);
return OPERATOR_INTERFACE;
return OPERATOR_INTERFACE;
}
static void WORKSPACE_OT_reorder_to_back(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Workspace Reorder to Back";
ot->description = "Reorder workspace to be first in the list";
ot->idname = "WORKSPACE_OT_reorder_to_back";
/* identifiers */
ot->name = "Workspace Reorder to Back";
ot->description = "Reorder workspace to be first in the list";
ot->idname = "WORKSPACE_OT_reorder_to_back";
/* api callbacks */
ot->poll = workspace_context_poll;
ot->exec = workspace_reorder_to_back_exec;
/* api callbacks */
ot->poll = workspace_context_poll;
ot->exec = workspace_reorder_to_back_exec;
}
static int workspace_reorder_to_front_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
WorkSpace *workspace = workspace_context_get(C);
Main *bmain = CTX_data_main(C);
WorkSpace *workspace = workspace_context_get(C);
BKE_id_reorder(&bmain->workspaces, &workspace->id, NULL, false);
WM_event_add_notifier(C, NC_WINDOW, NULL);
BKE_id_reorder(&bmain->workspaces, &workspace->id, NULL, false);
WM_event_add_notifier(C, NC_WINDOW, NULL);
return OPERATOR_INTERFACE;
return OPERATOR_INTERFACE;
}
static void WORKSPACE_OT_reorder_to_front(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Workspace Reorder to Front";
ot->description = "Reorder workspace to be first in the list";
ot->idname = "WORKSPACE_OT_reorder_to_front";
/* identifiers */
ot->name = "Workspace Reorder to Front";
ot->description = "Reorder workspace to be first in the list";
ot->idname = "WORKSPACE_OT_reorder_to_front";
/* api callbacks */
ot->poll = workspace_context_poll;
ot->exec = workspace_reorder_to_front_exec;
/* api callbacks */
ot->poll = workspace_context_poll;
ot->exec = workspace_reorder_to_front_exec;
}
void ED_operatortypes_workspace(void)
{
WM_operatortype_append(WORKSPACE_OT_duplicate);
WM_operatortype_append(WORKSPACE_OT_delete);
WM_operatortype_append(WORKSPACE_OT_add);
WM_operatortype_append(WORKSPACE_OT_append_activate);
WM_operatortype_append(WORKSPACE_OT_reorder_to_back);
WM_operatortype_append(WORKSPACE_OT_reorder_to_front);
WM_operatortype_append(WORKSPACE_OT_duplicate);
WM_operatortype_append(WORKSPACE_OT_delete);
WM_operatortype_append(WORKSPACE_OT_add);
WM_operatortype_append(WORKSPACE_OT_append_activate);
WM_operatortype_append(WORKSPACE_OT_reorder_to_back);
WM_operatortype_append(WORKSPACE_OT_reorder_to_front);
}
/** \} Workspace Operators */

View File

@@ -40,164 +40,163 @@
/**
* Empty screen, with 1 dummy area without spacedata. Uses window size.
*/
WorkSpaceLayout *ED_workspace_layout_add(
Main *bmain,
WorkSpace *workspace,
wmWindow *win,
const char *name)
WorkSpaceLayout *ED_workspace_layout_add(Main *bmain,
WorkSpace *workspace,
wmWindow *win,
const char *name)
{
bScreen *screen;
rcti screen_rect;
bScreen *screen;
rcti screen_rect;
WM_window_screen_rect_calc(win, &screen_rect);
screen = screen_add(bmain, name, &screen_rect);
WM_window_screen_rect_calc(win, &screen_rect);
screen = screen_add(bmain, name, &screen_rect);
return BKE_workspace_layout_add(bmain, workspace, screen, name);
return BKE_workspace_layout_add(bmain, workspace, screen, name);
}
WorkSpaceLayout *ED_workspace_layout_duplicate(
Main *bmain,
WorkSpace *workspace, const WorkSpaceLayout *layout_old,
wmWindow *win)
WorkSpaceLayout *ED_workspace_layout_duplicate(Main *bmain,
WorkSpace *workspace,
const WorkSpaceLayout *layout_old,
wmWindow *win)
{
bScreen *screen_old = BKE_workspace_layout_screen_get(layout_old);
const char *name = BKE_workspace_layout_name_get(layout_old);
bScreen *screen_new;
WorkSpaceLayout *layout_new;
bScreen *screen_old = BKE_workspace_layout_screen_get(layout_old);
const char *name = BKE_workspace_layout_name_get(layout_old);
bScreen *screen_new;
WorkSpaceLayout *layout_new;
layout_new = ED_workspace_layout_add(bmain, workspace, win, name);
screen_new = BKE_workspace_layout_screen_get(layout_new);
layout_new = ED_workspace_layout_add(bmain, workspace, win, name);
screen_new = BKE_workspace_layout_screen_get(layout_new);
if (BKE_screen_is_fullscreen_area(screen_old)) {
for (ScrArea *area_old = screen_old->areabase.first; area_old; area_old = area_old->next) {
if (area_old->full) {
ScrArea *area_new = (ScrArea *)screen_new->areabase.first;
ED_area_data_copy(area_new, area_old, true);
ED_area_tag_redraw(area_new);
break;
}
}
}
else {
screen_data_copy(screen_new, screen_old);
}
if (BKE_screen_is_fullscreen_area(screen_old)) {
for (ScrArea *area_old = screen_old->areabase.first; area_old; area_old = area_old->next) {
if (area_old->full) {
ScrArea *area_new = (ScrArea *)screen_new->areabase.first;
ED_area_data_copy(area_new, area_old, true);
ED_area_tag_redraw(area_new);
break;
}
}
}
else {
screen_data_copy(screen_new, screen_old);
}
return layout_new;
return layout_new;
}
static bool workspace_layout_delete_doit(
WorkSpace *workspace, WorkSpaceLayout *layout_old, WorkSpaceLayout *layout_new,
bContext *C)
static bool workspace_layout_delete_doit(WorkSpace *workspace,
WorkSpaceLayout *layout_old,
WorkSpaceLayout *layout_new,
bContext *C)
{
Main *bmain = CTX_data_main(C);
wmWindow *win = CTX_wm_window(C);
bScreen *screen_new = BKE_workspace_layout_screen_get(layout_new);
Main *bmain = CTX_data_main(C);
wmWindow *win = CTX_wm_window(C);
bScreen *screen_new = BKE_workspace_layout_screen_get(layout_new);
ED_screen_change(C, screen_new);
ED_screen_change(C, screen_new);
if (BKE_workspace_active_layout_get(win->workspace_hook) != layout_old) {
BKE_workspace_layout_remove(bmain, workspace, layout_old);
return true;
}
if (BKE_workspace_active_layout_get(win->workspace_hook) != layout_old) {
BKE_workspace_layout_remove(bmain, workspace, layout_old);
return true;
}
return false;
return false;
}
bool workspace_layout_set_poll(const WorkSpaceLayout *layout)
{
const bScreen *screen = BKE_workspace_layout_screen_get(layout);
const bScreen *screen = BKE_workspace_layout_screen_get(layout);
return ((BKE_screen_is_used(screen) == false) &&
/* in typical usage temp screens should have a nonzero winid
* (all temp screens should be used, or closed & freed). */
(screen->temp == false) &&
(BKE_screen_is_fullscreen_area(screen) == false) &&
(screen->id.name[2] != '.' || !(U.uiflag & USER_HIDE_DOT)));
return ((BKE_screen_is_used(screen) == false) &&
/* in typical usage temp screens should have a nonzero winid
* (all temp screens should be used, or closed & freed). */
(screen->temp == false) && (BKE_screen_is_fullscreen_area(screen) == false) &&
(screen->id.name[2] != '.' || !(U.uiflag & USER_HIDE_DOT)));
}
static WorkSpaceLayout *workspace_layout_delete_find_new(const WorkSpaceLayout *layout_old)
{
for (WorkSpaceLayout *layout_new = layout_old->prev; layout_new; layout_new = layout_new->next) {
if (workspace_layout_set_poll(layout_new)) {
return layout_new;
}
}
for (WorkSpaceLayout *layout_new = layout_old->prev; layout_new; layout_new = layout_new->next) {
if (workspace_layout_set_poll(layout_new)) {
return layout_new;
}
}
for (WorkSpaceLayout *layout_new = layout_old->next; layout_new; layout_new = layout_new->next) {
if (workspace_layout_set_poll(layout_new)) {
return layout_new;
}
}
for (WorkSpaceLayout *layout_new = layout_old->next; layout_new; layout_new = layout_new->next) {
if (workspace_layout_set_poll(layout_new)) {
return layout_new;
}
}
return NULL;
return NULL;
}
/**
* \warning Only call outside of area/region loops!
* \return true if succeeded.
*/
bool ED_workspace_layout_delete(
WorkSpace *workspace, WorkSpaceLayout *layout_old,
bContext *C)
bool ED_workspace_layout_delete(WorkSpace *workspace, WorkSpaceLayout *layout_old, bContext *C)
{
const bScreen *screen_old = BKE_workspace_layout_screen_get(layout_old);
WorkSpaceLayout *layout_new;
const bScreen *screen_old = BKE_workspace_layout_screen_get(layout_old);
WorkSpaceLayout *layout_new;
BLI_assert(BLI_findindex(BKE_workspace_layouts_get(workspace), layout_old) != -1);
BLI_assert(BLI_findindex(BKE_workspace_layouts_get(workspace), layout_old) != -1);
/* don't allow deleting temp fullscreens for now */
if (BKE_screen_is_fullscreen_area(screen_old)) {
return false;
}
/* don't allow deleting temp fullscreens for now */
if (BKE_screen_is_fullscreen_area(screen_old)) {
return false;
}
/* A layout/screen can only be in use by one window at a time, so as
* long as we are able to find a layout/screen that is unused, we
* can safely assume ours is not in use anywhere an delete it. */
/* A layout/screen can only be in use by one window at a time, so as
* long as we are able to find a layout/screen that is unused, we
* can safely assume ours is not in use anywhere an delete it. */
layout_new = workspace_layout_delete_find_new(layout_old);
layout_new = workspace_layout_delete_find_new(layout_old);
if (layout_new) {
return workspace_layout_delete_doit(workspace, layout_old, layout_new, C);
}
if (layout_new) {
return workspace_layout_delete_doit(workspace, layout_old, layout_new, C);
}
return false;
return false;
}
static bool workspace_layout_cycle_iter_cb(const WorkSpaceLayout *layout, void *UNUSED(arg))
{
/* return false to stop iterator when we have found a layout to activate */
return !workspace_layout_set_poll(layout);
/* return false to stop iterator when we have found a layout to activate */
return !workspace_layout_set_poll(layout);
}
bool ED_workspace_layout_cycle(
WorkSpace *workspace, const short direction, bContext *C)
bool ED_workspace_layout_cycle(WorkSpace *workspace, const short direction, bContext *C)
{
wmWindow *win = CTX_wm_window(C);
WorkSpaceLayout *old_layout = BKE_workspace_active_layout_get(win->workspace_hook);
WorkSpaceLayout *new_layout;
const bScreen *old_screen = BKE_workspace_layout_screen_get(old_layout);
ScrArea *sa = CTX_wm_area(C);
wmWindow *win = CTX_wm_window(C);
WorkSpaceLayout *old_layout = BKE_workspace_active_layout_get(win->workspace_hook);
WorkSpaceLayout *new_layout;
const bScreen *old_screen = BKE_workspace_layout_screen_get(old_layout);
ScrArea *sa = CTX_wm_area(C);
if (old_screen->temp || (sa && sa->full && sa->full->temp)) {
return false;
}
if (old_screen->temp || (sa && sa->full && sa->full->temp)) {
return false;
}
BLI_assert(ELEM(direction, 1, -1));
new_layout = BKE_workspace_layout_iter_circular(workspace, old_layout, workspace_layout_cycle_iter_cb,
NULL, (direction == -1) ? true : false);
BLI_assert(ELEM(direction, 1, -1));
new_layout = BKE_workspace_layout_iter_circular(workspace,
old_layout,
workspace_layout_cycle_iter_cb,
NULL,
(direction == -1) ? true : false);
if (new_layout && (old_layout != new_layout)) {
bScreen *new_screen = BKE_workspace_layout_screen_get(new_layout);
if (new_layout && (old_layout != new_layout)) {
bScreen *new_screen = BKE_workspace_layout_screen_get(new_layout);
if (sa && sa->full) {
/* return to previous state before switching screens */
ED_screen_full_restore(C, sa); /* may free screen of old_layout */
}
if (sa && sa->full) {
/* return to previous state before switching screens */
ED_screen_full_restore(C, sa); /* may free screen of old_layout */
}
ED_screen_change(C, new_screen);
ED_screen_change(C, new_screen);
return true;
}
return true;
}
return false;
return false;
}