Compositor: add new node: Kuwahara filter #107015

Merged
Habib Gahbiche merged 22 commits from zazizizou/blender:com-kuwahara-filter-node into main 2023-06-08 16:14:51 +02:00
55 changed files with 484 additions and 297 deletions
Showing only changes of commit 9f6ef78206 - Show all commits

View File

@ -98,6 +98,14 @@ typedef enum {
* This is a convention for X11/WAYLAND, select text & MMB to paste (without an explicit copy).
*/
GHOST_kCapabilityPrimaryClipboard = (1 << 2),
/**
* Support for reading the front-buffer.
*/
GHOST_kCapabilityGPUReadFrontBuffer = (1 << 3),
/**
* Set when there is support for system clipboard copy/paste.
*/
GHOST_kCapabilityClipboardImages = (1 << 4),
} GHOST_TCapabilityFlag;
/**
@ -106,7 +114,7 @@ typedef enum {
*/
#define GHOST_CAPABILITY_FLAG_ALL \
(GHOST_kCapabilityCursorWarp | GHOST_kCapabilityWindowPosition | \
GHOST_kCapabilityPrimaryClipboard)
GHOST_kCapabilityPrimaryClipboard | GHOST_kCapabilityGPUReadFrontBuffer)
/* Xtilt and Ytilt represent how much the pen is tilted away from
* vertically upright in either the X or Y direction, with X and Y the

View File

@ -903,7 +903,9 @@ GHOST_TCapabilityFlag GHOST_SystemCocoa::getCapabilities() const
return GHOST_TCapabilityFlag(GHOST_CAPABILITY_FLAG_ALL &
~(
/* Cocoa has no support for a primary selection clipboard. */
GHOST_kCapabilityPrimaryClipboard));
GHOST_kCapabilityPrimaryClipboard |
/* This Cocoa back-end has not yet implemented image copy/paste. */
GHOST_kCapabilityClipboardImages));
}
#pragma mark Event handlers

View File

@ -47,7 +47,8 @@ class GHOST_SystemHeadless : public GHOST_System {
return GHOST_TCapabilityFlag(GHOST_CAPABILITY_FLAG_ALL &
/* No windowing functionality supported. */
~(GHOST_kCapabilityWindowPosition | GHOST_kCapabilityCursorWarp |
GHOST_kCapabilityPrimaryClipboard));
GHOST_kCapabilityPrimaryClipboard |
GHOST_kCapabilityClipboardImages));
}
char *getClipboard(bool /*selection*/) const override
{

View File

@ -757,7 +757,9 @@ GHOST_TCapabilityFlag GHOST_SystemSDL::getCapabilities() const
GHOST_CAPABILITY_FLAG_ALL &
~(
/* This SDL back-end has not yet implemented primary clipboard. */
GHOST_kCapabilityPrimaryClipboard));
GHOST_kCapabilityPrimaryClipboard |
/* This SDL back-end has not yet implemented image copy/paste. */
GHOST_kCapabilityClipboardImages));
}
char *GHOST_SystemSDL::getClipboard(bool /*selection*/) const

View File

@ -6762,7 +6762,12 @@ GHOST_TCapabilityFlag GHOST_SystemWayland::getCapabilities() const
GHOST_kCapabilityWindowPosition |
/* WAYLAND doesn't support setting the cursor position directly,
* this is an intentional choice, forcing us to use a software cursor in this case. */
GHOST_kCapabilityCursorWarp));
GHOST_kCapabilityCursorWarp |
/* Some drivers don't support front-buffer reading, see: #98462 & #106264.
* We could inspect the graphics card driver - for now just disable on WAYLAND. */
GHOST_kCapabilityGPUReadFrontBuffer |
/* This WAYLAND back-end has not yet implemented image copy/paste. */
GHOST_kCapabilityClipboardImages));
}
bool GHOST_SystemWayland::cursor_grab_use_software_display_get(const GHOST_TGrabCursorMode mode)

View File

@ -1742,7 +1742,10 @@ GHOST_TSuccess GHOST_SystemX11::setCursorPosition(int32_t x, int32_t y)
GHOST_TCapabilityFlag GHOST_SystemX11::getCapabilities() const
{
return GHOST_TCapabilityFlag(GHOST_CAPABILITY_FLAG_ALL);
return GHOST_TCapabilityFlag(GHOST_CAPABILITY_FLAG_ALL &
~(
/* No support yet for image copy/paste. */
GHOST_kCapabilityClipboardImages));
}
void GHOST_SystemX11::addDirtyWindow(GHOST_WindowX11 *bad_wind)

View File

