Ejemplo n.º 1
0
static void wm_drop_operator_options(bContext *C, wmDrag *drag, wmEvent *event)
{
	wmWindow *win = CTX_wm_window(C);
	const int winsize_x = WM_window_pixels_x(win);
	const int winsize_y = WM_window_pixels_y(win);

	/* for multiwin drags, we only do this if mouse inside */
	if (event->x < 0 || event->y < 0 || event->x > winsize_x || event->y > winsize_y)
		return;
	
	drag->opname[0] = 0;
	
	/* check buttons (XXX todo rna and value) */
	if (UI_but_active_drop_name(C)) {
		BLI_strncpy(drag->opname, IFACE_("Paste name"), sizeof(drag->opname));
	}
	else {
		const char *opname = wm_dropbox_active(C, drag, event);
		
		if (opname) {
			BLI_strncpy(drag->opname, opname, sizeof(drag->opname));
			// WM_cursor_modal_set(win, CURSOR_COPY);
		}
		// else
		//	WM_cursor_modal_restore(win);
		/* unsure about cursor type, feels to be too much */
	}
}
Ejemplo n.º 2
0
static void wm_method_draw_stereo3d_topbottom(wmWindow *win)
{
	wmDrawData *drawdata;
	wmDrawTriple *triple;
	float halfx, halfy, ratiox, ratioy;
	int view;
	int soffy;

	for (view = 0; view < 2; view ++) {
		drawdata = BLI_findlink(&win->drawdata, (view * 2) + 1);
		triple = drawdata->triple;

		if (view == STEREO_LEFT_ID) {
			soffy = WM_window_pixels_y(win) * 0.5f;
		}
		else { /* STEREO_RIGHT_ID */
			soffy = 0;
		}

		const int sizex = triple->x;
		const int sizey = triple->y;

		/* wmOrtho for the screen has this same offset */
		ratiox = sizex;
		ratioy = sizey;
		halfx = GLA_PIXEL_OFS;
		halfy = GLA_PIXEL_OFS;

		/* texture rectangle has unnormalized coordinates */
		if (triple->target == GL_TEXTURE_2D) {
			ratiox /= triple->x;
			ratioy /= triple->y;
			halfx /= triple->x;
			halfy /= triple->y;
		}

		glEnable(triple->target);
		glBindTexture(triple->target, triple->bind);

		glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
		glBegin(GL_QUADS);
		glTexCoord2f(halfx, halfy);
		glVertex2f(0, soffy);

		glTexCoord2f(ratiox + halfx, halfy);
		glVertex2f(sizex, soffy);

		glTexCoord2f(ratiox + halfx, ratioy + halfy);
		glVertex2f(sizex, soffy + (sizey * 0.5f));

		glTexCoord2f(halfx, ratioy + halfy);
		glVertex2f(0, soffy + (sizey * 0.5f));
		glEnd();

		glBindTexture(triple->target, 0);
		glDisable(triple->target);
	}
}
Ejemplo n.º 3
0
void wmWindowViewport(wmWindow *win)
{
  int width = WM_window_pixels_x(win);
  int height = WM_window_pixels_y(win);

  glViewport(0, 0, width, height);
  glScissor(0, 0, width, height);

  wmOrtho2_pixelspace(width, height);
  GPU_matrix_identity_set();
}
Ejemplo n.º 4
0
static void wm_triple_draw_textures(wmWindow *win, wmDrawTriple *triple, float alpha)
{
	const int winsize_x = WM_window_pixels_x(win);
	const int winsize_y = WM_window_pixels_y(win);

	float halfx, halfy, ratiox, ratioy;
	int x, y, sizex, sizey, offx, offy;

	glEnable(triple->target);

	for (y = 0, offy = 0; y < triple->ny; offy += triple->y[y], y++) {
		for (x = 0, offx = 0; x < triple->nx; offx += triple->x[x], x++) {
			sizex = (x == triple->nx - 1) ? winsize_x - offx : triple->x[x];
			sizey = (y == triple->ny - 1) ? winsize_y - offy : triple->y[y];

			/* wmOrtho for the screen has this same offset */
			ratiox = sizex;
			ratioy = sizey;
			halfx = GLA_PIXEL_OFS;
			halfy = GLA_PIXEL_OFS;

			/* texture rectangle has unnormalized coordinates */
			if (triple->target == GL_TEXTURE_2D) {
				ratiox /= triple->x[x];
				ratioy /= triple->y[y];
				halfx /= triple->x[x];
				halfy /= triple->y[y];
			}

			glBindTexture(triple->target, triple->bind[x + y * triple->nx]);

			glColor4f(1.0f, 1.0f, 1.0f, alpha);
			glBegin(GL_QUADS);
			glTexCoord2f(halfx, halfy);
			glVertex2f(offx, offy);

			glTexCoord2f(ratiox + halfx, halfy);
			glVertex2f(offx + sizex, offy);

			glTexCoord2f(ratiox + halfx, ratioy + halfy);
			glVertex2f(offx + sizex, offy + sizey);

			glTexCoord2f(halfx, ratioy + halfy);
			glVertex2f(offx, offy + sizey);
			glEnd();
		}
	}

	glBindTexture(triple->target, 0);
	glDisable(triple->target);
}
Ejemplo n.º 5
0
static int screencast_exec(bContext *C, wmOperator *op)
{
    wmWindowManager *wm = CTX_wm_manager(C);
    wmWindow *win = CTX_wm_window(C);
    bScreen *screen = CTX_wm_screen(C);
    wmJob *wm_job;
    ScreenshotJob *sj;

    /* if called again, stop the running job */
    if (WM_jobs_test(wm, screen, WM_JOB_TYPE_SCREENCAST))
        WM_jobs_stop(wm, screen, screenshot_startjob);

    wm_job = WM_jobs_get(wm, win, screen, "Screencast", 0, WM_JOB_TYPE_SCREENCAST);
    sj = MEM_callocN(sizeof(ScreenshotJob), "screenshot job");

    /* setup sj */
    if (RNA_boolean_get(op->ptr, "full")) {
        sj->x = 0;
        sj->y = 0;
        sj->dumpsx = WM_window_pixels_x(win);
        sj->dumpsy = WM_window_pixels_y(win);
    }
    else {
        ScrArea *curarea = CTX_wm_area(C);
        sj->x = curarea->totrct.xmin;
        sj->y = curarea->totrct.ymin;
        sj->dumpsx = curarea->totrct.xmax - sj->x;
        sj->dumpsy = curarea->totrct.ymax - sj->y;
    }
    sj->bmain = CTX_data_main(C);
    sj->scene = CTX_data_scene(C);
    sj->wm = wm;

    BKE_reports_init(&sj->reports, RPT_PRINT);

    /* setup job */
    WM_jobs_customdata_set(wm_job, sj, screenshot_freejob);
    WM_jobs_timer(wm_job, 0.1, 0, NC_SCREEN | ND_SCREENCAST);
    WM_jobs_callbacks(wm_job, screenshot_startjob, NULL, screenshot_updatejob, screenshot_endjob);

    WM_jobs_start(sj->wm, wm_job);

    screencast_cursor_toggle(sj->wm, 1);

    WM_event_add_notifier(C, NC_SCREEN | ND_SCREENCAST, screen);

    return OPERATOR_FINISHED;
}
Ejemplo n.º 6
0
static void wm_triple_copy_textures(wmWindow *win, wmDrawTriple *triple)
{
	int x, y, sizex, sizey, offx, offy;

	for (y = 0, offy = 0; y < triple->ny; offy += triple->y[y], y++) {
		for (x = 0, offx = 0; x < triple->nx; offx += triple->x[x], x++) {
			sizex = (x == triple->nx - 1) ? WM_window_pixels_x(win) - offx : triple->x[x];
			sizey = (y == triple->ny - 1) ? WM_window_pixels_y(win) - offy : triple->y[y];

			glBindTexture(triple->target, triple->bind[x + y * triple->nx]);
			glCopyTexSubImage2D(triple->target, 0, 0, 0, offx, offy, sizex, sizey);
		}
	}

	glBindTexture(triple->target, 0);
}
Ejemplo n.º 7
0
static void wm_gesture_draw_cross(wmWindow *win, wmGesture *gt)
{
	rcti *rect = (rcti *)gt->customdata;
	const int winsize_x = WM_window_pixels_x(win);
	const int winsize_y = WM_window_pixels_y(win);

	glEnable(GL_LINE_STIPPLE);
	glColor3ub(96, 96, 96);
	glLineStipple(1, 0xCCCC);
	sdrawline(rect->xmin - winsize_x, rect->ymin, rect->xmin + winsize_x, rect->ymin);
	sdrawline(rect->xmin, rect->ymin - winsize_y, rect->xmin, rect->ymin + winsize_y);
	
	glColor3ub(255, 255, 255);
	glLineStipple(1, 0x3333);
	sdrawline(rect->xmin - winsize_x, rect->ymin, rect->xmin + winsize_x, rect->ymin);
	sdrawline(rect->xmin, rect->ymin - winsize_y, rect->xmin, rect->ymin + winsize_y);
	glDisable(GL_LINE_STIPPLE);
}
Ejemplo n.º 8
0
static void ui_popup_block_clip(wmWindow *window, uiBlock *block)
{
  uiBut *bt;
  const float xmin_orig = block->rect.xmin;
  const int margin = UI_SCREEN_MARGIN;
  int winx, winy;

  if (block->flag & UI_BLOCK_NO_WIN_CLIP) {
    return;
  }

  winx = WM_window_pixels_x(window);
  winy = WM_window_pixels_y(window);

  /* shift to left if outside of view */
  if (block->rect.xmax > winx - margin) {
    const float xofs = winx - margin - block->rect.xmax;
    block->rect.xmin += xofs;
    block->rect.xmax += xofs;
  }
  /* shift menus to right if outside of view */
  if (block->rect.xmin < margin) {
    const float xofs = (margin - block->rect.xmin);
    block->rect.xmin += xofs;
    block->rect.xmax += xofs;
  }

  if (block->rect.ymin < margin) {
    block->rect.ymin = margin;
  }
  if (block->rect.ymax > winy - UI_POPUP_MENU_TOP) {
    block->rect.ymax = winy - UI_POPUP_MENU_TOP;
  }

  /* ensure menu items draw inside left/right boundary */
  const float xofs = block->rect.xmin - xmin_orig;
  for (bt = block->buttons.first; bt; bt = bt->next) {
    bt->rect.xmin += xofs;
    bt->rect.xmax += xofs;
  }
}
Ejemplo n.º 9
0
/* 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;

    x = 0;
    y = 0;
    *dumpsx = WM_window_pixels_x(win);
    *dumpsy = WM_window_pixels_y(win);

    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);
    }

    return dumprect;
}
Ejemplo n.º 10
0
static int wm_triple_gen_textures(wmWindow *win, wmDrawTriple *triple)
{
	const int winsize_x = WM_window_pixels_x(win);
	const int winsize_y = WM_window_pixels_y(win);

	GLint maxsize;
	int x, y;

	/* compute texture sizes */
	if (GLEW_ARB_texture_rectangle || GLEW_NV_texture_rectangle || GLEW_EXT_texture_rectangle) {
		triple->target = GL_TEXTURE_RECTANGLE_ARB;
		triple->nx = 1;
		triple->ny = 1;
		triple->x[0] = winsize_x;
		triple->y[0] = winsize_y;
	}
	else if (GPU_non_power_of_two_support()) {
		triple->target = GL_TEXTURE_2D;
		triple->nx = 1;
		triple->ny = 1;
		triple->x[0] = winsize_x;
		triple->y[0] = winsize_y;
	}
	else {
		triple->target = GL_TEXTURE_2D;
		triple->nx = 0;
		triple->ny = 0;
		split_width(winsize_x, MAX_N_TEX, triple->x, &triple->nx);
		split_width(winsize_y, MAX_N_TEX, triple->y, &triple->ny);
	}

	/* generate texture names */
	glGenTextures(triple->nx * triple->ny, triple->bind);

	if (!triple->bind[0]) {
		/* not the typical failure case but we handle it anyway */
		printf("WM: failed to allocate texture for triple buffer drawing (glGenTextures).\n");
		return 0;
	}

	for (y = 0; y < triple->ny; y++) {
		for (x = 0; x < triple->nx; x++) {
			/* proxy texture is only guaranteed to test for the cases that
			 * there is only one texture in use, which may not be the case */
			maxsize = GPU_max_texture_size();

			if (triple->x[x] > maxsize || triple->y[y] > maxsize) {
				glBindTexture(triple->target, 0);
				printf("WM: failed to allocate texture for triple buffer drawing "
				       "(texture too large for graphics card).\n");
				return 0;
			}

			/* setup actual texture */
			glBindTexture(triple->target, triple->bind[x + y * triple->nx]);
			glTexImage2D(triple->target, 0, GL_RGB8, triple->x[x], triple->y[y], 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
			glTexParameteri(triple->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
			glTexParameteri(triple->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
			/* The current color is ignored if the GL_REPLACE texture environment is used. */
			// glTexEnvi(triple->target, GL_TEXTURE_ENV_MODE, GL_REPLACE);
			glBindTexture(triple->target, 0);

			/* not sure if this works everywhere .. */
			if (glGetError() == GL_OUT_OF_MEMORY) {
				printf("WM: failed to allocate texture for triple buffer drawing (out of memory).\n");
				return 0;
			}
		}
	}

	return 1;
}
Ejemplo n.º 11
0
/* position block relative to but, result is in window space */
static void ui_popup_block_position(wmWindow *window,
                                    ARegion *butregion,
                                    uiBut *but,
                                    uiBlock *block)
{
  uiPopupBlockHandle *handle = block->handle;

  /* Compute button position in window coordinates using the source
   * button region/block, to position the popup attached to it. */
  rctf butrct;

  if (!handle->refresh) {
    ui_block_to_window_rctf(butregion, but->block, &butrct, &but->rect);

    /* widget_roundbox_set has this correction too, keep in sync */
    if (but->type != UI_BTYPE_PULLDOWN) {
      if (but->drawflag & UI_BUT_ALIGN_TOP) {
        butrct.ymax += U.pixelsize;
      }
      if (but->drawflag & UI_BUT_ALIGN_LEFT) {
        butrct.xmin -= U.pixelsize;
      }
    }

    handle->prev_butrct = butrct;
  }
  else {
    /* For refreshes, keep same button position so popup doesn't move. */
    butrct = handle->prev_butrct;
  }

  /* Compute block size in window space, based on buttons contained in it. */
  if (block->rect.xmin == 0.0f && block->rect.xmax == 0.0f) {
    if (block->buttons.first) {
      BLI_rctf_init_minmax(&block->rect);

      for (uiBut *bt = block->buttons.first; bt; bt = bt->next) {
        if (block->content_hints & UI_BLOCK_CONTAINS_SUBMENU_BUT) {
          bt->rect.xmax += UI_MENU_SUBMENU_PADDING;
        }
        BLI_rctf_union(&block->rect, &bt->rect);
      }
    }
    else {
      /* we're nice and allow empty blocks too */
      block->rect.xmin = block->rect.ymin = 0;
      block->rect.xmax = block->rect.ymax = 20;
    }
  }

  ui_block_to_window_rctf(butregion, but->block, &block->rect, &block->rect);

  /* Compute direction relative to button, based on available space. */
  const int size_x = BLI_rctf_size_x(&block->rect) + 0.2f * UI_UNIT_X; /* 4 for shadow */
  const int size_y = BLI_rctf_size_y(&block->rect) + 0.2f * UI_UNIT_Y;
  const int center_x = (block->direction & UI_DIR_CENTER_X) ? size_x / 2 : 0;
  const int center_y = (block->direction & UI_DIR_CENTER_Y) ? size_y / 2 : 0;

  short dir1 = 0, dir2 = 0;

  if (!handle->refresh) {
    bool left = 0, right = 0, top = 0, down = 0;

    const int win_x = WM_window_pixels_x(window);
    const int win_y = WM_window_pixels_y(window);

    /* Take into account maximum size so we don't have to flip on refresh. */
    const float max_size_x = max_ff(size_x, handle->max_size_x);
    const float max_size_y = max_ff(size_y, handle->max_size_y);

    /* check if there's space at all */
    if (butrct.xmin - max_size_x + center_x > 0.0f) {
      left = 1;
    }
    if (butrct.xmax + max_size_x - center_x < win_x) {
      right = 1;
    }
    if (butrct.ymin - max_size_y + center_y > 0.0f) {
      down = 1;
    }
    if (butrct.ymax + max_size_y - center_y < win_y) {
      top = 1;
    }

    if (top == 0 && down == 0) {
      if (butrct.ymin - max_size_y < win_y - butrct.ymax - max_size_y) {
        top = 1;
      }
      else {
        down = 1;
      }
    }

    dir1 = (block->direction & UI_DIR_ALL);

    /* Secondary directions. */
    if (dir1 & (UI_DIR_UP | UI_DIR_DOWN)) {
      if (dir1 & UI_DIR_LEFT) {
        dir2 = UI_DIR_LEFT;
      }
      else if (dir1 & UI_DIR_RIGHT) {
        dir2 = UI_DIR_RIGHT;
      }
      dir1 &= (UI_DIR_UP | UI_DIR_DOWN);
    }

    if ((dir2 == 0) && (dir1 == UI_DIR_LEFT || dir1 == UI_DIR_RIGHT)) {
      dir2 = UI_DIR_DOWN;
    }
    if ((dir2 == 0) && (dir1 == UI_DIR_UP || dir1 == UI_DIR_DOWN)) {
      dir2 = UI_DIR_LEFT;
    }

    /* no space at all? don't change */
    if (left || right) {
      if (dir1 == UI_DIR_LEFT && left == 0) {
        dir1 = UI_DIR_RIGHT;
      }
      if (dir1 == UI_DIR_RIGHT && right == 0) {
        dir1 = UI_DIR_LEFT;
      }
      /* this is aligning, not append! */
      if (dir2 == UI_DIR_LEFT && right == 0) {
        dir2 = UI_DIR_RIGHT;
      }
      if (dir2 == UI_DIR_RIGHT && left == 0) {
        dir2 = UI_DIR_LEFT;
      }
    }
    if (down || top) {
      if (dir1 == UI_DIR_UP && top == 0) {
        dir1 = UI_DIR_DOWN;
      }
      if (dir1 == UI_DIR_DOWN && down == 0) {
        dir1 = UI_DIR_UP;
      }
      BLI_assert(dir2 != UI_DIR_UP);
      //          if (dir2 == UI_DIR_UP   && top == 0)  { dir2 = UI_DIR_DOWN; }
      if (dir2 == UI_DIR_DOWN && down == 0) {
        dir2 = UI_DIR_UP;
      }
    }

    handle->prev_dir1 = dir1;
    handle->prev_dir2 = dir2;
  }
  else {
    /* For refreshes, keep same popup direct so popup doesn't move
     * to a totally different position while editing in it. */
    dir1 = handle->prev_dir1;
    dir2 = handle->prev_dir2;
  }

  /* Compute offset based on direction. */
  float offset_x = 0, offset_y = 0;

  /* Ensure buttons don't come between the parent button and the popup, see: T63566. */
  const float offset_overlap = max_ff(U.pixelsize, 1.0f);

  if (dir1 == UI_DIR_LEFT) {
    offset_x = (butrct.xmin - block->rect.xmax) + offset_overlap;
    if (dir2 == UI_DIR_UP) {
      offset_y = butrct.ymin - block->rect.ymin - center_y - UI_MENU_PADDING;
    }
    else {
      offset_y = butrct.ymax - block->rect.ymax + center_y + UI_MENU_PADDING;
    }
  }
  else if (dir1 == UI_DIR_RIGHT) {
    offset_x = (butrct.xmax - block->rect.xmin) - offset_overlap;
    if (dir2 == UI_DIR_UP) {
      offset_y = butrct.ymin - block->rect.ymin - center_y - UI_MENU_PADDING;
    }
    else {
      offset_y = butrct.ymax - block->rect.ymax + center_y + UI_MENU_PADDING;
    }
  }
  else if (dir1 == UI_DIR_UP) {
    offset_y = (butrct.ymax - block->rect.ymin) - offset_overlap;
    if (dir2 == UI_DIR_RIGHT) {
      offset_x = butrct.xmax - block->rect.xmax + center_x;
    }
    else {
      offset_x = butrct.xmin - block->rect.xmin - center_x;
    }
    /* changed direction? */
    if ((dir1 & block->direction) == 0) {
      /* TODO: still do */
      UI_block_order_flip(block);
    }
  }
  else if (dir1 == UI_DIR_DOWN) {
    offset_y = (butrct.ymin - block->rect.ymax) + offset_overlap;
    if (dir2 == UI_DIR_RIGHT) {
      offset_x = butrct.xmax - block->rect.xmax + center_x;
    }
    else {
      offset_x = butrct.xmin - block->rect.xmin - center_x;
    }
    /* changed direction? */
    if ((dir1 & block->direction) == 0) {
      /* TODO: still do */
      UI_block_order_flip(block);
    }
  }

  /* Center over popovers for eg. */
  if (block->direction & UI_DIR_CENTER_X) {
    offset_x += BLI_rctf_size_x(&butrct) / ((dir2 == UI_DIR_LEFT) ? 2 : -2);
  }

  /* Apply offset, buttons in window coords. */
  for (uiBut *bt = block->buttons.first; bt; bt = bt->next) {
    ui_block_to_window_rctf(butregion, but->block, &bt->rect, &bt->rect);

    BLI_rctf_translate(&bt->rect, offset_x, offset_y);

    /* ui_but_update recalculates drawstring size in pixels */
    ui_but_update(bt);
  }

  BLI_rctf_translate(&block->rect, offset_x, offset_y);

  /* Safety calculus. */
  {
    const float midx = BLI_rctf_cent_x(&butrct);
    const float midy = BLI_rctf_cent_y(&butrct);

    /* when you are outside parent button, safety there should be smaller */

    /* parent button to left */
    if (midx < block->rect.xmin) {
      block->safety.xmin = block->rect.xmin - 3;
    }
    else {
      block->safety.xmin = block->rect.xmin - 40;
    }
    /* parent button to right */
    if (midx > block->rect.xmax) {
      block->safety.xmax = block->rect.xmax + 3;
    }
    else {
      block->safety.xmax = block->rect.xmax + 40;
    }

    /* parent button on bottom */
    if (midy < block->rect.ymin) {
      block->safety.ymin = block->rect.ymin - 3;
    }
    else {
      block->safety.ymin = block->rect.ymin - 40;
    }
    /* parent button on top */
    if (midy > block->rect.ymax) {
      block->safety.ymax = block->rect.ymax + 3;
    }
    else {
      block->safety.ymax = block->rect.ymax + 40;
    }

    /* exception for switched pulldowns... */
    if (dir1 && (dir1 & block->direction) == 0) {
      if (dir2 == UI_DIR_RIGHT) {
        block->safety.xmax = block->rect.xmax + 3;
      }
      if (dir2 == UI_DIR_LEFT) {
        block->safety.xmin = block->rect.xmin - 3;
      }
    }
    block->direction = dir1;
  }

  /* keep a list of these, needed for pulldown menus */
  uiSafetyRct *saferct = MEM_callocN(sizeof(uiSafetyRct), "uiSafetyRct");
  saferct->parent = butrct;
  saferct->safety = block->safety;
  BLI_freelistN(&block->saferct);
  BLI_duplicatelist(&block->saferct, &but->block->saferct);
  BLI_addhead(&block->saferct, saferct);
}
Ejemplo n.º 12
0
/**
 * Called for creating new popups and refreshing existing ones.
 */
uiBlock *ui_popup_block_refresh(bContext *C,
                                uiPopupBlockHandle *handle,
                                ARegion *butregion,
                                uiBut *but)
{
  const int margin = UI_POPUP_MARGIN;
  wmWindow *window = CTX_wm_window(C);
  ARegion *ar = handle->region;

  uiBlockCreateFunc create_func = handle->popup_create_vars.create_func;
  uiBlockHandleCreateFunc handle_create_func = handle->popup_create_vars.handle_create_func;
  void *arg = handle->popup_create_vars.arg;

  uiBlock *block_old = ar->uiblocks.first;
  uiBlock *block;

  handle->refresh = (block_old != NULL);

  BLI_assert(!handle->refresh || handle->can_refresh);

#ifdef DEBUG
  wmEvent *event_back = window->eventstate;
#endif

  /* create ui block */
  if (create_func) {
    block = create_func(C, ar, arg);
  }
  else {
    block = handle_create_func(C, handle, arg);
  }

  /* callbacks _must_ leave this for us, otherwise we can't call UI_block_update_from_old */
  BLI_assert(!block->endblock);

  /* ensure we don't use mouse coords here! */
#ifdef DEBUG
  window->eventstate = NULL;
#endif

  if (block->handle) {
    memcpy(block->handle, handle, sizeof(uiPopupBlockHandle));
    MEM_freeN(handle);
    handle = block->handle;
  }
  else {
    block->handle = handle;
  }

  ar->regiondata = handle;

  /* set UI_BLOCK_NUMSELECT before UI_block_end() so we get alphanumeric keys assigned */
  if (but == NULL) {
    block->flag |= UI_BLOCK_POPUP;
  }

  block->flag |= UI_BLOCK_LOOP;
  UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);

  /* defer this until blocks are translated (below) */
  block->oldblock = NULL;

  if (!block->endblock) {
    UI_block_end_ex(
        C, block, handle->popup_create_vars.event_xy, handle->popup_create_vars.event_xy);
  }

  /* if this is being created from a button */
  if (but) {
    block->aspect = but->block->aspect;
    ui_popup_block_position(window, butregion, but, block);
    handle->direction = block->direction;
  }
  else {
    uiSafetyRct *saferct;
    /* keep a list of these, needed for pulldown menus */
    saferct = MEM_callocN(sizeof(uiSafetyRct), "uiSafetyRct");
    saferct->safety = block->safety;
    BLI_addhead(&block->saferct, saferct);
  }

  if (block->flag & UI_BLOCK_RADIAL) {
    int win_width = UI_SCREEN_MARGIN;
    int winx, winy;

    int x_offset = 0, y_offset = 0;

    winx = WM_window_pixels_x(window);
    winy = WM_window_pixels_y(window);

    copy_v2_v2(block->pie_data.pie_center_init, block->pie_data.pie_center_spawned);

    /* only try translation if area is large enough */
    if (BLI_rctf_size_x(&block->rect) < winx - (2.0f * win_width)) {
      if (block->rect.xmin < win_width) {
        x_offset += win_width - block->rect.xmin;
      }
      if (block->rect.xmax > winx - win_width) {
        x_offset += winx - win_width - block->rect.xmax;
      }
    }

    if (BLI_rctf_size_y(&block->rect) < winy - (2.0f * win_width)) {
      if (block->rect.ymin < win_width) {
        y_offset += win_width - block->rect.ymin;
      }
      if (block->rect.ymax > winy - win_width) {
        y_offset += winy - win_width - block->rect.ymax;
      }
    }
    /* if we are offsetting set up initial data for timeout functionality */

    if ((x_offset != 0) || (y_offset != 0)) {
      block->pie_data.pie_center_spawned[0] += x_offset;
      block->pie_data.pie_center_spawned[1] += y_offset;

      UI_block_translate(block, x_offset, y_offset);

      if (U.pie_initial_timeout > 0) {
        block->pie_data.flags |= UI_PIE_INITIAL_DIRECTION;
      }
    }

    ar->winrct.xmin = 0;
    ar->winrct.xmax = winx;
    ar->winrct.ymin = 0;
    ar->winrct.ymax = winy;

    ui_block_calc_pie_segment(block, block->pie_data.pie_center_init);

    /* lastly set the buttons at the center of the pie menu, ready for animation */
    if (U.pie_animation_timeout > 0) {
      for (uiBut *but_iter = block->buttons.first; but_iter; but_iter = but_iter->next) {
        if (but_iter->pie_dir != UI_RADIAL_NONE) {
          BLI_rctf_recenter(&but_iter->rect, UNPACK2(block->pie_data.pie_center_spawned));
        }
      }
    }
  }
  else {
    /* clip block with window boundary */
    ui_popup_block_clip(window, block);

    /* Avoid menu moving down and losing cursor focus by keeping it at
     * the same height. */
    if (handle->refresh && handle->prev_block_rect.ymax > block->rect.ymax) {
      float offset = handle->prev_block_rect.ymax - block->rect.ymax;
      UI_block_translate(block, 0, offset);
      block->rect.ymin = handle->prev_block_rect.ymin;
    }

    handle->prev_block_rect = block->rect;

    /* the block and buttons were positioned in window space as in 2.4x, now
     * these menu blocks are regions so we bring it back to region space.
     * additionally we add some padding for the menu shadow or rounded menus */
    ar->winrct.xmin = block->rect.xmin - margin;
    ar->winrct.xmax = block->rect.xmax + margin;
    ar->winrct.ymin = block->rect.ymin - margin;
    ar->winrct.ymax = block->rect.ymax + UI_POPUP_MENU_TOP;

    UI_block_translate(block, -ar->winrct.xmin, -ar->winrct.ymin);

    /* apply scroll offset */
    if (handle->scrolloffset != 0.0f) {
      for (uiBut *bt = block->buttons.first; bt; bt = bt->next) {
        bt->rect.ymin += handle->scrolloffset;
        bt->rect.ymax += handle->scrolloffset;
      }
    }
  }

  if (block_old) {
    block->oldblock = block_old;
    UI_block_update_from_old(C, block);
    UI_blocklist_free_inactive(C, &ar->uiblocks);
  }

  /* checks which buttons are visible, sets flags to prevent draw (do after region init) */
  ui_popup_block_scrolltest(block);

  /* adds subwindow */
  ED_region_init(ar);

  /* get winmat now that we actually have the subwindow */
  wmGetProjectionMatrix(block->winmat, &ar->winrct);

  /* notify change and redraw */
  ED_region_tag_redraw(ar);

  ED_region_update_rect(ar);

#ifdef DEBUG
  window->eventstate = event_back;
#endif

  return block;
}
Ejemplo n.º 13
0
/* if rect set, do not draw */
void wm_drags_draw(bContext *C, wmWindow *win, rcti *rect)
{
	wmWindowManager *wm = CTX_wm_manager(C);
	wmDrag *drag;
	const int winsize_y = WM_window_pixels_y(win);
	int cursorx, cursory, x, y;
	
	cursorx = win->eventstate->x;
	cursory = win->eventstate->y;
	if (rect) {
		rect->xmin = rect->xmax = cursorx;
		rect->ymin = rect->ymax = cursory;
	}
	
	/* XXX todo, multiline drag draws... but maybe not, more types mixed wont work well */
	glEnable(GL_BLEND);
	for (drag = wm->drags.first; drag; drag = drag->next) {
		int iconsize = 16 * UI_DPI_FAC; /* assumed to be 16 pixels */
		int padding = 4 * UI_DPI_FAC;
		
		/* image or icon */
		if (drag->imb) {
			x = cursorx - drag->sx / 2;
			y = cursory - drag->sy / 2;
			
			if (rect)
				drag_rect_minmax(rect, x, y, x + drag->sx, y + drag->sy);
			else {
				glColor4f(1.0, 1.0, 1.0, 0.65); /* this blends texture */
				glaDrawPixelsTexScaled(x, y, drag->imb->x, drag->imb->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, drag->imb->rect, drag->scale, drag->scale);
			}
		}
		else {
			x = cursorx - 2 * padding;
			y = cursory - 2 * UI_DPI_FAC;
			
			if (rect)
				drag_rect_minmax(rect, x, y, x + iconsize, y + iconsize);
			else
				UI_icon_draw_aspect(x, y, drag->icon, 1.0f / UI_DPI_FAC, 0.8);
		}
		
		/* item name */
		if (drag->imb) {
			x = cursorx - drag->sx / 2;
			y = cursory - drag->sy / 2 - iconsize;
		}
		else {
			x = cursorx + 10 * UI_DPI_FAC;
			y = cursory + 1 * UI_DPI_FAC;
		}
		
		if (rect) {
			int w =  UI_fontstyle_string_width(wm_drag_name(drag));
			drag_rect_minmax(rect, x, y, x + w, y + iconsize);
		}
		else {
			glColor4ub(255, 255, 255, 255);
			UI_draw_string(x, y, wm_drag_name(drag));
		}
		
		/* operator name with roundbox */
		if (drag->opname[0]) {
			if (drag->imb) {
				x = cursorx - drag->sx / 2;

				if (cursory + drag->sy / 2 + padding + iconsize < winsize_y)
					y = cursory + drag->sy / 2 + padding;
				else
					y = cursory - drag->sy / 2 - padding - iconsize - padding - iconsize;
			}
			else {
				x = cursorx - 2 * padding;

				if (cursory + iconsize + iconsize < winsize_y)
					y = cursory + iconsize;
				else
					y = cursory - iconsize - 2 * UI_DPI_FAC;
			}
			
			if (rect) {
				int w =  UI_fontstyle_string_width(wm_drag_name(drag));
				drag_rect_minmax(rect, x, y, x + w, y + iconsize);
			}
			else 
				wm_drop_operator_draw(drag->opname, x, y);
			
		}
	}
	glDisable(GL_BLEND);
}