@ -16,7 +16,7 @@ def batch_for_shader(shader, type, content, *, indices=None):
:arg content: Maps the name of the shader attribute with the data to fill the vertex buffer.
:type content: dict
:return: compatible batch
:rtype: :class:`gpu.types.Batch`
:rtype: :class:`gpu.types.GPUBatch`
"""
from gpu.types import (
GPUBatch,

View File

@ -33,7 +33,7 @@ enum {
ICON_DATA_PREVIEW,
/** 2D triangles: obj is #Icon_Geom */
ICON_DATA_GEOM,
/** Studiolight */
/** Studio-light. */
ICON_DATA_STUDIOLIGHT,
/** GPencil Layer color preview (annotations): obj is #bGPDlayer */
ICON_DATA_GPLAYER,

View File

@ -245,7 +245,7 @@ void BKE_subdiv_ccg_update_normals(SubdivCCG *subdiv_ccg,
struct CCGFace **effected_faces,
int num_effected_faces);
/* Average grid coordinates and normals along the grid boundatries. */
/* Average grid coordinates and normals along the grid boundaries. */
void BKE_subdiv_ccg_average_grids(SubdivCCG *subdiv_ccg);
/* Similar to above, but only updates given faces. */

View File

@ -592,8 +592,8 @@ bGPDframe *BKE_gpencil_frame_addcopy(bGPDlayer *gpl, int cframe)
break;
}
if (gpf->framenum == cframe) {
/* This only happens when we're editing with framelock on...
* - Delete the new frame and don't do anything else here...
/* This only happens when we're editing with frame-lock on.
* - Delete the new frame and don't do anything else here.
*/
BKE_gpencil_free_strokes(new_frame);
MEM_freeN(new_frame);

View File

@ -1404,9 +1404,24 @@ void nodeUnregisterType(bNodeType *nt)
bool nodeTypeUndefined(const bNode *node)
{
return (node->typeinfo == &NodeTypeUndefined) ||
(ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP) && node->id && ID_IS_LINKED(node->id) &&
(node->id->tag & LIB_TAG_MISSING));
if (node->typeinfo == &NodeTypeUndefined) {
return true;
}
if (node->is_group()) {
const ID *group_tree = node->id;
if (group_tree == nullptr) {
return false;
}
if (!ID_IS_LINKED(group_tree)) {
return false;
}
if ((group_tree->tag & LIB_TAG_MISSING) == 0) {
return false;
}
return true;
}
return false;
}
GHashIterator *nodeTypeGetIterator()
@ -1464,7 +1479,10 @@ GHashIterator *nodeSocketTypeGetIterator()
const char *nodeSocketTypeLabel(const bNodeSocketType *stype)
{
/* Use socket type name as a fallback if label is undefined. */
return stype->label[0] != '\0' ? stype->label : RNA_struct_ui_name(stype->ext_socket.srna);
if (stype->label[0] == '\0') {
return RNA_struct_ui_name(stype->ext_socket.srna);
}
return stype->label;
}
const char *nodeSocketSubTypeLabel(int subtype)
@ -2132,18 +2150,23 @@ void nodeChainIter(const bNodeTree *ntree,
/* Skip links marked as cyclic. */
continue;
}
if (link->tonode && link->fromnode) {
/* Is the link part of the chain meaning node_start == fromnode
* (or tonode for reversed case)? */
if ((reversed && (link->tonode == node_start)) ||
(!reversed && link->fromnode == node_start)) {
if (!callback(link->fromnode, link->tonode, userdata, reversed)) {
return;
}
nodeChainIter(
ntree, reversed ? link->fromnode : link->tonode, callback, userdata, reversed);
/* Is the link part of the chain meaning node_start == fromnode
* (or tonode for reversed case)? */
if (!reversed) {
if (link->fromnode != node_start) {
continue;
}
}
else {
if (link->tonode != node_start) {
continue;
}
}
if (!callback(link->fromnode, link->tonode, userdata, reversed)) {
return;
}
nodeChainIter(ntree, reversed ? link->fromnode : link->tonode, callback, userdata, reversed);
}
}
@ -2289,8 +2312,12 @@ bNode *nodeAddStaticNode(const bContext *C, bNodeTree *ntree, const int type)
NODE_TYPES_BEGIN (ntype) {
/* Do an extra poll here, because some int types are used
* for multiple node types, this helps find the desired type. */
if (ntype->type != type) {
continue;
}
const char *disabled_hint;
if (ntype->type == type && (!ntype->poll || ntype->poll(ntype, ntree, &disabled_hint))) {
if (ntype->poll && ntype->poll(ntype, ntree, &disabled_hint)) {
idname = ntype->idname;
break;
}
@ -2635,55 +2662,49 @@ void nodeInternalRelink(bNodeTree *ntree, bNode *node)
/* redirect downstream links */
LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) {
/* do we have internal link? */
if (link->fromnode == node) {
if (link->fromsock->link) {
/* get the upstream input link */
bNodeLink *fromlink = link->fromsock->link->fromsock->link;
/* skip the node */
if (fromlink) {
if (link->tosock->flag & SOCK_MULTI_INPUT) {
/* remove the link that would be the same as the relinked one */
LISTBASE_FOREACH_MUTABLE (bNodeLink *, link_to_compare, &ntree->links) {
if (link_to_compare->fromsock == fromlink->fromsock &&
link_to_compare->tosock == link->tosock) {
adjust_multi_input_indices_after_removed_link(
ntree, link_to_compare->tosock, link_to_compare->multi_input_socket_index);
duplicate_links_to_remove.append_non_duplicates(link_to_compare);
}
}
}
link->fromnode = fromlink->fromnode;
link->fromsock = fromlink->fromsock;
if (link->fromnode != node) {
continue;
}
/* if the up- or downstream link is invalid,
* the replacement link will be invalid too.
*/
if (!(fromlink->flag & NODE_LINK_VALID)) {
link->flag &= ~NODE_LINK_VALID;
}
bNodeLink *internal_link = link->fromsock->link;
bNodeLink *fromlink = internal_link ? internal_link->fromsock->link : nullptr;
if (fromlink->flag & NODE_LINK_MUTED) {
link->flag |= NODE_LINK_MUTED;
}
BKE_ntree_update_tag_link_changed(ntree);
}
else {
if (link->tosock->flag & SOCK_MULTI_INPUT) {
adjust_multi_input_indices_after_removed_link(
ntree, link->tosock, link->multi_input_socket_index);
}
nodeRemLink(ntree, link);
}
if (fromlink == nullptr) {
if (link->tosock->flag & SOCK_MULTI_INPUT) {
adjust_multi_input_indices_after_removed_link(
ntree, link->tosock, link->multi_input_socket_index);
}
else {
if (link->tosock->flag & SOCK_MULTI_INPUT) {
nodeRemLink(ntree, link);
continue;
}
if (link->tosock->flag & SOCK_MULTI_INPUT) {
/* remove the link that would be the same as the relinked one */
LISTBASE_FOREACH_MUTABLE (bNodeLink *, link_to_compare, &ntree->links) {
if (link_to_compare->fromsock == fromlink->fromsock &&
link_to_compare->tosock == link->tosock) {
adjust_multi_input_indices_after_removed_link(
ntree, link->tosock, link->multi_input_socket_index);
};
nodeRemLink(ntree, link);
ntree, link_to_compare->tosock, link_to_compare->multi_input_socket_index);
duplicate_links_to_remove.append_non_duplicates(link_to_compare);
}
}
}
link->fromnode = fromlink->fromnode;
link->fromsock = fromlink->fromsock;
/* if the up- or downstream link is invalid,
* the replacement link will be invalid too.
*/
if (!(fromlink->flag & NODE_LINK_VALID)) {
link->flag &= ~NODE_LINK_VALID;
}
if (fromlink->flag & NODE_LINK_MUTED) {
link->flag |= NODE_LINK_MUTED;
}
BKE_ntree_update_tag_link_changed(ntree);
}
for (bNodeLink *link : duplicate_links_to_remove) {
@ -3292,6 +3313,7 @@ void ntreeFreeLocalTree(bNodeTree *ntree)
void ntreeSetOutput(bNodeTree *ntree)
{
const bool is_compositor = ntree->type == NTREE_COMPOSIT;
/* find the active outputs, might become tree type dependent handler */
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
if (node->typeinfo->nclass == NODE_CLASS_OUTPUT) {
@ -3299,37 +3321,29 @@ void ntreeSetOutput(bNodeTree *ntree)
if (ELEM(node->type, CMP_NODE_OUTPUT_FILE, GEO_NODE_VIEWER)) {
continue;
}
const bool node_is_output = ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER);
int output = 0;
/* there is more types having output class, each one is checked */
LISTBASE_FOREACH (bNode *, tnode, &ntree->nodes) {
if (tnode->typeinfo->nclass == NODE_CLASS_OUTPUT) {
if (ntree->type == NTREE_COMPOSIT) {
/* same type, exception for viewer */
if (tnode->type == node->type ||
(ELEM(tnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER) &&
ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))) {
if (tnode->flag & NODE_DO_OUTPUT) {
output++;
if (output > 1) {
tnode->flag &= ~NODE_DO_OUTPUT;
}
}
}
}
else {
/* same type */
if (tnode->type == node->type) {
if (tnode->flag & NODE_DO_OUTPUT) {
output++;
if (output > 1) {
tnode->flag &= ~NODE_DO_OUTPUT;
}
}
if (tnode->typeinfo->nclass != NODE_CLASS_OUTPUT) {
continue;
}
/* same type, exception for viewer */
const bool tnode_is_output = ELEM(tnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER);
const bool compositor_case = is_compositor && tnode_is_output && node_is_output;
if (tnode->type == node->type || compositor_case) {
if (tnode->flag & NODE_DO_OUTPUT) {
output++;
if (output > 1) {
tnode->flag &= ~NODE_DO_OUTPUT;
}
}
}
}
if (output == 0) {
node->flag |= NODE_DO_OUTPUT;
}
@ -3339,12 +3353,13 @@ void ntreeSetOutput(bNodeTree *ntree)
if (node->type == NODE_GROUP_OUTPUT) {
int output = 0;
LISTBASE_FOREACH (bNode *, tnode, &ntree->nodes) {
if (tnode->type == NODE_GROUP_OUTPUT) {
if (tnode->flag & NODE_DO_OUTPUT) {
output++;
if (output > 1) {
tnode->flag &= ~NODE_DO_OUTPUT;
}
if (tnode->type != NODE_GROUP_OUTPUT) {
continue;
}
if (tnode->flag & NODE_DO_OUTPUT) {
output++;
if (output > 1) {
tnode->flag &= ~NODE_DO_OUTPUT;
}
}
}
@ -3547,10 +3562,11 @@ bNodeSocket *ntreeAddSocketInterfaceFromSocketWithName(bNodeTree *ntree,
{
bNodeSocket *iosock = ntreeAddSocketInterface(
ntree, static_cast<eNodeSocketInOut>(from_sock->in_out), idname, DATA_(name));
if (iosock) {
if (iosock->typeinfo->interface_from_socket) {
iosock->typeinfo->interface_from_socket(ntree, iosock, from_node, from_sock);
}
if (iosock == nullptr) {
return nullptr;
}
if (iosock->typeinfo->interface_from_socket) {
iosock->typeinfo->interface_from_socket(ntree, iosock, from_node, from_sock);
}
return iosock;
}
@ -3677,17 +3693,15 @@ void nodeSetSelected(bNode *node, const bool select)
{
if (select) {
node->flag |= NODE_SELECT;
return;
}
else {
node->flag &= ~NODE_SELECT;
/* deselect sockets too */
LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
sock->flag &= ~NODE_SELECT;
}
LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
sock->flag &= ~NODE_SELECT;
}
node->flag &= ~NODE_SELECT;
/* deselect sockets too */
LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
sock->flag &= ~NODE_SELECT;
}
LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
sock->flag &= ~NODE_SELECT;
}
}
@ -3734,17 +3748,17 @@ void nodeSetSocketAvailability(bNodeTree *ntree, bNodeSocket *sock, const bool i
int nodeSocketLinkLimit(const bNodeSocket *sock)
{
const bNodeSocketType *stype = sock->typeinfo;
if (sock->flag & SOCK_MULTI_INPUT) {
return 4095;
}
if (stype != nullptr && stype->use_link_limits_of_type) {
const int limit = (sock->in_out == SOCK_IN) ? stype->input_link_limit :
stype->output_link_limit;
return limit;
if (sock->typeinfo == nullptr) {
return sock->limit;
}
return sock->limit;
const bNodeSocketType &stype = *sock->typeinfo;
if (!stype.use_link_limits_of_type) {
return sock->limit;
}
return sock->in_out == SOCK_IN ? stype.input_link_limit : stype.output_link_limit;
}
static void update_socket_declarations(ListBase *sockets,
@ -3770,11 +3784,10 @@ void nodeSocketDeclarationsUpdate(bNode *node)
if (node->runtime->declaration->skip_updating_sockets) {
reset_socket_declarations(&node->inputs);
reset_socket_declarations(&node->outputs);
return;
}
else {
update_socket_declarations(&node->inputs, node->runtime->declaration->inputs);
update_socket_declarations(&node->outputs, node->runtime->declaration->outputs);
}
update_socket_declarations(&node->inputs, node->runtime->declaration->inputs);
update_socket_declarations(&node->outputs, node->runtime->declaration->outputs);
}
bool nodeDeclarationEnsureOnOutdatedNode(bNodeTree *ntree, bNode *node)
@ -4034,16 +4047,17 @@ void nodeLabel(const bNodeTree *ntree, const bNode *node, char *label, const int
else if (node->typeinfo->labelfunc) {
node->typeinfo->labelfunc(ntree, node, label, maxlen);
}
/* The previous methods (labelfunc) could not provide an adequate label for the node. */
if (label[0] == '\0') {
/* Kind of hacky and weak... Ideally would be better to use RNA here. :| */
const char *tmp = CTX_IFACE_(BLT_I18NCONTEXT_ID_NODETREE, node->typeinfo->ui_name);
if (tmp == node->typeinfo->ui_name) {
tmp = IFACE_(node->typeinfo->ui_name);
}
BLI_strncpy(label, tmp, maxlen);
if (label[0] != '\0') {
/* The previous methods (labelfunc) could not provide an adequate label for the node. */
return;
}
/* Kind of hacky and weak... Ideally would be better to use RNA here. :| */
const char *tmp = CTX_IFACE_(BLT_I18NCONTEXT_ID_NODETREE, node->typeinfo->ui_name);
if (tmp == node->typeinfo->ui_name) {
tmp = IFACE_(node->typeinfo->ui_name);
}
BLI_strncpy(label, tmp, maxlen);
}
const char *nodeSocketLabel(const bNodeSocket *sock)

View File

@ -602,7 +602,7 @@ static void annotation_draw_onionskins(
for (gf = gpf->prev; gf; gf = gf->prev) {
/* check if frame is drawable */
if ((gpf->framenum - gf->framenum) <= gpl->gstep) {
/* alpha decreases with distance from curframe index */
/* Alpha decreases with distance from current-frame index. */
fac = 1.0f - ((float)(gpf->framenum - gf->framenum) / (float)(gpl->gstep + 1));
color[3] = alpha * fac * 0.66f;
annotation_draw_strokes(gf, offsx, offsy, winx, winy, dflag, gpl->thickness, color);
@ -634,7 +634,7 @@ static void annotation_draw_onionskins(
for (gf = gpf->next; gf; gf = gf->next) {
/* check if frame is drawable */
if ((gf->framenum - gpf->framenum) <= gpl->gstep_next) {
/* alpha decreases with distance from curframe index */
/* Alpha decreases with distance from current-frame index. */
fac = 1.0f - ((float)(gf->framenum - gpf->framenum) / (float)(gpl->gstep_next + 1));
color[3] = alpha * fac * 0.66f;
annotation_draw_strokes(gf, offsx, offsy, winx, winy, dflag, gpl->thickness, color);

View File

@ -291,7 +291,7 @@ static bool annotation_stroke_filtermval(tGPsdata *p, const float mval[2], const
/* Check if the distance since the last point is significant enough:
* - Prevents points being added too densely
* - Distance here doesn't use sqrt to prevent slowness.
* - Distance here doesn't use `sqrt` to prevent slowness.
* We should still be safe from overflows though.
*/
if ((dx * dx + dy * dy) > MIN_EUCLIDEAN_PX * MIN_EUCLIDEAN_PX) {
@ -2457,7 +2457,7 @@ static int annotation_draw_modal(bContext *C, wmOperator *op, const wmEvent *eve
}
/* We don't pass on key events, GP is used with key-modifiers -
* prevents Dkey to insert drivers. */
* prevents D-key to insert drivers. */
if (ISKEYBOARD(event->type)) {
if (ELEM(event->type,
EVT_LEFTARROWKEY,

View File

@ -188,7 +188,7 @@ static void gpencil_draw_stroke_3d(tGPDdraw *tgpw,
int keep_size = (int)((tgpw->gpd) && (tgpw->gpd->flag & GP_DATA_STROKE_KEEPTHICKNESS));
gpencil_stroke_data.keep_size = keep_size;
gpencil_stroke_data.pixfactor = tgpw->gpd->pixfactor;
/* xray mode always to 3D space to avoid wrong zdepth calculation (#60051) */
/* X-ray mode always to 3D space to avoid wrong Z-depth calculation (#60051). */
gpencil_stroke_data.xraymode = GP_XRAY_3DSPACE;
gpencil_stroke_data.caps_start = tgpw->gps->caps[0];
gpencil_stroke_data.caps_end = tgpw->gps->caps[1];

View File

@ -2754,7 +2754,7 @@ void GPENCIL_OT_vertex_group_normalize_all(wmOperatorType *ot)
/****************************** Join ***********************************/
/* userdata for joined_gpencil_fix_animdata_cb() */
/** User-data for #gpencil_joined_fix_animdata_cb(). */
typedef struct tJoinGPencil_AdtFixData {
bGPdata *src_gpd;
bGPdata *tar_gpd;

View File

@ -193,7 +193,7 @@ static int gpencil_editmode_toggle_exec(bContext *C, wmOperator *op)
ob->mode = mode;
}
/* Recalculate editcurves for strokes where the geometry/vertex colors have changed */
/* Recalculate edit-curves for strokes where the geometry/vertex colors have changed. */
if (GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd)) {
GP_EDITABLE_CURVES_BEGIN(gps_iter, C, gpl, gps, gpc)
{
@ -1410,9 +1410,8 @@ void ED_gpencil_strokes_copybuf_free(void)
{
bGPDstroke *gps, *gpsn;
/* Free the colors buffer
* NOTE: This is done before the strokes so that the ptrs are still safe
*/
/* Free the colors buffer.
* NOTE: This is done before the strokes so that the pointers are still safe. */
if (gpencil_strokes_copypastebuf_colors) {
BLI_ghash_free(gpencil_strokes_copypastebuf_colors, NULL, MEM_freeN);
gpencil_strokes_copypastebuf_colors = NULL;

View File

@ -715,7 +715,7 @@ static void gpencil_update_extensions_line(tGPDfill *tgpf)
}
}
/* Cut overlength strokes. */
/* Cut over-length strokes. */
gpencil_cut_extensions(tgpf);
}
@ -1317,10 +1317,10 @@ static bool gpencil_render_offscreen(tGPDfill *tgpf)
/* create a image to see result of template */
if (ibuf->rect_float) {
GPU_offscreen_read_pixels(offscreen, GPU_DATA_FLOAT, ibuf->rect_float);
GPU_offscreen_read_color(offscreen, GPU_DATA_FLOAT, ibuf->rect_float);
}
else if (ibuf->rect) {
GPU_offscreen_read_pixels(offscreen, GPU_DATA_UBYTE, ibuf->rect);
GPU_offscreen_read_color(offscreen, GPU_DATA_UBYTE, ibuf->rect);
}
if (ibuf->rect_float && ibuf->rect) {
IMB_rect_from_float(ibuf);

View File

@ -1371,7 +1371,7 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
float factor = (float)(cframe - prevFrame->framenum) / framerange;
if (type == GP_IPO_CURVEMAP) {
/* custom curvemap */
/* Custom curve-map. */
if (ipo_settings->custom_ipo) {
factor = BKE_curvemapping_evaluateF(ipo_settings->custom_ipo, 0, factor);
}

View File

@ -374,7 +374,7 @@ static bool gpencil_stroke_filtermval(tGPsdata *p, const float mval[2], const fl
}
/* Check if the distance since the last point is significant enough:
* - Prevents points being added too densely
* - Distance here doesn't use sqrt to prevent slowness.
* - Distance here doesn't use `sqrt` to prevent slowness.
* We should still be safe from overflows though.
*/
if ((dx * dx + dy * dy) > MIN_EUCLIDEAN_PX * MIN_EUCLIDEAN_PX) {

View File

@ -1222,7 +1222,7 @@ static void gpencil_primitive_init(bContext *C, wmOperator *op)
"gp primitive cpoint");
tgpi->gpd->runtime.tot_cp_points = 0;
/* getcolor info */
/* Get color info. */
tgpi->material = BKE_gpencil_object_material_ensure_from_active_input_toolsettings(
bmain, tgpi->ob, ts);

View File

@ -1324,7 +1324,7 @@ static void gpencil_sculpt_brush_exit(bContext *C, wmOperator *op)
BLI_ghash_free(gso->automasking_strokes, NULL, NULL);
}
/* Disable headerprints. */
/* Clear status-bar text. */
ED_workspace_status_text(C, NULL);
/* disable temp invert flag */
@ -2320,21 +2320,21 @@ static int gpencil_sculpt_brush_modal(bContext *C, wmOperator *op, const wmEvent
bool redraw_region = false;
bool redraw_toolsettings = false;
/* The operator can be in 2 states: Painting and Idling */
/* The operator can be in 2 states: Painting and Idling. */
if (gso->is_painting) {
/* Painting. */
switch (event->type) {
/* Mouse Move = Apply somewhere else */
/* Mouse Move: Apply somewhere else. */
case MOUSEMOVE:
case INBETWEEN_MOUSEMOVE:
/* apply brush effect at new position */
/* apply brush effect at new position. */
gpencil_sculpt_brush_apply_event(C, op, event);
/* force redraw, so that the cursor will at least be valid */
/* force redraw, so that the cursor will at least be valid. */
redraw_region = true;
break;
/* Timer Tick - Only if this was our own timer */
/* Timer Tick - Only if this was our own timer. */
case TIMER:
if (event->customdata == gso->timer) {
gso->timerTick = true;
@ -2343,7 +2343,7 @@ static int gpencil_sculpt_brush_modal(bContext *C, wmOperator *op, const wmEvent
}
break;
/* Painting mbut release = Stop painting (back to idle) */
/* Painting mouse-button release: Stop painting (back to idle). */
case LEFTMOUSE:
// BLI_assert(event->val == KM_RELEASE);
if (is_modal) {
@ -2351,7 +2351,7 @@ static int gpencil_sculpt_brush_modal(bContext *C, wmOperator *op, const wmEvent
gso->is_painting = false;
}
else {
/* end sculpt session, since we're not modal */
/* end sculpt session, since we're not modal. */
gso->is_painting = false;
gpencil_sculpt_brush_exit(C, op);
@ -2359,7 +2359,7 @@ static int gpencil_sculpt_brush_modal(bContext *C, wmOperator *op, const wmEvent
}
break;
/* Abort painting if any of the usual things are tried */
/* Abort painting if any of the usual things are tried. */
case MIDDLEMOUSE:
case RIGHTMOUSE:
case EVT_ESCKEY:
@ -2368,13 +2368,13 @@ static int gpencil_sculpt_brush_modal(bContext *C, wmOperator *op, const wmEvent
}
}
else {
/* Idling */
/* Idling. */
BLI_assert(is_modal == true);
switch (event->type) {
/* Painting mbut press = Start painting (switch to painting state) */
/* Painting mouse-button press: Start painting (switch to painting state). */
case LEFTMOUSE:
/* do initial "click" apply */
/* do initial "click" apply. */
gso->is_painting = true;
gso->first = true;
@ -2382,30 +2382,30 @@ static int gpencil_sculpt_brush_modal(bContext *C, wmOperator *op, const wmEvent
gpencil_sculpt_brush_apply_event(C, op, event);
break;
/* Exit modal operator, based on the "standard" ops */
/* Exit modal operator, based on the "standard" ops. */
case RIGHTMOUSE:
case EVT_ESCKEY:
gpencil_sculpt_brush_exit(C, op);
return OPERATOR_FINISHED;
/* MMB is often used for view manipulations */
/* MMB is often used for view manipulations. */
case MIDDLEMOUSE:
return OPERATOR_PASS_THROUGH;
/* Mouse movements should update the brush cursor - Just redraw the active region */
/* Mouse movements should update the brush cursor - Just redraw the active region. */
case MOUSEMOVE:
case INBETWEEN_MOUSEMOVE:
redraw_region = true;
break;
/* Change Frame - Allowed */
/* Change Frame - Allowed. */
case EVT_LEFTARROWKEY:
case EVT_RIGHTARROWKEY:
case EVT_UPARROWKEY:
case EVT_DOWNARROWKEY:
return OPERATOR_PASS_THROUGH;
/* Camera/View Gizmo's - Allowed */
/* Camera/View Gizmo's - Allowed. */
/* (See rationale in gpencil_paint.c -> gpencil_draw_modal()) */
case EVT_PAD0:
case EVT_PAD1:
@ -2419,7 +2419,7 @@ static int gpencil_sculpt_brush_modal(bContext *C, wmOperator *op, const wmEvent
case EVT_PAD9:
return OPERATOR_PASS_THROUGH;
/* Unhandled event */
/* Unhandled event. */
default:
break;
}

View File

@ -761,7 +761,7 @@ static void gpencil_vertexpaint_brush_exit(bContext *C, wmOperator *op)
{
tGP_BrushVertexpaintData *gso = op->customdata;
/* Disable headerprints. */
/* Clear status-bar text. */
ED_workspace_status_text(C, NULL);
/* Disable temp invert flag. */
@ -1318,28 +1318,28 @@ static int gpencil_vertexpaint_brush_modal(bContext *C, wmOperator *op, const wm
bool redraw_region = false;
bool redraw_toolsettings = false;
/* The operator can be in 2 states: Painting and Idling */
/* The operator can be in 2 states: Painting and Idling. */
if (gso->is_painting) {
/* Painting. */
switch (event->type) {
/* Mouse Move = Apply somewhere else */
/* Mouse Move: Apply somewhere else. */
case MOUSEMOVE:
case INBETWEEN_MOUSEMOVE:
/* apply brush effect at new position */
/* Apply brush effect at new position. */
gpencil_vertexpaint_brush_apply_event(C, op, event);
/* force redraw, so that the cursor will at least be valid */
/* Force redraw, so that the cursor will at least be valid. */
redraw_region = true;
break;
/* Painting mbut release = Stop painting (back to idle) */
/* Painting mouse-button release means: Stop painting (back to idle). */
case LEFTMOUSE:
if (is_modal) {
/* go back to idling... */
gso->is_painting = false;
}
else {
/* end painting, since we're not modal */
/* end painting, since we're not modal. */
gso->is_painting = false;
gpencil_vertexpaint_brush_exit(C, op);
@ -1347,7 +1347,7 @@ static int gpencil_vertexpaint_brush_modal(bContext *C, wmOperator *op, const wm
}
break;
/* Abort painting if any of the usual things are tried */
/* Abort painting if any of the usual things are tried. */
case MIDDLEMOUSE:
case RIGHTMOUSE:
case EVT_ESCKEY:
@ -1356,43 +1356,43 @@ static int gpencil_vertexpaint_brush_modal(bContext *C, wmOperator *op, const wm
}
}
else {
/* Idling */
/* Idling. */
BLI_assert(is_modal == true);
switch (event->type) {
/* Painting mbut press = Start painting (switch to painting state) */
/* Painting mouse-button press means: Start painting (switch to painting state). */
case LEFTMOUSE:
/* do initial "click" apply */
/* do initial "click" apply. */
gso->is_painting = true;
gso->first = true;
gpencil_vertexpaint_brush_apply_event(C, op, event);
break;
/* Exit modal operator, based on the "standard" ops */
/* Exit modal operator, based on the "standard" ops. */
case RIGHTMOUSE:
case EVT_ESCKEY:
gpencil_vertexpaint_brush_exit(C, op);
return OPERATOR_FINISHED;
/* MMB is often used for view manipulations */
/* MMB is often used for view manipulations. */
case MIDDLEMOUSE:
return OPERATOR_PASS_THROUGH;
/* Mouse movements should update the brush cursor - Just redraw the active region */
/* Mouse movements should update the brush cursor - Just redraw the active region. */
case MOUSEMOVE:
case INBETWEEN_MOUSEMOVE:
redraw_region = true;
break;
/* Change Frame - Allowed */
/* Change Frame - Allowed. */
case EVT_LEFTARROWKEY:
case EVT_RIGHTARROWKEY:
case EVT_UPARROWKEY:
case EVT_DOWNARROWKEY:
return OPERATOR_PASS_THROUGH;
/* Camera/View Gizmo's - Allowed */
/* Camera/View Gizmo's - Allowed. */
/* (See rationale in gpencil_paint.c -> gpencil_draw_modal()) */
case EVT_PAD0:
case EVT_PAD1:
@ -1406,7 +1406,7 @@ static int gpencil_vertexpaint_brush_modal(bContext *C, wmOperator *op, const wm
case EVT_PAD9:
return OPERATOR_PASS_THROUGH;
/* Unhandled event */
/* Unhandled event. */
default:
break;
}

View File

@ -345,7 +345,7 @@ static void gpencil_weightpaint_brush_exit(bContext *C, wmOperator *op)
{
tGP_BrushWeightpaintData *gso = op->customdata;
/* Disable headerprints. */
/* Clear status bar text. */
ED_workspace_status_text(C, NULL);
/* Free operator data */
@ -767,7 +767,7 @@ static int gpencil_weightpaint_brush_invoke(bContext *C, wmOperator *op, const w
return OPERATOR_RUNNING_MODAL;
}
/* painting - handle events */
/* painting - handle events. */
static int gpencil_weightpaint_brush_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
tGP_BrushWeightpaintData *gso = op->customdata;
@ -775,28 +775,28 @@ static int gpencil_weightpaint_brush_modal(bContext *C, wmOperator *op, const wm
bool redraw_region = false;
bool redraw_toolsettings = false;
/* The operator can be in 2 states: Painting and Idling */
/* The operator can be in 2 states: Painting and Idling. */
if (gso->is_painting) {
/* Painting. */
switch (event->type) {
/* Mouse Move = Apply somewhere else */
/* Mouse Move: Apply somewhere else. */
case MOUSEMOVE:
case INBETWEEN_MOUSEMOVE:
/* apply brush effect at new position */
/* Apply brush effect at new position. */
gpencil_weightpaint_brush_apply_event(C, op, event);
/* force redraw, so that the cursor will at least be valid */
/* Force redraw, so that the cursor will at least be valid. */
redraw_region = true;
break;
/* Painting mbut release = Stop painting (back to idle) */
/* Painting mouse-button release: Stop painting (back to idle). */
case LEFTMOUSE:
if (is_modal) {
/* go back to idling... */
gso->is_painting = false;
}
else {
/* end painting, since we're not modal */
/* end painting, since we're not modal. */
gso->is_painting = false;
gpencil_weightpaint_brush_exit(C, op);
@ -804,7 +804,7 @@ static int gpencil_weightpaint_brush_modal(bContext *C, wmOperator *op, const wm
}
break;
/* Abort painting if any of the usual things are tried */
/* Abort painting if any of the usual things are tried. */
case MIDDLEMOUSE:
case RIGHTMOUSE:
case EVT_ESCKEY:
@ -813,43 +813,43 @@ static int gpencil_weightpaint_brush_modal(bContext *C, wmOperator *op, const wm
}
}
else {
/* Idling */
/* Idling. */
BLI_assert(is_modal == true);
switch (event->type) {
/* Painting mbut press = Start painting (switch to painting state) */
/* Painting mouse-button press = Start painting (switch to painting state). */
case LEFTMOUSE:
/* do initial "click" apply */
/* do initial "click" apply. */
gso->is_painting = true;
gso->first = true;
gpencil_weightpaint_brush_apply_event(C, op, event);
break;
/* Exit modal operator, based on the "standard" ops */
/* Exit modal operator, based on the "standard" ops. */
case RIGHTMOUSE:
case EVT_ESCKEY:
gpencil_weightpaint_brush_exit(C, op);
return OPERATOR_FINISHED;
/* MMB is often used for view manipulations */
/* MMB is often used for view manipulations. */
case MIDDLEMOUSE:
return OPERATOR_PASS_THROUGH;
/* Mouse movements should update the brush cursor - Just redraw the active region */
/* Mouse movements should update the brush cursor - Just redraw the active region. */
case MOUSEMOVE:
case INBETWEEN_MOUSEMOVE:
redraw_region = true;
break;
/* Change Frame - Allowed */
/* Change Frame - Allowed. */
case EVT_LEFTARROWKEY:
case EVT_RIGHTARROWKEY:
case EVT_UPARROWKEY:
case EVT_DOWNARROWKEY:
return OPERATOR_PASS_THROUGH;
/* Camera/View Gizmo's - Allowed */
/* Camera/View Gizmo's - Allowed. */
/* (See rationale in gpencil_paint.c -> gpencil_draw_modal()) */
case EVT_PAD0:
case EVT_PAD1:
@ -863,7 +863,7 @@ static int gpencil_weightpaint_brush_modal(bContext *C, wmOperator *op, const wm
case EVT_PAD9:
return OPERATOR_PASS_THROUGH;
/* Unhandled event */
/* Unhandled event. */
default:
break;
}

View File

@ -361,7 +361,13 @@ void eyedropper_color_sample_fl(bContext *C, const int m_xy[2], float r_col[3])
if (win) {
/* Fallback to simple opengl picker. */
WM_window_pixel_sample_read(wm, win, mval, r_col);
if (WM_capabilities_flag() & WM_CAPABILITY_GPU_FRONT_BUFFER_READ) {
WM_window_pixels_read_sample(wm, win, mval, r_col);
}
else {
WM_window_pixels_read_sample_offscreen(C, win, mval, r_col);
}
IMB_colormanagement_display_to_scene_linear_v3(r_col, display);
}
else {

View File

@ -333,7 +333,7 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R
gp_rect = static_cast<uchar *>(
MEM_mallocN(sizeof(uchar[4]) * sizex * sizey, "offscreen rect"));
GPU_offscreen_read_pixels(oglrender->ofs, GPU_DATA_UBYTE, gp_rect);
GPU_offscreen_read_color(oglrender->ofs, GPU_DATA_UBYTE, gp_rect);
for (i = 0; i < sizex * sizey * 4; i += 4) {
blend_color_mix_byte(&render_rect[i], &render_rect[i], &gp_rect[i]);

View File

@ -439,7 +439,7 @@ void ED_screen_preview_render(const bScreen *screen, int size_x, int size_y, uin
screen_preview_draw(screen, size_x, size_y);
GPU_offscreen_read_pixels(offscreen, GPU_DATA_UBYTE, r_rect);
GPU_offscreen_read_color(offscreen, GPU_DATA_UBYTE, r_rect);
GPU_offscreen_unbind(offscreen, true);
GPU_offscreen_free(offscreen);

View File

@ -56,12 +56,15 @@ static int screenshot_data_create(bContext *C, wmOperator *op, ScrArea *area)
{
int dumprect_size[2];
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = CTX_wm_window(C);
/* do redraw so we don't show popups/menus */
WM_redraw_windows(C);
uint *dumprect = WM_window_pixels_read_offscreen(C, win, dumprect_size);
uint *dumprect = (WM_capabilities_flag() & WM_CAPABILITY_GPU_FRONT_BUFFER_READ) ?
WM_window_pixels_read(wm, win, dumprect_size) :
WM_window_pixels_read_offscreen(C, win, dumprect_size);
if (dumprect) {
ScreenshotData *scd = MEM_callocN(sizeof(ScreenshotData), "screenshot");

View File

@ -537,7 +537,7 @@ void paint_sample_color(
/* No sample found; sample directly from the GPU front buffer. */
{
float rgba_f[4];
GPU_frontbuffer_read_pixels(
GPU_frontbuffer_read_color(
x + region->winrct.xmin, y + region->winrct.ymin, 1, 1, 4, GPU_DATA_FLOAT, &rgba_f);
if (use_palette) {

View File

@ -3021,7 +3021,7 @@ static void do_vpaint_brush_blur_loops(bContext *C,
for (const int corner : poly) {
Color *col = lcol + corner;
/* Color is squared to compensate the sqrt color encoding. */
/* Color is squared to compensate the `sqrt` color encoding. */
blend[0] += (Blend)col->r * (Blend)col->r;
blend[1] += (Blend)col->g * (Blend)col->g;
blend[2] += (Blend)col->b * (Blend)col->b;
@ -3164,7 +3164,7 @@ static void do_vpaint_brush_blur_verts(bContext *C,
for (const int vert : ss->corner_verts.slice(poly)) {
Color *col = lcol + vert;
/* Color is squared to compensate the sqrt color encoding. */
/* Color is squared to compensate the `sqrt` color encoding. */
blend[0] += (Blend)col->r * (Blend)col->r;
blend[1] += (Blend)col->g * (Blend)col->g;
blend[2] += (Blend)col->b * (Blend)col->b;
@ -3463,7 +3463,7 @@ static void calculate_average_color(VPaintData<Color, Traits, domain> *vpd,
Color *col = lcol + elem_index;
/* Color is squared to compensate the sqrt color encoding. */
/* Color is squared to compensate the `sqrt` color encoding. */
accum2->value[0] += col->r * col->r;
accum2->value[1] += col->g * col->g;
accum2->value[2] += col->b * col->b;

View File

@ -470,10 +470,10 @@ static int console_insert_invoke(bContext *C, wmOperator *op, const wmEvent *eve
/* NOTE: the "text" property is always set from key-map,
* so we can't use #RNA_struct_property_is_set, check the length instead. */
if (!RNA_string_length(op->ptr, "text")) {
/* if alt/ctrl/super are pressed pass through except for utf8 character event
* (when input method are used for utf8 inputs, the user may assign key event
* including alt/ctrl/super like ctrl+m to commit utf8 string. in such case,
* the modifiers in the utf8 character event make no sense.) */
/* If alt/control/super are pressed pass through except for UTF8 character event
* (when input method are used for UTF8 inputs, the user may assign key event
* including alt/control/super like control-m to commit UTF8 string.
* in such case, the modifiers in the UTF8 character event make no sense.) */
if ((event->modifier & (KM_CTRL | KM_OSKEY)) && !event->utf8_buf[0]) {
return OPERATOR_PASS_THROUGH;
}

View File

@ -2177,7 +2177,7 @@ static void outliner_batch_delete_object_tag(ReportList *reports,
reports, RPT_WARNING, "Cannot delete indirectly linked object '%s'", object->id.name + 2);
BLI_assert((object->id.tag & LIB_TAG_DOIT) == 0);
}
/* FIXME: This code checking object usercount won't work as expected if a same object belongs to
/* FIXME: This code checking object user-count won't work as expected if a same object belongs to
* more than one collection in the scene. */
if (ID_REAL_USERS(object) <= 1 && ID_EXTRA_USERS(object) == 0 &&
BKE_library_ID_is_indirectly_used(bmain, object)) {

View File

@ -1976,10 +1976,10 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph,
nullptr);
if (ibuf->rect_float) {
GPU_offscreen_read_pixels(ofs, GPU_DATA_FLOAT, ibuf->rect_float);
GPU_offscreen_read_color(ofs, GPU_DATA_FLOAT, ibuf->rect_float);
}
else if (ibuf->rect) {
GPU_offscreen_read_pixels(ofs, GPU_DATA_UBYTE, ibuf->rect);
GPU_offscreen_read_color(ofs, GPU_DATA_UBYTE, ibuf->rect);
}
/* unbind */

View File

@ -160,12 +160,66 @@ void view3d_orbit_apply_dyn_ofs(float r_ofs[3],
add_v3_v3(r_ofs, dyn_ofs);
}
static void view3d_orbit_apply_dyn_ofs_ortho_correction(float ofs[3],
const float viewquat_old[4],
const float viewquat_new[4],
const float dyn_ofs[3])
{
/* NOTE(@ideasman42): While orbiting in orthographic mode the "depth" of the offset
* (position along the views Z-axis) is only noticeable when the view contents is clipped.
* The likelihood of clipping depends on the clipping range & size of the scene.
* In practice some users might not run into this, however using dynamic-offset in
* orthographic views can cause the depth of the offset to drift while navigating the view,
* causing unexpected clipping that seems like a bug from the user perspective, see: #104385.
*
* Imagine a camera is focused on a distant object. Now imagine a closer object in front of
* the camera is used as a pivot, the camera is rotated to view it from the side (~90d rotation).
* The outcome is the camera is now focused on a distant region to the left/right.
* The new focal point is unlikely to point to anything useful (unless by accident).
* Instead of a focal point - the `rv3d->ofs` is being manipulated in this case.
*
* Resolve by moving #RegionView3D::ofs so it is depth-aligned to `dyn_ofs`,
* this is interpolated by the amount of rotation so minor rotations don't cause
* the view-clipping to suddenly jump. */
float q_inv[4];
float view_z_init[3] = {0.0f, 0.0f, 1.0f};
invert_qt_qt_normalized(q_inv, viewquat_old);
mul_qt_v3(q_inv, view_z_init);
float view_z_curr[3] = {0.0f, 0.0f, 1.0f};
invert_qt_qt_normalized(q_inv, viewquat_new);
mul_qt_v3(q_inv, view_z_curr);
const float angle_cos = max_ff(0.0f, dot_v3v3(view_z_init, view_z_curr));
/* 1.0 or more means no rotation, there is nothing to do in that case. */
if (LIKELY(angle_cos < 1.0f)) {
const float dot_ofs_curr = dot_v3v3(view_z_curr, ofs);
const float dot_ofs_next = dot_v3v3(view_z_curr, dyn_ofs);
const float ofs_delta = dot_ofs_next - dot_ofs_curr;
if (LIKELY(ofs_delta != 0.0f)) {
/* Calculate a factor where 0.0 represents no rotation and 1.0 represents 90d or more.
* NOTE: Without applying the factor, the distances immediately changes
* (useful for testing), but not good for the users experience as minor rotations
* should not immediately adjust the depth. */
const float factor = acosf(angle_cos) / M_PI_2;
madd_v3_v3fl(ofs, view_z_curr, ofs_delta * factor);
}
}
}
void viewrotate_apply_dyn_ofs(ViewOpsData *vod, const float viewquat_new[4])
{
if (vod->use_dyn_ofs) {
RegionView3D *rv3d = vod->rv3d;
view3d_orbit_apply_dyn_ofs(
rv3d->ofs, vod->init.ofs, vod->init.quat, viewquat_new, vod->dyn_ofs);
if (vod->use_dyn_ofs_ortho_correction) {
view3d_orbit_apply_dyn_ofs_ortho_correction(
rv3d->ofs, vod->init.quat, viewquat_new, vod->dyn_ofs);
}
}
}

View File

@ -151,6 +151,15 @@ typedef struct ViewOpsData {
/** Use for orbit selection and auto-dist. */
float dyn_ofs[3];
bool use_dyn_ofs;
/**
* In orthographic views, a dynamic offset should not cause #RegionView3D::ofs to end up
* at a location that has no relation to the content where `ofs` originated or to `dyn_ofs`.
* Failing to do so can cause the orthographic views `ofs` to be far away from the content
* to the point it gets clipped out of the view.
* See #view3d_orbit_apply_dyn_ofs code-comments for an example, also see: #104385.
*/
bool use_dyn_ofs_ortho_correction;
} ViewOpsData;
/* view3d_navigate.cc */

View File

@ -430,6 +430,10 @@ static int viewrotate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
viewops_flag_from_prefs() | VIEWOPS_FLAG_PERSP_ENSURE |
(use_cursor_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0));
if (vod->use_dyn_ofs && (vod->rv3d->is_persp == false)) {
vod->use_dyn_ofs_ortho_correction = true;
}
ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
if (ELEM(event->type, MOUSEPAN, MOUSEROTATE)) {

View File

@ -218,7 +218,7 @@ static void createTransGPencil_curves(bContext *C,
if (IS_AUTOKEY_ON(scene)) {
gpf = BKE_gpencil_frame_addcopy(gpl, cfra);
}
/* in some weird situations (framelock enabled) return NULL */
/* In some weird situations (frame-lock enabled) return NULL. */
if (gpf == NULL) {
continue;
}
@ -513,7 +513,7 @@ static void createTransGPencil_strokes(bContext *C,
if (IS_AUTOKEY_ON(scene)) {
gpf = BKE_gpencil_frame_addcopy(gpl, cfra);
}
/* in some weird situations (framelock enabled) return NULL */
/* In some weird situations (frame-lock enabled) return NULL. */
if (gpf == NULL) {
continue;
}
@ -628,14 +628,14 @@ static void createTransGPencil_strokes(bContext *C,
}
}
/* screenspace needs special matrices... */
/* Screen-space needs special matrices. */
if ((gps->flag & (GP_STROKE_3DSPACE | GP_STROKE_2DSPACE | GP_STROKE_2DIMAGE)) ==
0) {
/* screenspace */
/* Screen-space. */
td->protectflag = OB_LOCK_LOCZ | OB_LOCK_ROTZ | OB_LOCK_SCALEZ;
}
else {
/* configure 2D dataspace points so that they don't play up... */
/* configure 2D data-space points so that they don't play up. */
if (gps->flag & (GP_STROKE_2DSPACE | GP_STROKE_2DIMAGE)) {
td->protectflag = OB_LOCK_LOCZ | OB_LOCK_ROTZ | OB_LOCK_SCALEZ;
}
@ -646,10 +646,10 @@ static void createTransGPencil_strokes(bContext *C,
copy_m3_m3(td->axismtx, diff_mat); /* axis orientation */
/* Triangulation must be calculated again,
* so save the stroke for recalc function */
* so save the stroke for recalculate function. */
td->extra = gps;
/* save pointer to object */
/* Save pointer to object. */
td->ob = obact;
td++;
@ -657,7 +657,7 @@ static void createTransGPencil_strokes(bContext *C,
}
}
/* March over these points, and calculate the proportional editing distances */
/* March over these points, and calculate the proportional editing distances. */
if (is_prop_edit && (head != tail)) {
calc_distanceCurveVerts(head, tail - 1, false);
}

View File

@ -285,7 +285,7 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob)
invert_m3_m3_safe_ortho(td->mtx, td->smtx);
}
else {
/* no conversion to/from dataspace */
/* No conversion to/from data-space. */
unit_m3(td->smtx);
unit_m3(td->mtx);
}

View File

@ -40,7 +40,7 @@ static void drawArrow(const uint pos_id, const enum eArrowDirection dir)
int size = (3.0f * UI_SCALE_FAC) + (2.0f * U.pixelsize);
/* To line up the arrow point nicely, one end has to be extended by half its width. But
* being on a 45 degree angle, Pythagoras says a movement of sqrt(2)/2 * (line width /2) */
* being on a 45 degree angle, Pythagoras says a movement of `sqrt(2) / 2 * (line width / 2)`. */
float adjust = (M_SQRT2 * ARROW_WIDTH / 4.0f);
if (ELEM(dir, LEFT, DOWN)) {

View File

@ -1273,7 +1273,7 @@ class OverlapMerger {
}
/** Return a new root of the binary tree, with `a` and `b` as leaves. */
static PackIsland *merge_islands(PackIsland *a, PackIsland *b, const UVPackIsland_Params &params)
static PackIsland *merge_islands(PackIsland *a, PackIsland *b)
{
PackIsland *result = new PackIsland();
result->aspect_y = sqrtf(a->aspect_y * b->aspect_y);
@ -1306,7 +1306,7 @@ class OverlapMerger {
if (overlap(island, sub_islands[j])) {
merge_trace.append(island);
merge_trace.append(sub_islands[j]);
island = merge_islands(island, sub_islands[j], params);
island = merge_islands(island, sub_islands[j]);
merge_trace.append(island);
sub_islands.remove(j);
}

View File

@ -164,7 +164,7 @@ static void generate_geometry(GpencilModifierData *md,
bGPdata *gpd = (bGPdata *)ob->data;
bool found = false;
/* Get bounbox for relative offset. */
/* Get bound-box for relative offset. */
float size[3] = {0.0f, 0.0f, 0.0f};
if (mmd->flag & GP_ARRAY_USE_RELATIVE) {
float min[3];

View File

@ -61,7 +61,7 @@ static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
BKE_gpencil_modifier_copydata_generic(md, target);
}
/* change stroke offsetness */
/* Change stroke offset. */
static void deformStroke(GpencilModifierData *md,
Depsgraph *UNUSED(depsgraph),
Object *ob,

View File

@ -539,7 +539,7 @@ void GPU_framebuffer_read_color(GPUFrameBuffer *framebuffer,
* TODO: Emulate this by doing some slow texture copy on the backend side or try to read the areas
* offscreen textures directly.
*/
void GPU_frontbuffer_read_pixels(
void GPU_frontbuffer_read_color(
int x, int y, int width, int height, int channels, eGPUDataFormat data_format, void *r_data);
/**
@ -623,7 +623,12 @@ void GPU_offscreen_unbind(GPUOffScreen *offscreen, bool restore);
* attachment type.
* IMPORTANT: \a r_data must be big enough for all pixels in \a data_format .
*/
void GPU_offscreen_read_pixels(GPUOffScreen *offscreen, eGPUDataFormat data_format, void *r_data);
void GPU_offscreen_read_color(GPUOffScreen *offscreen, eGPUDataFormat data_format, void *r_data);
/**
* A version of #GPU_offscreen_read_color that reads into a region.
*/
void GPU_offscreen_read_color_region(
GPUOffScreen *offscreen, eGPUDataFormat data_format, int x, int y, int w, int h, void *r_data);
/**
* Blit the offscreen color texture to the active framebuffer at the `(x, y)` location.

View File

@ -484,8 +484,7 @@ void GPU_framebuffer_read_color(GPUFrameBuffer *gpu_fb,
unwrap(gpu_fb)->read(GPU_COLOR_BIT, format, rect, channels, slot, data);
}
/* TODO(fclem): rename to read_color. */
void GPU_frontbuffer_read_pixels(
void GPU_frontbuffer_read_color(
int x, int y, int w, int h, int channels, eGPUDataFormat format, void *data)
{
int rect[4] = {x, y, w, h};
@ -747,15 +746,26 @@ void GPU_offscreen_draw_to_screen(GPUOffScreen *ofs, int x, int y)
ofs_fb->blit_to(GPU_COLOR_BIT, 0, ctx->active_fb, 0, x, y);
}
void GPU_offscreen_read_pixels(GPUOffScreen *ofs, eGPUDataFormat format, void *pixels)
void GPU_offscreen_read_color_region(
GPUOffScreen *ofs, eGPUDataFormat format, int x, int y, int w, int h, void *r_data)
{
BLI_assert(ELEM(format, GPU_DATA_UBYTE, GPU_DATA_FLOAT));
BLI_assert(x >= 0 && y >= 0 && w > 0 && h > 0);
BLI_assert(x + w <= GPU_texture_width(ofs->color));
BLI_assert(y + h <= GPU_texture_height(ofs->color));
GPUFrameBuffer *ofs_fb = gpu_offscreen_fb_get(ofs);
GPU_framebuffer_read_color(ofs_fb, x, y, w, h, 4, 0, format, r_data);
}
void GPU_offscreen_read_color(GPUOffScreen *ofs, eGPUDataFormat format, void *r_data)
{
BLI_assert(ELEM(format, GPU_DATA_UBYTE, GPU_DATA_FLOAT));
const int w = GPU_texture_width(ofs->color);
const int h = GPU_texture_height(ofs->color);
GPUFrameBuffer *ofs_fb = gpu_offscreen_fb_get(ofs);
GPU_framebuffer_read_color(ofs_fb, 0, 0, w, h, 4, 0, format, pixels);
GPU_offscreen_read_color_region(ofs, format, 0, 0, w, h, r_data);
}
int GPU_offscreen_width(const GPUOffScreen *ofs)

View File

@ -196,37 +196,41 @@ void load_plydata(PlyData &plyData, Depsgraph *depsgraph, const PLYExportParams
world_and_axes_normal_transform);
/* Face data. */
plyData.face_vertices.reserve(mesh->totloop);
plyData.face_sizes.reserve(mesh->totpoly);
plyData.face_vertices.reserve(plyData.face_vertices.size() + mesh->totloop);
for (const int corner : IndexRange(mesh->totloop)) {
int ply_index = loop_to_ply[corner];
BLI_assert(ply_index >= 0 && ply_index < ply_to_vertex.size());
plyData.face_vertices.append_unchecked(ply_index + vertex_offset);
}
plyData.face_sizes.reserve(plyData.face_sizes.size() + mesh->totpoly);
for (const int i : polys.index_range()) {
const IndexRange poly = polys[i];
for (const int corner : poly) {
int ply_index = loop_to_ply[corner];
BLI_assert(ply_index >= 0 && ply_index < ply_to_vertex.size());
plyData.face_vertices.append(ply_index + vertex_offset);
}
plyData.face_sizes.append(poly.size());
plyData.face_sizes.append_unchecked(poly.size());
}
/* Vertices */
plyData.vertices.reserve(ply_to_vertex.size());
plyData.vertices.reserve(plyData.vertices.size() + ply_to_vertex.size());
Span<float3> vert_positions = mesh->vert_positions();
for (int vertex_index : ply_to_vertex) {
float3 pos = vert_positions[vertex_index];
mul_m4_v3(world_and_axes_transform, pos);
mul_v3_fl(pos, export_params.global_scale);
plyData.vertices.append(pos);
plyData.vertices.append_unchecked(pos);
}
/* UV's */
if (!uvs.is_empty()) {
if (uvs.is_empty()) {
uvs.append_n_times(float2(0), ply_to_vertex.size());
}
else {
BLI_assert(uvs.size() == ply_to_vertex.size());
plyData.uv_coordinates = uvs;
plyData.uv_coordinates.extend(uvs);
}
/* Normals */
if (export_params.export_normals) {
plyData.vertex_normals.reserve(ply_to_vertex.size());
plyData.vertex_normals.reserve(plyData.vertex_normals.size() + ply_to_vertex.size());
const Span<float3> vert_normals = mesh->vert_normals();
for (int vertex_index : ply_to_vertex) {
float3 normal = vert_normals[vertex_index];

View File

@ -715,7 +715,7 @@ enum {
/**
* Long-life tags giving important info about general ID management.
*
* These tags are typically not chnaged often, if ever, during an ID's life.
* These tags are typically not changed often, if ever, during an ID's life.
*/
/**
@ -793,7 +793,7 @@ enum {
LIB_TAG_LIB_OVERRIDE_NEED_RESYNC = 1 << 8,
/**
* Short-life tags used during specific processes, like blendfile readind.
* Short-life tags used during specific processes, like blend-file reading.
*/
/**

View File

@ -2548,7 +2548,7 @@ static void rna_def_modifier_gpencilbuild(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Time Alignment", "How should strokes start to appear/disappear");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
/* Which time mode to use: Current frames, manual percentage, or drawspeed. */
/* Which time mode to use: Current frames, manual percentage, or draw-speed. */
prop = RNA_def_property(srna, "time_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "time_mode");
RNA_def_property_enum_items(prop, gpencil_build_time_mode_items);

View File

@ -1038,7 +1038,7 @@ static void rna_EnumProperty_items_begin(CollectionPropertyIterator *iter, Point
static void rna_EnumProperty_items_ui_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
/* No skip-funciton, include all "UI" items. */
/* No skip-function, include all "UI" items. */
rna_EnumProperty_items_begin_impl(iter, ptr, NULL);
}

View File

@ -2787,7 +2787,7 @@ static void rna_def_gpencil_interpolate(BlenderRNA *brna)
"Grease Pencil Interpolate Settings",
"Settings for Grease Pencil interpolation tools");
/* custom curvemap */
/* Custom curve-map. */
prop = RNA_def_property(srna, "interpolation_curve", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "custom_ipo");
RNA_def_property_struct_type(prop, "CurveMapping");

View File

@ -134,6 +134,12 @@ typedef enum eWM_CapabilitiesFlag {
* (typically set when interactively selecting text).
*/
WM_CAPABILITY_PRIMARY_CLIPBOARD = (1 << 2),
/**
* Reading from the back-buffer is supported.
*/
WM_CAPABILITY_GPU_FRONT_BUFFER_READ = (1 << 3),
/** Ability to copy/paste system clipboard images. */
WM_CAPABILITY_CLIPBOARD_IMAGES = (1 << 4),
} eWM_CapabilitiesFlag;
eWM_CapabilitiesFlag WM_capabilities_flag(void);
@ -155,11 +161,6 @@ wmWindow *WM_window_find_under_cursor(wmWindow *win, const int mval[2], int r_mv
*/
wmWindow *WM_window_find_by_area(wmWindowManager *wm, const struct ScrArea *area);
void WM_window_pixel_sample_read(const wmWindowManager *wm,
const wmWindow *win,
const int pos[2],
float r_col[3]);
/**
* Read pixels from the front-buffer (fast).
*
@ -171,6 +172,11 @@ void WM_window_pixel_sample_read(const wmWindowManager *wm,
* the front-buffer state to be invalid under some EGL configurations.
*/
uint *WM_window_pixels_read(struct wmWindowManager *wm, struct wmWindow *win, int r_size[2]);
void WM_window_pixels_read_sample(const wmWindowManager *wm,
const wmWindow *win,
const int pos[2],
float r_col[3]);
/**
* Draw the window & read pixels from an off-screen buffer (slower than #WM_window_pixels_read).
*
@ -178,6 +184,10 @@ uint *WM_window_pixels_read(struct wmWindowManager *wm, struct wmWindow *win, in
* (see in-line code comments for details).
*/
uint *WM_window_pixels_read_offscreen(struct bContext *C, struct wmWindow *win, int r_size[2]);
bool WM_window_pixels_read_sample_offscreen(struct bContext *C,
struct wmWindow *win,
const int pos[2],
float r_col[3]);
/**
* Support for native pixel size

View File

@ -983,7 +983,7 @@ static void wm_drag_draw_default(bContext *C, wmWindow *win, wmDrag *drag, const
}
wm_drag_draw_item_name(drag, UNPACK2(xy_tmp));
/* Operator name with roundbox. */
/* Operator name with round-box. */
wm_drag_draw_tooltip(C, win, drag, xy);
}

View File

@ -1238,11 +1238,43 @@ uint *WM_window_pixels_read_offscreen(bContext *C, wmWindow *win, int r_size[2])
GPU_offscreen_bind(offscreen, false);
wm_draw_window_onscreen(C, win, -1);
GPU_offscreen_unbind(offscreen, false);
GPU_offscreen_read_pixels(offscreen, GPU_DATA_UBYTE, rect);
GPU_offscreen_read_color(offscreen, GPU_DATA_UBYTE, rect);
GPU_offscreen_free(offscreen);
return rect;
}
bool WM_window_pixels_read_sample_offscreen(bContext *C,
wmWindow *win,
const int pos[2],
float r_col[3])
{
/* A version of #WM_window_pixels_read_offscreen. */
const int size[2] = {WM_window_pixels_x(win), WM_window_pixels_y(win)};
zero_v3(r_col);
/* While this shouldn't happen, return in the case it does. */
BLI_assert((uint)pos[0] < (uint)size[0] && (uint)pos[1] < (uint)size[1]);
if (!((uint)pos[0] < (uint)size[0] && (uint)pos[1] < (uint)size[1])) {
return false;
}
GPUOffScreen *offscreen = GPU_offscreen_create(
size[0], size[1], false, GPU_RGBA8, GPU_TEXTURE_USAGE_SHADER_READ, NULL);
if (UNLIKELY(!offscreen)) {
return false;
}
float rect_pixel[4];
GPU_offscreen_bind(offscreen, false);
wm_draw_window_onscreen(C, win, -1);
GPU_offscreen_unbind(offscreen, false);
GPU_offscreen_read_color_region(offscreen, GPU_DATA_FLOAT, pos[0], pos[1], 1, 1, rect_pixel);
GPU_offscreen_free(offscreen);
copy_v3_v3(r_col, rect_pixel);
return true;
}
/** \} */
/* -------------------------------------------------------------------- */

View File

@ -1347,11 +1347,10 @@ static bool ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_pt
if (state != GHOST_kWindowStateMinimized) {
/*
* Ghost sometimes send size or move events when the window hasn't changed.
* One case of this is using compiz on linux. To alleviate the problem
* we ignore all such event here.
* One case of this is using COMPIZ on Linux.
* To alleviate the problem we ignore all such event here.
*
* It might be good to eventually do that at Ghost level, but that is for
* another time.
* It might be good to eventually do that at GHOST level, but that is for another time.
*/
if (wm_window_update_size_position(win)) {
const bScreen *screen = WM_window_get_active_screen(win);
@ -1850,6 +1849,12 @@ eWM_CapabilitiesFlag WM_capabilities_flag(void)
if (ghost_flag & GHOST_kCapabilityPrimaryClipboard) {
flag |= WM_CAPABILITY_PRIMARY_CLIPBOARD;
}
if (ghost_flag & GHOST_kCapabilityGPUReadFrontBuffer) {
flag |= WM_CAPABILITY_GPU_FRONT_BUFFER_READ;
}
if (ghost_flag & GHOST_kCapabilityClipboardImages) {
flag |= WM_CAPABILITY_CLIPBOARD_IMAGES;
}
return flag;
}
@ -2218,28 +2223,6 @@ wmWindow *WM_window_find_by_area(wmWindowManager *wm, const struct ScrArea *area
return NULL;
}
void WM_window_pixel_sample_read(const wmWindowManager *wm,
const wmWindow *win,
const int pos[2],
float r_col[3])
{
bool setup_context = wm->windrawable != win;
if (setup_context) {
GHOST_ActivateWindowDrawingContext(win->ghostwin);
GPU_context_active_set(win->gpuctx);
}
GPU_frontbuffer_read_pixels(pos[0], pos[1], 1, 1, 3, GPU_DATA_FLOAT, r_col);
if (setup_context) {
if (wm->windrawable) {
GHOST_ActivateWindowDrawingContext(wm->windrawable->ghostwin);
GPU_context_active_set(wm->windrawable->gpuctx);
}
}
}
/** \} */
/* -------------------------------------------------------------------- */
@ -2251,6 +2234,8 @@ void WM_window_pixel_sample_read(const wmWindowManager *wm,
uint *WM_window_pixels_read(wmWindowManager *wm, wmWindow *win, int r_size[2])
{
BLI_assert(WM_capabilities_flag() & WM_CAPABILITY_GPU_FRONT_BUFFER_READ);
/* WARNING: Reading from the front-buffer immediately after drawing may fail,
* for a slower but more reliable version of this function #WM_window_pixels_read_offscreen
* should be preferred. See it's comments for details on why it's needed, see also #98462. */
@ -2266,7 +2251,7 @@ uint *WM_window_pixels_read(wmWindowManager *wm, wmWindow *win, int r_size[2])
const uint rect_len = r_size[0] * r_size[1];
uint *rect = MEM_mallocN(sizeof(*rect) * rect_len, __func__);
GPU_frontbuffer_read_pixels(0, 0, r_size[0], r_size[1], 4, GPU_DATA_UBYTE, rect);
GPU_frontbuffer_read_color(0, 0, r_size[0], r_size[1], 4, GPU_DATA_UBYTE, rect);
if (setup_context) {
if (wm->windrawable) {
@ -2284,6 +2269,29 @@ uint *WM_window_pixels_read(wmWindowManager *wm, wmWindow *win, int r_size[2])
return (uint *)rect;
}
void WM_window_pixels_read_sample(const wmWindowManager *wm,
const wmWindow *win,
const int pos[2],
float r_col[3])
{
BLI_assert(WM_capabilities_flag() & WM_CAPABILITY_GPU_FRONT_BUFFER_READ);
bool setup_context = wm->windrawable != win;
if (setup_context) {
GHOST_ActivateWindowDrawingContext(win->ghostwin);
GPU_context_active_set(win->gpuctx);
}
GPU_frontbuffer_read_color(pos[0], pos[1], 1, 1, 3, GPU_DATA_FLOAT, r_col);
if (setup_context) {
if (wm->windrawable) {
GHOST_ActivateWindowDrawingContext(wm->windrawable->ghostwin);
GPU_context_active_set(wm->windrawable->gpuctx);
}
}
}
/** \} */
/* -------------------------------------------------------------------- */

View File

@ -58,6 +58,7 @@ PATHS_EXCLUDE = set(
"tools/utils/git_log.py",
"tools/utils/git_log_review_commits.py",
"tools/utils/git_log_review_commits_advanced.py",
"tools/utils/gitea_inactive_developers.py",
"tools/utils/make_cursor_gui.py",
"tools/utils/make_gl_stipple_from_xpm.py",
"tools/utils/make_shape_2d_from_blend.py",

View File

@ -83,6 +83,7 @@ dict_custom = {
"deduplication",
"defocus",
"degeneracies",
"deletable",
"deleter",
"denoised",
"denoiser",
@ -187,6 +188,7 @@ dict_custom = {
"orthonormalized",
"overridable",
"paddings",
"paintable",
"pannable",
"parallelepiped",
"parallelize",

View File

@ -31,7 +31,9 @@ from typing import (
Tuple,
Type,
TypeVar,
Union,
)
from requests.structures import CaseInsensitiveDict
logger = logging.getLogger(__file__)
@ -43,7 +45,7 @@ class TeamMember():
full_name: str
last_login: datetime.datetime
def __str__(self):
def __str__(self) -> str:
return "{id};{login};{full_name};{last_login};{url}\n".format(
id=self.id,
login=self.login,
@ -64,22 +66,25 @@ retry: Callable[[F], F] = retry_decorator(
def assert_cast(typ: Type[T], obj: object) -> T:
assert isinstance(obj, typ), f'object is not of type {typ}: {obj}'
return cast(T, obj)
# NOTE: MYPY warns the cast is redundant, we might consider removing it.
return cast(T, obj) # type: ignore
def get_date_object(date_string: str) -> datetime.datetime:
return iso8601.parse_date(date_string)
result = iso8601.parse_date(date_string)
assert isinstance(result, datetime.datetime)
return result
results_per_page = 25
def get_next_page(headers: Dict, page: int) -> int:
def get_next_page(headers: CaseInsensitiveDict[str], page: Optional[Page]) -> Optional[Page]:
"""
Parse the header looking for reference to next.
"""
total_count = int(assert_cast(str, headers.get('X-Total-Count')))
next_page = page + 1 if page else 1
next_page = Page(page + 1 if page else 1)
if next_page * results_per_page > total_count:
return None
@ -105,7 +110,7 @@ def fetch_single(
'Authorization': 'token ' + api_token,
}
params = {
params: Dict[str, Union[str, int]] = {
'limit': results_per_page,
**data,
}
@ -119,7 +124,7 @@ def fetch_single(
response_json = response.json()
next_page = get_next_page(response.headers, page)
return response_json, None if next_page is None else Page(next_page)
return response_json, None if next_page is None else next_page
def fetch_all(
@ -226,7 +231,7 @@ api_url = yarl.URL(gitea_domain + 'api/v1/')
organization_name = "blender"
def main():
def main() -> None:
for team_name in teams:
logger.warning(team_name)
members = fetch_team_members(