forked from bartvdbraak/blender
Merge branch 'master' into blender2.8
This commit is contained in:
commit
346619159a
@ -454,7 +454,8 @@ endif()
|
||||
if(WITH_OPENSUBDIV OR WITH_CYCLES_OPENSUBDIV)
|
||||
set(OPENSUBDIV_INCLUDE_DIR ${LIBDIR}/opensubdiv/include)
|
||||
set(OPENSUBDIV_LIBPATH ${LIBDIR}/opensubdiv/lib)
|
||||
set(OPENSUBDIV_LIBRARIES optimized ${OPENSUBDIV_LIBPATH}/osdCPU.lib
|
||||
set(OPENSUBDIV_LIBRARIES
|
||||
optimized ${OPENSUBDIV_LIBPATH}/osdCPU.lib
|
||||
optimized ${OPENSUBDIV_LIBPATH}/osdGPU.lib
|
||||
debug ${OPENSUBDIV_LIBPATH}/osdCPU_d.lib
|
||||
debug ${OPENSUBDIV_LIBPATH}/osdGPU_d.lib
|
||||
@ -489,9 +490,9 @@ endif()
|
||||
blender_include_dirs_sys("${PTHREADS_INCLUDE_DIRS}")
|
||||
|
||||
#find signtool
|
||||
SET(ProgramFilesX86_NAME "ProgramFiles(x86)") #env dislikes the ( )
|
||||
set(ProgramFilesX86_NAME "ProgramFiles(x86)") #env dislikes the ( )
|
||||
find_program(SIGNTOOL_EXE signtool
|
||||
HINTS
|
||||
HINTS
|
||||
"$ENV{${ProgramFilesX86_NAME}}/Windows Kits/10/bin/x86/"
|
||||
"$ENV{ProgramFiles}/Windows Kits/10/bin/x86/"
|
||||
"$ENV{${ProgramFilesX86_NAME}}/Windows Kits/8.1/bin/x86/"
|
||||
|
@ -130,10 +130,22 @@ string device_opencl_capabilities(void)
|
||||
opencl_assert(func(id, what, sizeof(data), &data, NULL)); \
|
||||
result += string_printf("%s: %s\n", name, data); \
|
||||
} while(false)
|
||||
#define APPEND_STRING_EXTENSION_INFO(func, id, name, what) \
|
||||
do { \
|
||||
char data[1024] = "\0"; \
|
||||
size_t length = 0; \
|
||||
if(func(id, what, sizeof(data), &data, &length) == CL_SUCCESS) { \
|
||||
if(length != 0 && data[0] != '\0') { \
|
||||
result += string_printf("%s: %s\n", name, data); \
|
||||
} \
|
||||
} \
|
||||
} while(false)
|
||||
#define APPEND_PLATFORM_STRING_INFO(id, name, what) \
|
||||
APPEND_STRING_INFO(clGetPlatformInfo, id, "\tPlatform " name, what)
|
||||
#define APPEND_DEVICE_STRING_INFO(id, name, what) \
|
||||
APPEND_STRING_INFO(clGetDeviceInfo, id, "\t\t\tDevice " name, what)
|
||||
#define APPEND_DEVICE_STRING_EXTENSION_INFO(id, name, what) \
|
||||
APPEND_STRING_EXTENSION_INFO(clGetDeviceInfo, id, "\t\t\tDevice " name, what)
|
||||
|
||||
vector<cl_device_id> device_ids;
|
||||
for(cl_uint platform = 0; platform < num_platforms; ++platform) {
|
||||
@ -167,6 +179,7 @@ string device_opencl_capabilities(void)
|
||||
result += string_printf("\t\tDevice: #%u\n", device);
|
||||
|
||||
APPEND_DEVICE_STRING_INFO(device_id, "Name", CL_DEVICE_NAME);
|
||||
APPEND_DEVICE_STRING_EXTENSION_INFO(device_id, "Board Name", CL_DEVICE_BOARD_NAME_AMD);
|
||||
APPEND_DEVICE_STRING_INFO(device_id, "Vendor", CL_DEVICE_VENDOR);
|
||||
APPEND_DEVICE_STRING_INFO(device_id, "OpenCL C Version", CL_DEVICE_OPENCL_C_VERSION);
|
||||
APPEND_DEVICE_STRING_INFO(device_id, "Profile", CL_DEVICE_PROFILE);
|
||||
|
@ -245,4 +245,41 @@ TEST(util_string_remove_trademark, both)
|
||||
EXPECT_EQ(str, "foo bar zzz");
|
||||
}
|
||||
|
||||
TEST(util_string_remove_trademark, both_space)
|
||||
{
|
||||
string str = string_remove_trademark("foo bar(TM) (R) zzz");
|
||||
EXPECT_EQ(str, "foo bar zzz");
|
||||
}
|
||||
|
||||
TEST(util_string_remove_trademark, both_space_around)
|
||||
{
|
||||
string str = string_remove_trademark("foo bar (TM) (R) zzz");
|
||||
EXPECT_EQ(str, "foo bar zzz");
|
||||
}
|
||||
|
||||
TEST(util_string_remove_trademark, trademark_space_suffix)
|
||||
{
|
||||
string str = string_remove_trademark("foo bar (TM)");
|
||||
EXPECT_EQ(str, "foo bar");
|
||||
}
|
||||
|
||||
TEST(util_string_remove_trademark, trademark_space_middle)
|
||||
{
|
||||
string str = string_remove_trademark("foo bar (TM) baz");
|
||||
EXPECT_EQ(str, "foo bar baz");
|
||||
}
|
||||
|
||||
|
||||
TEST(util_string_remove_trademark, r_space_suffix)
|
||||
{
|
||||
string str = string_remove_trademark("foo bar (R)");
|
||||
EXPECT_EQ(str, "foo bar");
|
||||
}
|
||||
|
||||
TEST(util_string_remove_trademark, r_space_middle)
|
||||
{
|
||||
string str = string_remove_trademark("foo bar (R) baz");
|
||||
EXPECT_EQ(str, "foo bar baz");
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@ -148,6 +148,12 @@ void string_replace(string& haystack, const string& needle, const string& other)
|
||||
string string_remove_trademark(const string &s)
|
||||
{
|
||||
string result = s;
|
||||
|
||||
/* Special case, so we don;t leave sequential spaces behind. */
|
||||
/* TODO(sergey): Consider using regex perhaps? */
|
||||
string_replace(result, " (TM)", "");
|
||||
string_replace(result, " (R)", "");
|
||||
|
||||
string_replace(result, "(TM)", "");
|
||||
string_replace(result, "(R)", "");
|
||||
|
||||
|
@ -1741,6 +1741,8 @@ static BMOpDefine bmo_bevel_def = {
|
||||
},
|
||||
/* slots_out */
|
||||
{{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */
|
||||
{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* output edges */
|
||||
{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */
|
||||
{{'\0'}},
|
||||
},
|
||||
|
||||
|
@ -1515,16 +1515,30 @@ float BM_loop_calc_face_angle(const BMLoop *l)
|
||||
*/
|
||||
void BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3])
|
||||
{
|
||||
if (normal_tri_v3(r_normal,
|
||||
l->prev->v->co,
|
||||
l->v->co,
|
||||
l->next->v->co) != 0.0f)
|
||||
{
|
||||
/* pass */
|
||||
#define FEPSILON 1e-5f
|
||||
|
||||
/* Note: we cannot use result of normal_tri_v3 here to detect colinear vectors (vertex on a straight line)
|
||||
* from zero value, because it does not normalize both vectors before making crossproduct.
|
||||
* Instead of adding two costly normalize computations, just check ourselves for colinear case. */
|
||||
/* Note: FEPSILON might need some finer tweaking at some point? Seems to be working OK for now though. */
|
||||
float v1[3], v2[3], v_tmp[3];
|
||||
sub_v3_v3v3(v1, l->prev->v->co, l->v->co);
|
||||
sub_v3_v3v3(v2, l->next->v->co, l->v->co);
|
||||
|
||||
const float fac = (v2[0] == 0.0f) ? ((v2[1] == 0.0f) ? ((v2[2] == 0.0f) ? 0.0f : v1[2] / v2[2]) : v1[1] / v2[1]) : v1[0] / v2[0];
|
||||
|
||||
mul_v3_v3fl(v_tmp, v2, fac);
|
||||
sub_v3_v3(v_tmp, v1);
|
||||
if (fac != 0.0f && !is_zero_v3(v1) && len_manhattan_v3(v_tmp) > FEPSILON) {
|
||||
/* Not co-linear, we can compute crossproduct and normalize it into normal. */
|
||||
cross_v3_v3v3(r_normal, v1, v2);
|
||||
normalize_v3(r_normal);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(r_normal, l->f->no);
|
||||
}
|
||||
|
||||
#undef FEPSILON
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -66,5 +66,7 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op)
|
||||
BM_mesh_bevel(bm, offset, offset_type, seg, profile, vonly, false, clamp_overlap, NULL, -1, material, loop_slide);
|
||||
|
||||
BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces.out", BM_FACE, BM_ELEM_TAG);
|
||||
BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "edges.out", BM_EDGE, BM_ELEM_TAG);
|
||||
BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "verts.out", BM_VERT, BM_ELEM_TAG);
|
||||
}
|
||||
}
|
||||
|
@ -205,6 +205,29 @@ static int bev_debug_flags = 0;
|
||||
#define DEBUG_OLD_PROJ_TO_PERP_PLANE (bev_debug_flags & 2)
|
||||
#define DEBUG_OLD_FLAT_MID (bev_debug_flags & 4)
|
||||
|
||||
/* this flag values will get set on geom we want to return in 'out' slots for edges and verts */
|
||||
#define EDGE_OUT 4
|
||||
#define VERT_OUT 8
|
||||
|
||||
/* If we're called from the modifier, tool flags aren't available, but don't need output geometry */
|
||||
static void flag_out_edge(BMesh *bm, BMEdge *bme)
|
||||
{
|
||||
if (bm->use_toolflags)
|
||||
BMO_edge_flag_enable(bm, bme, EDGE_OUT);
|
||||
}
|
||||
|
||||
static void flag_out_vert(BMesh *bm, BMVert *bmv)
|
||||
{
|
||||
if (bm->use_toolflags)
|
||||
BMO_vert_flag_enable(bm, bmv, VERT_OUT);
|
||||
}
|
||||
|
||||
static void disable_flag_out_edge(BMesh *bm, BMEdge *bme)
|
||||
{
|
||||
if (bm->use_toolflags)
|
||||
BMO_edge_flag_disable(bm, bme, EDGE_OUT);
|
||||
}
|
||||
|
||||
/* Are d1 and d2 parallel or nearly so? */
|
||||
static bool nearly_parallel(const float d1[3], const float d2[3])
|
||||
{
|
||||
@ -262,6 +285,7 @@ static void create_mesh_bmvert(BMesh *bm, VMesh *vm, int i, int j, int k, BMVert
|
||||
NewVert *nv = mesh_vert(vm, i, j, k);
|
||||
nv->v = BM_vert_create(bm, nv->co, eg, BM_CREATE_NOP);
|
||||
BM_elem_flag_disable(nv->v, BM_ELEM_TAG);
|
||||
flag_out_vert(bm, nv->v);
|
||||
}
|
||||
|
||||
static void copy_mesh_vert(
|
||||
@ -504,9 +528,12 @@ static BMFace *bev_create_ngon(
|
||||
}
|
||||
|
||||
/* not essential for bevels own internal logic,
|
||||
* this is done so the operator can select newly created faces */
|
||||
* this is done so the operator can select newly created geometry */
|
||||
if (f) {
|
||||
BM_elem_flag_enable(f, BM_ELEM_TAG);
|
||||
BM_ITER_ELEM(bme, &iter, f, BM_EDGES_OF_FACE) {
|
||||
flag_out_edge(bm, bme);
|
||||
}
|
||||
}
|
||||
|
||||
if (mat_nr >= 0)
|
||||
@ -3213,6 +3240,7 @@ static void bevel_build_trifan(BevelParams *bp, BMesh *bm, BevVert *bv)
|
||||
BMFace *f_new;
|
||||
BLI_assert(v_fan == l_fan->v);
|
||||
f_new = BM_face_split(bm, f, l_fan, l_fan->next->next, &l_new, NULL, false);
|
||||
flag_out_edge(bm, l_new->e);
|
||||
|
||||
if (f_new->len > f->len) {
|
||||
f = f_new;
|
||||
@ -3259,6 +3287,7 @@ static void bevel_build_quadstrip(BevelParams *bp, BMesh *bm, BevVert *bv)
|
||||
else {
|
||||
BM_face_split(bm, f, l_a, l_b, &l_new, NULL, false);
|
||||
f = l_new->f;
|
||||
flag_out_edge(bm, l_new->e);
|
||||
|
||||
/* walk around the new face to get the next verts to split */
|
||||
l_a = l_new->prev;
|
||||
@ -3278,7 +3307,7 @@ static void bevel_vert_two_edges(BevelParams *bp, BMesh *bm, BevVert *bv)
|
||||
{
|
||||
VMesh *vm = bv->vmesh;
|
||||
BMVert *v1, *v2;
|
||||
BMEdge *e_eg;
|
||||
BMEdge *e_eg, *bme;
|
||||
Profile *pro;
|
||||
float co[3];
|
||||
BoundVert *bndv;
|
||||
@ -3320,7 +3349,9 @@ static void bevel_vert_two_edges(BevelParams *bp, BMesh *bm, BevVert *bv)
|
||||
v1 = mesh_vert(vm, 0, 0, k)->v;
|
||||
v2 = mesh_vert(vm, 0, 0, k + 1)->v;
|
||||
BLI_assert(v1 != NULL && v2 != NULL);
|
||||
BM_edge_create(bm, v1, v2, e_eg, BM_CREATE_NO_DOUBLE);
|
||||
bme = BM_edge_create(bm, v1, v2, e_eg, BM_CREATE_NO_DOUBLE);
|
||||
if (bme)
|
||||
flag_out_edge(bm, bme);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3901,7 +3932,7 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
|
||||
/* Face f has at least one beveled vertex. Rebuild f */
|
||||
static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f)
|
||||
{
|
||||
BMIter liter;
|
||||
BMIter liter, eiter, fiter;
|
||||
BMLoop *l, *lprev;
|
||||
BevVert *bv;
|
||||
BoundVert *v, *vstart, *vend;
|
||||
@ -3909,10 +3940,10 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f)
|
||||
VMesh *vm;
|
||||
int i, k, n;
|
||||
bool do_rebuild = false;
|
||||
bool go_ccw, corner3special;
|
||||
bool go_ccw, corner3special, keep;
|
||||
BMVert *bmv;
|
||||
BMEdge *bme, *bme_new, *bme_prev;
|
||||
BMFace *f_new;
|
||||
BMFace *f_new, *f_other;
|
||||
BMVert **vv = NULL;
|
||||
BMVert **vv_fix = NULL;
|
||||
BMEdge **ee = NULL;
|
||||
@ -4050,9 +4081,21 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f)
|
||||
}
|
||||
}
|
||||
|
||||
/* don't select newly created boundary faces... */
|
||||
/* don't select newly or return created boundary faces... */
|
||||
if (f_new) {
|
||||
BM_elem_flag_disable(f_new, BM_ELEM_TAG);
|
||||
/* Also don't want new edges that aren't part of a new bevel face */
|
||||
BM_ITER_ELEM(bme, &eiter, f_new, BM_EDGES_OF_FACE) {
|
||||
keep = false;
|
||||
BM_ITER_ELEM(f_other, &fiter, bme, BM_FACES_OF_EDGE) {
|
||||
if (BM_elem_flag_test(f_other, BM_ELEM_TAG)) {
|
||||
keep = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!keep)
|
||||
disable_flag_out_edge(bm, bme);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -4134,9 +4177,10 @@ static void bevel_reattach_wires(BMesh *bm, BevelParams *bp, BMVert *v)
|
||||
}
|
||||
}
|
||||
} while ((bndv = bndv->next) != bv->vmesh->boundstart);
|
||||
if (vclosest)
|
||||
if (vclosest) {
|
||||
BM_edge_create(bm, vclosest, votherclosest, e, BM_CREATE_NO_DOUBLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void bev_merge_end_uvs(BMesh *bm, BevVert *bv, EdgeHalf *e)
|
||||
@ -4539,9 +4583,9 @@ static float bevel_limit_offset(BMesh *bm, BevelParams *bp)
|
||||
/**
|
||||
* - Currently only bevels BM_ELEM_TAG'd verts and edges.
|
||||
*
|
||||
* - Newly created faces are BM_ELEM_TAG'd too,
|
||||
* the caller needs to ensure this is cleared before calling
|
||||
* if its going to use this face tag.
|
||||
* - Newly created faces, edges, and verts are BM_ELEM_TAG'd too,
|
||||
* the caller needs to ensure these are cleared before calling
|
||||
* if its going to use this tag.
|
||||
*
|
||||
* - If limit_offset is set, adjusts offset down if necessary
|
||||
* to avoid geometry collisions.
|
||||
@ -4633,6 +4677,20 @@ void BM_mesh_bevel(
|
||||
}
|
||||
}
|
||||
|
||||
/* When called from operator (as opposed to modifier), bm->use_toolflags
|
||||
* will be set, and we to transfer the oflags to BM_ELEM_TAGs */
|
||||
if (bm->use_toolflags) {
|
||||
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
|
||||
if (BMO_vert_flag_test(bm, v, VERT_OUT))
|
||||
BM_elem_flag_enable(v, BM_ELEM_TAG);
|
||||
}
|
||||
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
|
||||
if (BMO_edge_flag_test(bm, e, EDGE_OUT)) {
|
||||
BM_elem_flag_enable(e, BM_ELEM_TAG);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* primary free */
|
||||
BLI_ghash_free(bp.vert_hash, NULL, NULL);
|
||||
BLI_memarena_free(bp.mem_arena);
|
||||
|
@ -89,6 +89,7 @@ set(SRC
|
||||
intern/depsgraph_intern.h
|
||||
intern/depsgraph_types.h
|
||||
|
||||
util/deg_util_foreach.h
|
||||
util/deg_util_function.h
|
||||
)
|
||||
|
||||
|
@ -773,6 +773,9 @@ typedef struct tGPSB_CloneBrushData {
|
||||
|
||||
/* for "stamp" mode, the currently pasted brushes */
|
||||
bGPDstroke **new_strokes;
|
||||
|
||||
/* mapping from colors referenced per stroke, to the new colours in the "pasted" strokes */
|
||||
GHash *new_colors;
|
||||
} tGPSB_CloneBrushData;
|
||||
|
||||
/* Initialise "clone" brush data */
|
||||
@ -816,6 +819,11 @@ static void gp_brush_clone_init(bContext *C, tGP_BrushEditData *gso)
|
||||
if (1 /*gso->brush->mode == GP_EDITBRUSH_CLONE_MODE_STAMP*/) {
|
||||
data->new_strokes = MEM_callocN(sizeof(bGPDstroke *) * data->totitems, "cloned strokes ptr array");
|
||||
}
|
||||
|
||||
/* Init colormap for mapping between the pasted stroke's source colour(names)
|
||||
* and the final colours that will be used here instead...
|
||||
*/
|
||||
data->new_colors = gp_copybuf_validate_colormap(gso->gpd);
|
||||
}
|
||||
|
||||
/* Free custom data used for "clone" brush */
|
||||
@ -829,6 +837,12 @@ static void gp_brush_clone_free(tGP_BrushEditData *gso)
|
||||
data->new_strokes = NULL;
|
||||
}
|
||||
|
||||
/* free copybuf colormap */
|
||||
if (data->new_colors) {
|
||||
BLI_ghash_free(data->new_colors, NULL, NULL);
|
||||
data->new_colors = NULL;
|
||||
}
|
||||
|
||||
/* free the customdata itself */
|
||||
MEM_freeN(data);
|
||||
gso->customdata = NULL;
|
||||
@ -869,6 +883,13 @@ static void gp_brush_clone_add(bContext *C, tGP_BrushEditData *gso)
|
||||
new_stroke->next = new_stroke->prev = NULL;
|
||||
BLI_addtail(&gpf->strokes, new_stroke);
|
||||
|
||||
/* Fix color references */
|
||||
BLI_assert(new_stroke->colorname[0] != '\0');
|
||||
new_stroke->palcolor = BLI_ghash_lookup(data->new_colors, new_stroke->colorname);
|
||||
|
||||
BLI_assert(new_stroke->palcolor != NULL);
|
||||
BLI_strncpy(new_stroke->colorname, new_stroke->palcolor->info, sizeof(new_stroke->colorname));
|
||||
|
||||
/* Adjust all the stroke's points, so that the strokes
|
||||
* get pasted relative to where the cursor is now
|
||||
*/
|
||||
|
@ -38,8 +38,11 @@
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_string_utils.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BLT_translation.h"
|
||||
@ -335,11 +338,27 @@ void GPENCIL_OT_duplicate(wmOperatorType *ot)
|
||||
/* NOTE: is exposed within the editors/gpencil module so that other tools can use it too */
|
||||
ListBase gp_strokes_copypastebuf = {NULL, NULL};
|
||||
|
||||
/* Hash for hanging on to all the palette colors used by strokes in the buffer
|
||||
*
|
||||
* This is needed to prevent dangling and unsafe pointers when pasting across datablocks,
|
||||
* or after a color used by a stroke in the buffer gets deleted (via user action or undo).
|
||||
*/
|
||||
GHash *gp_strokes_copypastebuf_colors = NULL;
|
||||
|
||||
/* Free copy/paste buffer data */
|
||||
void ED_gpencil_strokes_copybuf_free(void)
|
||||
{
|
||||
bGPDstroke *gps, *gpsn;
|
||||
|
||||
/* Free the palettes buffer
|
||||
* NOTE: This is done before the strokes so that the name ptrs (keys) are still safe
|
||||
*/
|
||||
if (gp_strokes_copypastebuf_colors) {
|
||||
BLI_ghash_free(gp_strokes_copypastebuf_colors, NULL, MEM_freeN);
|
||||
gp_strokes_copypastebuf_colors = NULL;
|
||||
}
|
||||
|
||||
/* Free the stroke buffer */
|
||||
for (gps = gp_strokes_copypastebuf.first; gps; gps = gpsn) {
|
||||
gpsn = gps->next;
|
||||
|
||||
@ -352,6 +371,46 @@ void ED_gpencil_strokes_copybuf_free(void)
|
||||
gp_strokes_copypastebuf.first = gp_strokes_copypastebuf.last = NULL;
|
||||
}
|
||||
|
||||
/* Ensure that destination datablock has all the colours the pasted strokes need
|
||||
* Helper function for copy-pasting strokes
|
||||
*/
|
||||
GHash *gp_copybuf_validate_colormap(bGPdata *gpd)
|
||||
{
|
||||
GHash *new_colors = BLI_ghash_str_new("GPencil Paste Dst Colors");
|
||||
GHashIterator gh_iter;
|
||||
|
||||
/* If there's no active palette yet (i.e. new datablock), add one */
|
||||
bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd);
|
||||
if (palette == NULL) {
|
||||
palette = BKE_gpencil_palette_addnew(gpd, "Pasted Palette", true);
|
||||
}
|
||||
|
||||
/* For each color, figure out what to map to... */
|
||||
GHASH_ITER(gh_iter, gp_strokes_copypastebuf_colors) {
|
||||
bGPDpalettecolor *palcolor;
|
||||
char *name = BLI_ghashIterator_getKey(&gh_iter);
|
||||
|
||||
/* Look for existing color to map to */
|
||||
/* XXX: What to do if same name but different color? Behaviour here should depend on a property? */
|
||||
palcolor = BKE_gpencil_palettecolor_getbyname(palette, name);
|
||||
if (palcolor == NULL) {
|
||||
/* Doesn't Exist - Create new matching color for this palette */
|
||||
/* XXX: This still doesn't fix the pasting across file boundaries problem... */
|
||||
bGPDpalettecolor *src_color = BLI_ghashIterator_getValue(&gh_iter);
|
||||
|
||||
palcolor = MEM_dupallocN(src_color);
|
||||
BLI_addtail(&palette->colors, palcolor);
|
||||
|
||||
BLI_uniquename(&palette->colors, palcolor, DATA_("GP Color"), '.', offsetof(bGPDpalettecolor, info), sizeof(palcolor->info));
|
||||
}
|
||||
|
||||
/* Store this mapping (for use later when pasting) */
|
||||
BLI_ghash_insert(new_colors, name, palcolor);
|
||||
}
|
||||
|
||||
return new_colors;
|
||||
}
|
||||
|
||||
/* --------------------- */
|
||||
/* Copy selected strokes */
|
||||
|
||||
@ -413,7 +472,26 @@ static int gp_strokes_copy_exec(bContext *C, wmOperator *op)
|
||||
}
|
||||
CTX_DATA_END;
|
||||
|
||||
/* done - no updates needed */
|
||||
/* Build up hash of colors used in these strokes, making copies of these to protect against dangling pointers */
|
||||
if (gp_strokes_copypastebuf.first) {
|
||||
gp_strokes_copypastebuf_colors = BLI_ghash_str_new("GPencil CopyBuf Colors");
|
||||
|
||||
for (bGPDstroke *gps = gp_strokes_copypastebuf.first; gps; gps = gps->next) {
|
||||
if (ED_gpencil_stroke_can_use(C, gps)) {
|
||||
if (BLI_ghash_haskey(gp_strokes_copypastebuf_colors, gps->colorname) == false) {
|
||||
bGPDpalettecolor *color = MEM_dupallocN(gps->palcolor);
|
||||
|
||||
BLI_ghash_insert(gp_strokes_copypastebuf_colors, gps->colorname, color);
|
||||
gps->palcolor = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* updates (to ensure operator buttons are refreshed, when used via hotkeys) */
|
||||
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, NULL); // XXX?
|
||||
|
||||
/* done */
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
@ -458,6 +536,7 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op)
|
||||
bGPDframe *gpf;
|
||||
|
||||
eGP_PasteMode type = RNA_enum_get(op->ptr, "type");
|
||||
GHash *new_colors;
|
||||
|
||||
/* check for various error conditions */
|
||||
if (gpd == NULL) {
|
||||
@ -515,6 +594,10 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op)
|
||||
}
|
||||
CTX_DATA_END;
|
||||
|
||||
/* Ensure that all the necessary colors exist */
|
||||
new_colors = gp_copybuf_validate_colormap(gpd);
|
||||
|
||||
/* Copy over the strokes from the buffer (and adjust the colors) */
|
||||
for (bGPDstroke *gps = gp_strokes_copypastebuf.first; gps; gps = gps->next) {
|
||||
if (ED_gpencil_stroke_can_use(C, gps)) {
|
||||
/* Need to verify if layer exists */
|
||||
@ -533,6 +616,7 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op)
|
||||
*/
|
||||
gpf = BKE_gpencil_layer_getframe(gpl, CFRA, true);
|
||||
if (gpf) {
|
||||
/* Create new stroke */
|
||||
bGPDstroke *new_stroke = MEM_dupallocN(gps);
|
||||
new_stroke->tmp_layerinfo[0] = '\0';
|
||||
|
||||
@ -543,10 +627,22 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op)
|
||||
|
||||
new_stroke->next = new_stroke->prev = NULL;
|
||||
BLI_addtail(&gpf->strokes, new_stroke);
|
||||
|
||||
/* Fix color references */
|
||||
BLI_assert(new_stroke->colorname[0] != '\0');
|
||||
new_stroke->palcolor = BLI_ghash_lookup(new_colors, new_stroke->colorname);
|
||||
|
||||
BLI_assert(new_stroke->palcolor != NULL);
|
||||
BLI_strncpy(new_stroke->colorname, new_stroke->palcolor->info, sizeof(new_stroke->colorname));
|
||||
|
||||
/*new_stroke->flag |= GP_STROKE_RECALC_COLOR; */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* free temp data */
|
||||
BLI_ghash_free(new_colors, NULL, NULL);
|
||||
|
||||
/* updates */
|
||||
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
|
||||
|
||||
|
@ -40,6 +40,8 @@ struct bGPdata;
|
||||
struct bGPDstroke;
|
||||
struct bGPDspoint;
|
||||
|
||||
struct GHash;
|
||||
|
||||
struct ARegion;
|
||||
struct View2D;
|
||||
struct wmOperatorType;
|
||||
@ -155,6 +157,9 @@ int gp_brush_crt_presets_poll(bContext *C);
|
||||
|
||||
extern ListBase gp_strokes_copypastebuf;
|
||||
|
||||
/* Build a map for converting between old colornames and destination-color-refs */
|
||||
struct GHash *gp_copybuf_validate_colormap(bGPdata *gpd);
|
||||
|
||||
/* Stroke Editing ------------------------------------ */
|
||||
|
||||
void gp_stroke_delete_tagged_points(bGPDframe *gpf, bGPDstroke *gps, bGPDstroke *next_stroke, int tag_flags);
|
||||
|
@ -1031,6 +1031,314 @@ static void rna_wmClipboard_set(PointerRNA *UNUSED(ptr), const char *value)
|
||||
}
|
||||
|
||||
#ifdef WITH_PYTHON
|
||||
|
||||
static int rna_operator_poll_cb(bContext *C, wmOperatorType *ot)
|
||||
{
|
||||
extern FunctionRNA rna_Operator_poll_func;
|
||||
|
||||
PointerRNA ptr;
|
||||
ParameterList list;
|
||||
FunctionRNA *func;
|
||||
void *ret;
|
||||
int visible;
|
||||
|
||||
RNA_pointer_create(NULL, ot->ext.srna, NULL, &ptr); /* dummy */
|
||||
func = &rna_Operator_poll_func; /* RNA_struct_find_function(&ptr, "poll"); */
|
||||
|
||||
RNA_parameter_list_create(&list, &ptr, func);
|
||||
RNA_parameter_set_lookup(&list, "context", &C);
|
||||
ot->ext.call(C, &ptr, func, &list);
|
||||
|
||||
RNA_parameter_get_lookup(&list, "visible", &ret);
|
||||
visible = *(int *)ret;
|
||||
|
||||
RNA_parameter_list_free(&list);
|
||||
|
||||
return visible;
|
||||
}
|
||||
|
||||
static int rna_operator_execute_cb(bContext *C, wmOperator *op)
|
||||
{
|
||||
extern FunctionRNA rna_Operator_execute_func;
|
||||
|
||||
PointerRNA opr;
|
||||
ParameterList list;
|
||||
FunctionRNA *func;
|
||||
void *ret;
|
||||
int result;
|
||||
|
||||
RNA_pointer_create(NULL, op->type->ext.srna, op, &opr);
|
||||
func = &rna_Operator_execute_func; /* RNA_struct_find_function(&opr, "execute"); */
|
||||
|
||||
RNA_parameter_list_create(&list, &opr, func);
|
||||
RNA_parameter_set_lookup(&list, "context", &C);
|
||||
op->type->ext.call(C, &opr, func, &list);
|
||||
|
||||
RNA_parameter_get_lookup(&list, "result", &ret);
|
||||
result = *(int *)ret;
|
||||
|
||||
RNA_parameter_list_free(&list);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* same as execute() but no return value */
|
||||
static bool rna_operator_check_cb(bContext *C, wmOperator *op)
|
||||
{
|
||||
extern FunctionRNA rna_Operator_check_func;
|
||||
|
||||
PointerRNA opr;
|
||||
ParameterList list;
|
||||
FunctionRNA *func;
|
||||
void *ret;
|
||||
bool result;
|
||||
|
||||
RNA_pointer_create(NULL, op->type->ext.srna, op, &opr);
|
||||
func = &rna_Operator_check_func; /* RNA_struct_find_function(&opr, "check"); */
|
||||
|
||||
RNA_parameter_list_create(&list, &opr, func);
|
||||
RNA_parameter_set_lookup(&list, "context", &C);
|
||||
op->type->ext.call(C, &opr, func, &list);
|
||||
|
||||
RNA_parameter_get_lookup(&list, "result", &ret);
|
||||
result = (*(int *)ret) != 0;
|
||||
|
||||
RNA_parameter_list_free(&list);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int rna_operator_invoke_cb(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
extern FunctionRNA rna_Operator_invoke_func;
|
||||
|
||||
PointerRNA opr;
|
||||
ParameterList list;
|
||||
FunctionRNA *func;
|
||||
void *ret;
|
||||
int result;
|
||||
|
||||
RNA_pointer_create(NULL, op->type->ext.srna, op, &opr);
|
||||
func = &rna_Operator_invoke_func; /* RNA_struct_find_function(&opr, "invoke"); */
|
||||
|
||||
RNA_parameter_list_create(&list, &opr, func);
|
||||
RNA_parameter_set_lookup(&list, "context", &C);
|
||||
RNA_parameter_set_lookup(&list, "event", &event);
|
||||
op->type->ext.call(C, &opr, func, &list);
|
||||
|
||||
RNA_parameter_get_lookup(&list, "result", &ret);
|
||||
result = *(int *)ret;
|
||||
|
||||
RNA_parameter_list_free(&list);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* same as invoke */
|
||||
static int rna_operator_modal_cb(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
extern FunctionRNA rna_Operator_modal_func;
|
||||
|
||||
PointerRNA opr;
|
||||
ParameterList list;
|
||||
FunctionRNA *func;
|
||||
void *ret;
|
||||
int result;
|
||||
|
||||
RNA_pointer_create(NULL, op->type->ext.srna, op, &opr);
|
||||
func = &rna_Operator_modal_func; /* RNA_struct_find_function(&opr, "modal"); */
|
||||
|
||||
RNA_parameter_list_create(&list, &opr, func);
|
||||
RNA_parameter_set_lookup(&list, "context", &C);
|
||||
RNA_parameter_set_lookup(&list, "event", &event);
|
||||
op->type->ext.call(C, &opr, func, &list);
|
||||
|
||||
RNA_parameter_get_lookup(&list, "result", &ret);
|
||||
result = *(int *)ret;
|
||||
|
||||
RNA_parameter_list_free(&list);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void rna_operator_draw_cb(bContext *C, wmOperator *op)
|
||||
{
|
||||
extern FunctionRNA rna_Operator_draw_func;
|
||||
|
||||
PointerRNA opr;
|
||||
ParameterList list;
|
||||
FunctionRNA *func;
|
||||
|
||||
RNA_pointer_create(NULL, op->type->ext.srna, op, &opr);
|
||||
func = &rna_Operator_draw_func; /* RNA_struct_find_function(&opr, "draw"); */
|
||||
|
||||
RNA_parameter_list_create(&list, &opr, func);
|
||||
RNA_parameter_set_lookup(&list, "context", &C);
|
||||
op->type->ext.call(C, &opr, func, &list);
|
||||
|
||||
RNA_parameter_list_free(&list);
|
||||
}
|
||||
|
||||
/* same as exec(), but call cancel */
|
||||
static void rna_operator_cancel_cb(bContext *C, wmOperator *op)
|
||||
{
|
||||
extern FunctionRNA rna_Operator_cancel_func;
|
||||
|
||||
PointerRNA opr;
|
||||
ParameterList list;
|
||||
FunctionRNA *func;
|
||||
|
||||
RNA_pointer_create(NULL, op->type->ext.srna, op, &opr);
|
||||
func = &rna_Operator_cancel_func; /* RNA_struct_find_function(&opr, "cancel"); */
|
||||
|
||||
RNA_parameter_list_create(&list, &opr, func);
|
||||
RNA_parameter_set_lookup(&list, "context", &C);
|
||||
op->type->ext.call(C, &opr, func, &list);
|
||||
|
||||
RNA_parameter_list_free(&list);
|
||||
}
|
||||
|
||||
static void rna_Operator_unregister(struct Main *bmain, StructRNA *type);
|
||||
|
||||
/* bpy_operator_wrap.c */
|
||||
extern void BPY_RNA_operator_wrapper(wmOperatorType *ot, void *userdata);
|
||||
extern void BPY_RNA_operator_macro_wrapper(wmOperatorType *ot, void *userdata);
|
||||
|
||||
static StructRNA *rna_Operator_register(
|
||||
Main *bmain, ReportList *reports, void *data, const char *identifier,
|
||||
StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
|
||||
{
|
||||
wmOperatorType dummyot = {NULL};
|
||||
wmOperator dummyop = {NULL};
|
||||
PointerRNA dummyotr;
|
||||
int have_function[7];
|
||||
|
||||
struct {
|
||||
char idname[OP_MAX_TYPENAME];
|
||||
char name[OP_MAX_TYPENAME];
|
||||
char descr[RNA_DYN_DESCR_MAX];
|
||||
char ctxt[RNA_DYN_DESCR_MAX];
|
||||
char undo_group[OP_MAX_TYPENAME];
|
||||
} temp_buffers;
|
||||
|
||||
/* setup dummy operator & operator type to store static properties in */
|
||||
dummyop.type = &dummyot;
|
||||
dummyot.idname = temp_buffers.idname; /* only assigne the pointer, string is NULL'd */
|
||||
dummyot.name = temp_buffers.name; /* only assigne the pointer, string is NULL'd */
|
||||
dummyot.description = temp_buffers.descr; /* only assigne the pointer, string is NULL'd */
|
||||
dummyot.translation_context = temp_buffers.ctxt; /* only assigne the pointer, string is NULL'd */
|
||||
dummyot.undo_group = temp_buffers.undo_group; /* only assigne the pointer, string is NULL'd */
|
||||
RNA_pointer_create(NULL, &RNA_Operator, &dummyop, &dummyotr);
|
||||
|
||||
/* clear in case they are left unset */
|
||||
temp_buffers.idname[0] = temp_buffers.name[0] = temp_buffers.descr[0] = temp_buffers.undo_group[0] = '\0';
|
||||
/* We have to set default op context! */
|
||||
strcpy(temp_buffers.ctxt, BLT_I18NCONTEXT_OPERATOR_DEFAULT);
|
||||
|
||||
/* validate the python class */
|
||||
if (validate(&dummyotr, data, have_function) != 0)
|
||||
return NULL;
|
||||
|
||||
{ /* convert foo.bar to FOO_OT_bar
|
||||
* allocate the description and the idname in 1 go */
|
||||
|
||||
/* inconveniently long name sanity check */
|
||||
{
|
||||
char *ch = temp_buffers.idname;
|
||||
int i;
|
||||
int dot = 0;
|
||||
for (i = 0; *ch; i++) {
|
||||
if ((*ch >= 'a' && *ch <= 'z') || (*ch >= '0' && *ch <= '9') || *ch == '_') {
|
||||
/* pass */
|
||||
}
|
||||
else if (*ch == '.') {
|
||||
dot++;
|
||||
}
|
||||
else {
|
||||
BKE_reportf(reports, RPT_ERROR,
|
||||
"Registering operator class: '%s', invalid bl_idname '%s', at position %d",
|
||||
identifier, temp_buffers.idname, i);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ch++;
|
||||
}
|
||||
|
||||
if (i > ((int)sizeof(dummyop.idname)) - 3) {
|
||||
BKE_reportf(reports, RPT_ERROR, "Registering operator class: '%s', invalid bl_idname '%s', "
|
||||
"is too long, maximum length is %d", identifier, temp_buffers.idname,
|
||||
(int)sizeof(dummyop.idname) - 3);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (dot != 1) {
|
||||
BKE_reportf(reports, RPT_ERROR,
|
||||
"Registering operator class: '%s', invalid bl_idname '%s', must contain 1 '.' character",
|
||||
identifier, temp_buffers.idname);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
/* end sanity check */
|
||||
|
||||
{
|
||||
const uint idname_len = strlen(temp_buffers.idname) + 4;
|
||||
const uint name_len = strlen(temp_buffers.name) + 1;
|
||||
const uint desc_len = strlen(temp_buffers.descr) + 1;
|
||||
const uint ctxt_len = strlen(temp_buffers.ctxt) + 1;
|
||||
const uint undo_group_len = strlen(temp_buffers.undo_group) + 1;
|
||||
/* 2 terminators and 3 to convert a.b -> A_OT_b */
|
||||
char *ch = MEM_mallocN(
|
||||
sizeof(char) * (idname_len + name_len + desc_len + ctxt_len + undo_group_len), __func__);
|
||||
WM_operator_bl_idname(ch, temp_buffers.idname); /* convert the idname from python */
|
||||
dummyot.idname = ch;
|
||||
ch += idname_len;
|
||||
memcpy(ch, temp_buffers.name, name_len);
|
||||
dummyot.name = ch;
|
||||
ch += name_len;
|
||||
memcpy(ch, temp_buffers.descr, desc_len);
|
||||
dummyot.description = ch;
|
||||
ch += desc_len;
|
||||
memcpy(ch, temp_buffers.ctxt, ctxt_len);
|
||||
dummyot.translation_context = ch;
|
||||
ch += ctxt_len;
|
||||
memcpy(ch, temp_buffers.undo_group, undo_group_len);
|
||||
dummyot.undo_group = ch;
|
||||
}
|
||||
}
|
||||
|
||||
/* check if we have registered this operator type before, and remove it */
|
||||
{
|
||||
wmOperatorType *ot = WM_operatortype_find(dummyot.idname, true);
|
||||
if (ot && ot->ext.srna)
|
||||
rna_Operator_unregister(bmain, ot->ext.srna);
|
||||
}
|
||||
|
||||
/* XXX, this doubles up with the operator name [#29666]
|
||||
* for now just remove from dir(bpy.types) */
|
||||
|
||||
/* create a new operator type */
|
||||
dummyot.ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, dummyot.idname, &RNA_Operator);
|
||||
RNA_def_struct_flag(dummyot.ext.srna, STRUCT_NO_IDPROPERTIES); /* operator properties are registered separately */
|
||||
RNA_def_struct_translation_context(dummyot.ext.srna, dummyot.translation_context);
|
||||
dummyot.ext.data = data;
|
||||
dummyot.ext.call = call;
|
||||
dummyot.ext.free = free;
|
||||
|
||||
dummyot.pyop_poll = (have_function[0]) ? rna_operator_poll_cb : NULL;
|
||||
dummyot.exec = (have_function[1]) ? rna_operator_execute_cb : NULL;
|
||||
dummyot.check = (have_function[2]) ? rna_operator_check_cb : NULL;
|
||||
dummyot.invoke = (have_function[3]) ? rna_operator_invoke_cb : NULL;
|
||||
dummyot.modal = (have_function[4]) ? rna_operator_modal_cb : NULL;
|
||||
dummyot.ui = (have_function[5]) ? rna_operator_draw_cb : NULL;
|
||||
dummyot.cancel = (have_function[6]) ? rna_operator_cancel_cb : NULL;
|
||||
WM_operatortype_append_ptr(BPY_RNA_operator_wrapper, (void *)&dummyot);
|
||||
|
||||
/* update while blender is running */
|
||||
WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL);
|
||||
|
||||
return dummyot.ext.srna;
|
||||
}
|
||||
|
||||
static void rna_Operator_unregister(struct Main *bmain, StructRNA *type)
|
||||
{
|
||||
const char *idname;
|
||||
@ -1059,313 +1367,14 @@ static void rna_Operator_unregister(struct Main *bmain, StructRNA *type)
|
||||
RNA_struct_free(&BLENDER_RNA, type);
|
||||
}
|
||||
|
||||
static int operator_poll(bContext *C, wmOperatorType *ot)
|
||||
{
|
||||
extern FunctionRNA rna_Operator_poll_func;
|
||||
|
||||
PointerRNA ptr;
|
||||
ParameterList list;
|
||||
FunctionRNA *func;
|
||||
void *ret;
|
||||
int visible;
|
||||
|
||||
RNA_pointer_create(NULL, ot->ext.srna, NULL, &ptr); /* dummy */
|
||||
func = &rna_Operator_poll_func; /* RNA_struct_find_function(&ptr, "poll"); */
|
||||
|
||||
RNA_parameter_list_create(&list, &ptr, func);
|
||||
RNA_parameter_set_lookup(&list, "context", &C);
|
||||
ot->ext.call(C, &ptr, func, &list);
|
||||
|
||||
RNA_parameter_get_lookup(&list, "visible", &ret);
|
||||
visible = *(int *)ret;
|
||||
|
||||
RNA_parameter_list_free(&list);
|
||||
|
||||
return visible;
|
||||
}
|
||||
|
||||
static int operator_execute(bContext *C, wmOperator *op)
|
||||
{
|
||||
extern FunctionRNA rna_Operator_execute_func;
|
||||
|
||||
PointerRNA opr;
|
||||
ParameterList list;
|
||||
FunctionRNA *func;
|
||||
void *ret;
|
||||
int result;
|
||||
|
||||
RNA_pointer_create(NULL, op->type->ext.srna, op, &opr);
|
||||
func = &rna_Operator_execute_func; /* RNA_struct_find_function(&opr, "execute"); */
|
||||
|
||||
RNA_parameter_list_create(&list, &opr, func);
|
||||
RNA_parameter_set_lookup(&list, "context", &C);
|
||||
op->type->ext.call(C, &opr, func, &list);
|
||||
|
||||
RNA_parameter_get_lookup(&list, "result", &ret);
|
||||
result = *(int *)ret;
|
||||
|
||||
RNA_parameter_list_free(&list);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* same as execute() but no return value */
|
||||
static bool operator_check(bContext *C, wmOperator *op)
|
||||
{
|
||||
extern FunctionRNA rna_Operator_check_func;
|
||||
|
||||
PointerRNA opr;
|
||||
ParameterList list;
|
||||
FunctionRNA *func;
|
||||
void *ret;
|
||||
bool result;
|
||||
|
||||
RNA_pointer_create(NULL, op->type->ext.srna, op, &opr);
|
||||
func = &rna_Operator_check_func; /* RNA_struct_find_function(&opr, "check"); */
|
||||
|
||||
RNA_parameter_list_create(&list, &opr, func);
|
||||
RNA_parameter_set_lookup(&list, "context", &C);
|
||||
op->type->ext.call(C, &opr, func, &list);
|
||||
|
||||
RNA_parameter_get_lookup(&list, "result", &ret);
|
||||
result = (*(int *)ret) != 0;
|
||||
|
||||
RNA_parameter_list_free(&list);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int operator_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
extern FunctionRNA rna_Operator_invoke_func;
|
||||
|
||||
PointerRNA opr;
|
||||
ParameterList list;
|
||||
FunctionRNA *func;
|
||||
void *ret;
|
||||
int result;
|
||||
|
||||
RNA_pointer_create(NULL, op->type->ext.srna, op, &opr);
|
||||
func = &rna_Operator_invoke_func; /* RNA_struct_find_function(&opr, "invoke"); */
|
||||
|
||||
RNA_parameter_list_create(&list, &opr, func);
|
||||
RNA_parameter_set_lookup(&list, "context", &C);
|
||||
RNA_parameter_set_lookup(&list, "event", &event);
|
||||
op->type->ext.call(C, &opr, func, &list);
|
||||
|
||||
RNA_parameter_get_lookup(&list, "result", &ret);
|
||||
result = *(int *)ret;
|
||||
|
||||
RNA_parameter_list_free(&list);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* same as invoke */
|
||||
static int operator_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
extern FunctionRNA rna_Operator_modal_func;
|
||||
|
||||
PointerRNA opr;
|
||||
ParameterList list;
|
||||
FunctionRNA *func;
|
||||
void *ret;
|
||||
int result;
|
||||
|
||||
RNA_pointer_create(NULL, op->type->ext.srna, op, &opr);
|
||||
func = &rna_Operator_modal_func; /* RNA_struct_find_function(&opr, "modal"); */
|
||||
|
||||
RNA_parameter_list_create(&list, &opr, func);
|
||||
RNA_parameter_set_lookup(&list, "context", &C);
|
||||
RNA_parameter_set_lookup(&list, "event", &event);
|
||||
op->type->ext.call(C, &opr, func, &list);
|
||||
|
||||
RNA_parameter_get_lookup(&list, "result", &ret);
|
||||
result = *(int *)ret;
|
||||
|
||||
RNA_parameter_list_free(&list);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void operator_draw(bContext *C, wmOperator *op)
|
||||
{
|
||||
extern FunctionRNA rna_Operator_draw_func;
|
||||
|
||||
PointerRNA opr;
|
||||
ParameterList list;
|
||||
FunctionRNA *func;
|
||||
|
||||
RNA_pointer_create(NULL, op->type->ext.srna, op, &opr);
|
||||
func = &rna_Operator_draw_func; /* RNA_struct_find_function(&opr, "draw"); */
|
||||
|
||||
RNA_parameter_list_create(&list, &opr, func);
|
||||
RNA_parameter_set_lookup(&list, "context", &C);
|
||||
op->type->ext.call(C, &opr, func, &list);
|
||||
|
||||
RNA_parameter_list_free(&list);
|
||||
}
|
||||
|
||||
/* same as exec(), but call cancel */
|
||||
static void operator_cancel(bContext *C, wmOperator *op)
|
||||
{
|
||||
extern FunctionRNA rna_Operator_cancel_func;
|
||||
|
||||
PointerRNA opr;
|
||||
ParameterList list;
|
||||
FunctionRNA *func;
|
||||
|
||||
RNA_pointer_create(NULL, op->type->ext.srna, op, &opr);
|
||||
func = &rna_Operator_cancel_func; /* RNA_struct_find_function(&opr, "cancel"); */
|
||||
|
||||
RNA_parameter_list_create(&list, &opr, func);
|
||||
RNA_parameter_set_lookup(&list, "context", &C);
|
||||
op->type->ext.call(C, &opr, func, &list);
|
||||
|
||||
RNA_parameter_list_free(&list);
|
||||
}
|
||||
|
||||
void operator_wrapper(wmOperatorType *ot, void *userdata);
|
||||
void macro_wrapper(wmOperatorType *ot, void *userdata);
|
||||
|
||||
static char _operator_idname[OP_MAX_TYPENAME];
|
||||
static char _operator_name[OP_MAX_TYPENAME];
|
||||
static char _operator_descr[RNA_DYN_DESCR_MAX];
|
||||
static char _operator_ctxt[RNA_DYN_DESCR_MAX];
|
||||
static char _operator_undo_group[OP_MAX_TYPENAME];
|
||||
static StructRNA *rna_Operator_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
|
||||
StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
|
||||
{
|
||||
wmOperatorType dummyot = {NULL};
|
||||
wmOperator dummyop = {NULL};
|
||||
PointerRNA dummyotr;
|
||||
int have_function[7];
|
||||
|
||||
/* setup dummy operator & operator type to store static properties in */
|
||||
dummyop.type = &dummyot;
|
||||
dummyot.idname = _operator_idname; /* only assigne the pointer, string is NULL'd */
|
||||
dummyot.name = _operator_name; /* only assigne the pointer, string is NULL'd */
|
||||
dummyot.description = _operator_descr; /* only assigne the pointer, string is NULL'd */
|
||||
dummyot.translation_context = _operator_ctxt; /* only assigne the pointer, string is NULL'd */
|
||||
dummyot.undo_group = _operator_undo_group; /* only assigne the pointer, string is NULL'd */
|
||||
RNA_pointer_create(NULL, &RNA_Operator, &dummyop, &dummyotr);
|
||||
|
||||
/* clear in case they are left unset */
|
||||
_operator_idname[0] = _operator_name[0] = _operator_descr[0] = _operator_undo_group[0] = '\0';
|
||||
/* We have to set default op context! */
|
||||
strcpy(_operator_ctxt, BLT_I18NCONTEXT_OPERATOR_DEFAULT);
|
||||
|
||||
/* validate the python class */
|
||||
if (validate(&dummyotr, data, have_function) != 0)
|
||||
return NULL;
|
||||
|
||||
{ /* convert foo.bar to FOO_OT_bar
|
||||
* allocate the description and the idname in 1 go */
|
||||
|
||||
/* inconveniently long name sanity check */
|
||||
{
|
||||
char *ch = _operator_idname;
|
||||
int i;
|
||||
int dot = 0;
|
||||
for (i = 0; *ch; i++) {
|
||||
if ((*ch >= 'a' && *ch <= 'z') || (*ch >= '0' && *ch <= '9') || *ch == '_') {
|
||||
/* pass */
|
||||
}
|
||||
else if (*ch == '.') {
|
||||
dot++;
|
||||
}
|
||||
else {
|
||||
BKE_reportf(reports, RPT_ERROR,
|
||||
"Registering operator class: '%s', invalid bl_idname '%s', at position %d",
|
||||
identifier, _operator_idname, i);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ch++;
|
||||
}
|
||||
|
||||
if (i > ((int)sizeof(dummyop.idname)) - 3) {
|
||||
BKE_reportf(reports, RPT_ERROR, "Registering operator class: '%s', invalid bl_idname '%s', "
|
||||
"is too long, maximum length is %d", identifier, _operator_idname,
|
||||
(int)sizeof(dummyop.idname) - 3);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (dot != 1) {
|
||||
BKE_reportf(reports, RPT_ERROR,
|
||||
"Registering operator class: '%s', invalid bl_idname '%s', must contain 1 '.' character",
|
||||
identifier, _operator_idname);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
/* end sanity check */
|
||||
|
||||
{
|
||||
int idlen = strlen(_operator_idname) + 4;
|
||||
int namelen = strlen(_operator_name) + 1;
|
||||
int desclen = strlen(_operator_descr) + 1;
|
||||
int ctxtlen = strlen(_operator_ctxt) + 1;
|
||||
int ugrouplen = strlen(_operator_undo_group) + 1;
|
||||
char *ch;
|
||||
/* 2 terminators and 3 to convert a.b -> A_OT_b */
|
||||
ch = MEM_callocN(sizeof(char) * (idlen + namelen + desclen + ctxtlen + ugrouplen), "_operator_idname");
|
||||
WM_operator_bl_idname(ch, _operator_idname); /* convert the idname from python */
|
||||
dummyot.idname = ch;
|
||||
ch += idlen;
|
||||
strcpy(ch, _operator_name);
|
||||
dummyot.name = ch;
|
||||
ch += namelen;
|
||||
strcpy(ch, _operator_descr);
|
||||
dummyot.description = ch;
|
||||
ch += desclen;
|
||||
strcpy(ch, _operator_ctxt);
|
||||
dummyot.translation_context = ch;
|
||||
ch += ctxtlen;
|
||||
strcpy(ch, _operator_undo_group);
|
||||
dummyot.undo_group = ch;
|
||||
}
|
||||
}
|
||||
|
||||
/* check if we have registered this operator type before, and remove it */
|
||||
{
|
||||
wmOperatorType *ot = WM_operatortype_find(dummyot.idname, true);
|
||||
if (ot && ot->ext.srna)
|
||||
rna_Operator_unregister(bmain, ot->ext.srna);
|
||||
}
|
||||
|
||||
/* XXX, this doubles up with the operator name [#29666]
|
||||
* for now just remove from dir(bpy.types) */
|
||||
|
||||
/* create a new operator type */
|
||||
dummyot.ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, dummyot.idname, &RNA_Operator);
|
||||
RNA_def_struct_flag(dummyot.ext.srna, STRUCT_NO_IDPROPERTIES); /* operator properties are registered separately */
|
||||
RNA_def_struct_translation_context(dummyot.ext.srna, dummyot.translation_context);
|
||||
dummyot.ext.data = data;
|
||||
dummyot.ext.call = call;
|
||||
dummyot.ext.free = free;
|
||||
|
||||
dummyot.pyop_poll = (have_function[0]) ? operator_poll : NULL;
|
||||
dummyot.exec = (have_function[1]) ? operator_execute : NULL;
|
||||
dummyot.check = (have_function[2]) ? operator_check : NULL;
|
||||
dummyot.invoke = (have_function[3]) ? operator_invoke : NULL;
|
||||
dummyot.modal = (have_function[4]) ? operator_modal : NULL;
|
||||
dummyot.ui = (have_function[5]) ? operator_draw : NULL;
|
||||
dummyot.cancel = (have_function[6]) ? operator_cancel : NULL;
|
||||
WM_operatortype_append_ptr(operator_wrapper, (void *)&dummyot);
|
||||
|
||||
/* update while blender is running */
|
||||
WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL);
|
||||
|
||||
return dummyot.ext.srna;
|
||||
}
|
||||
|
||||
static void **rna_Operator_instance(PointerRNA *ptr)
|
||||
{
|
||||
wmOperator *op = ptr->data;
|
||||
return &op->py_instance;
|
||||
}
|
||||
|
||||
static StructRNA *rna_MacroOperator_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
|
||||
static StructRNA *rna_MacroOperator_register(
|
||||
Main *bmain, ReportList *reports, void *data, const char *identifier,
|
||||
StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
|
||||
{
|
||||
wmOperatorType dummyot = {NULL};
|
||||
@ -1373,56 +1382,64 @@ static StructRNA *rna_MacroOperator_register(Main *bmain, ReportList *reports, v
|
||||
PointerRNA dummyotr;
|
||||
int have_function[4];
|
||||
|
||||
struct {
|
||||
char idname[OP_MAX_TYPENAME];
|
||||
char name[OP_MAX_TYPENAME];
|
||||
char descr[RNA_DYN_DESCR_MAX];
|
||||
char ctxt[RNA_DYN_DESCR_MAX];
|
||||
char undo_group[OP_MAX_TYPENAME];
|
||||
} temp_buffers;
|
||||
|
||||
/* setup dummy operator & operator type to store static properties in */
|
||||
dummyop.type = &dummyot;
|
||||
dummyot.idname = _operator_idname; /* only assigne the pointer, string is NULL'd */
|
||||
dummyot.name = _operator_name; /* only assigne the pointer, string is NULL'd */
|
||||
dummyot.description = _operator_descr; /* only assigne the pointer, string is NULL'd */
|
||||
dummyot.translation_context = _operator_ctxt; /* only assigne the pointer, string is NULL'd */
|
||||
dummyot.undo_group = _operator_undo_group; /* only assigne the pointer, string is NULL'd */
|
||||
dummyot.idname = temp_buffers.idname; /* only assigne the pointer, string is NULL'd */
|
||||
dummyot.name = temp_buffers.name; /* only assigne the pointer, string is NULL'd */
|
||||
dummyot.description = temp_buffers.descr; /* only assigne the pointer, string is NULL'd */
|
||||
dummyot.translation_context = temp_buffers.ctxt; /* only assigne the pointer, string is NULL'd */
|
||||
dummyot.undo_group = temp_buffers.undo_group; /* only assigne the pointer, string is NULL'd */
|
||||
RNA_pointer_create(NULL, &RNA_Macro, &dummyop, &dummyotr);
|
||||
|
||||
/* clear in case they are left unset */
|
||||
_operator_idname[0] = _operator_name[0] = _operator_descr[0] = _operator_undo_group[0] = '\0';
|
||||
temp_buffers.idname[0] = temp_buffers.name[0] = temp_buffers.descr[0] = temp_buffers.undo_group[0] = '\0';
|
||||
/* We have to set default op context! */
|
||||
strcpy(_operator_ctxt, BLT_I18NCONTEXT_OPERATOR_DEFAULT);
|
||||
strcpy(temp_buffers.ctxt, BLT_I18NCONTEXT_OPERATOR_DEFAULT);
|
||||
|
||||
/* validate the python class */
|
||||
if (validate(&dummyotr, data, have_function) != 0)
|
||||
return NULL;
|
||||
|
||||
{ /* convert foo.bar to FOO_OT_bar
|
||||
* allocate the description and the idname in 1 go */
|
||||
int idlen = strlen(_operator_idname) + 4;
|
||||
int namelen = strlen(_operator_name) + 1;
|
||||
int desclen = strlen(_operator_descr) + 1;
|
||||
int ctxtlen = strlen(_operator_ctxt) + 1;
|
||||
int ugrouplen = strlen(_operator_undo_group) + 1;
|
||||
char *ch;
|
||||
/* 2 terminators and 3 to convert a.b -> A_OT_b */
|
||||
ch = MEM_callocN(sizeof(char) * (idlen + namelen + desclen + ctxtlen + ugrouplen), "_operator_idname");
|
||||
WM_operator_bl_idname(ch, _operator_idname); /* convert the idname from python */
|
||||
dummyot.idname = ch;
|
||||
ch += idlen;
|
||||
strcpy(ch, _operator_name);
|
||||
dummyot.name = ch;
|
||||
ch += namelen;
|
||||
strcpy(ch, _operator_descr);
|
||||
dummyot.description = ch;
|
||||
ch += desclen;
|
||||
strcpy(ch, _operator_ctxt);
|
||||
dummyot.translation_context = ch;
|
||||
ch += ctxtlen;
|
||||
strcpy(ch, _operator_undo_group);
|
||||
dummyot.undo_group = ch;
|
||||
}
|
||||
|
||||
if (strlen(identifier) >= sizeof(dummyop.idname)) {
|
||||
BKE_reportf(reports, RPT_ERROR, "Registering operator class: '%s' is too long, maximum length is %d",
|
||||
identifier, (int)sizeof(dummyop.idname));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
{ /* convert foo.bar to FOO_OT_bar
|
||||
* allocate the description and the idname in 1 go */
|
||||
const uint idname_len = strlen(temp_buffers.idname) + 4;
|
||||
const uint name_len = strlen(temp_buffers.name) + 1;
|
||||
const uint desc_len = strlen(temp_buffers.descr) + 1;
|
||||
const uint ctxt_len = strlen(temp_buffers.ctxt) + 1;
|
||||
const uint undo_group_len = strlen(temp_buffers.undo_group) + 1;
|
||||
/* 2 terminators and 3 to convert a.b -> A_OT_b */
|
||||
char *ch = MEM_mallocN(
|
||||
sizeof(char) * (idname_len + name_len + desc_len + ctxt_len + undo_group_len), __func__);
|
||||
WM_operator_bl_idname(ch, temp_buffers.idname); /* convert the idname from python */
|
||||
dummyot.idname = ch;
|
||||
ch += idname_len;
|
||||
memcpy(ch, temp_buffers.name, name_len);
|
||||
dummyot.name = ch;
|
||||
ch += name_len;
|
||||
memcpy(ch, temp_buffers.descr, desc_len);
|
||||
dummyot.description = ch;
|
||||
ch += desc_len;
|
||||
memcpy(ch, temp_buffers.ctxt, ctxt_len);
|
||||
dummyot.translation_context = ch;
|
||||
ch += ctxt_len;
|
||||
memcpy(ch, temp_buffers.undo_group, undo_group_len);
|
||||
dummyot.undo_group = ch;
|
||||
}
|
||||
|
||||
/* check if we have registered this operator type before, and remove it */
|
||||
{
|
||||
wmOperatorType *ot = WM_operatortype_find(dummyot.idname, true);
|
||||
@ -1440,10 +1457,10 @@ static StructRNA *rna_MacroOperator_register(Main *bmain, ReportList *reports, v
|
||||
dummyot.ext.call = call;
|
||||
dummyot.ext.free = free;
|
||||
|
||||
dummyot.pyop_poll = (have_function[0]) ? operator_poll : NULL;
|
||||
dummyot.ui = (have_function[3]) ? operator_draw : NULL;
|
||||
dummyot.pyop_poll = (have_function[0]) ? rna_operator_poll_cb : NULL;
|
||||
dummyot.ui = (have_function[3]) ? rna_operator_draw_cb : NULL;
|
||||
|
||||
WM_operatortype_append_macro_ptr(macro_wrapper, (void *)&dummyot);
|
||||
WM_operatortype_append_macro_ptr(BPY_RNA_operator_macro_wrapper, (void *)&dummyot);
|
||||
|
||||
/* update while blender is running */
|
||||
WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL);
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include "BKE_curve.h"
|
||||
#include "BKE_library_query.h"
|
||||
#include "BKE_modifier.h"
|
||||
#include "BKE_mesh.h"
|
||||
|
||||
#include "MOD_util.h"
|
||||
|
||||
@ -123,25 +124,6 @@ static void updateDepsgraph(ModifierData *md,
|
||||
}
|
||||
}
|
||||
|
||||
static float vertarray_size(const MVert *mvert, int numVerts, int axis)
|
||||
{
|
||||
int i;
|
||||
float min_co, max_co;
|
||||
|
||||
/* if there are no vertices, width is 0 */
|
||||
if (numVerts == 0) return 0;
|
||||
|
||||
/* find the minimum and maximum coordinates on the desired axis */
|
||||
min_co = max_co = mvert->co[axis];
|
||||
mvert++;
|
||||
for (i = 1; i < numVerts; ++i, ++mvert) {
|
||||
if (mvert->co[axis] < min_co) min_co = mvert->co[axis];
|
||||
if (mvert->co[axis] > max_co) max_co = mvert->co[axis];
|
||||
}
|
||||
|
||||
return max_co - min_co;
|
||||
}
|
||||
|
||||
BLI_INLINE float sum_v3(const float v[3])
|
||||
{
|
||||
return v[0] + v[1] + v[2];
|
||||
@ -438,12 +420,22 @@ static DerivedMesh *arrayModifier_doArray(
|
||||
unit_m4(offset);
|
||||
src_mvert = dm->getVertArray(dm);
|
||||
|
||||
if (amd->offset_type & MOD_ARR_OFF_CONST)
|
||||
add_v3_v3v3(offset[3], offset[3], amd->offset);
|
||||
if (amd->offset_type & MOD_ARR_OFF_CONST) {
|
||||
add_v3_v3(offset[3], amd->offset);
|
||||
}
|
||||
|
||||
if (amd->offset_type & MOD_ARR_OFF_RELATIVE) {
|
||||
for (j = 0; j < 3; j++)
|
||||
offset[3][j] += amd->scale[j] * vertarray_size(src_mvert, chunk_nverts, j);
|
||||
float min[3], max[3];
|
||||
const MVert *src_mv;
|
||||
|
||||
INIT_MINMAX(min, max);
|
||||
for (src_mv = src_mvert, j = chunk_nverts; j--; src_mv++) {
|
||||
minmax_v3v3_v3(min, max, src_mv->co);
|
||||
}
|
||||
|
||||
for (j = 3; j--; ) {
|
||||
offset[3][j] += amd->scale[j] * (max[j] - min[j]);
|
||||
}
|
||||
}
|
||||
|
||||
if (use_offset_ob) {
|
||||
|
@ -117,7 +117,7 @@ static void cmp_node_image_add_pass_output(bNodeTree *ntree, bNode *node,
|
||||
else {
|
||||
sock = BLI_findlink(&node->outputs, sock_index);
|
||||
NodeImageLayer *sockdata = sock->storage;
|
||||
if(sockdata) {
|
||||
if (sockdata) {
|
||||
BLI_strncpy(sockdata->pass_name, passname, sizeof(sockdata->pass_name));
|
||||
}
|
||||
}
|
||||
|
@ -118,7 +118,7 @@ static void operator_properties_init(wmOperatorType *ot)
|
||||
|
||||
}
|
||||
|
||||
void operator_wrapper(wmOperatorType *ot, void *userdata)
|
||||
void BPY_RNA_operator_wrapper(wmOperatorType *ot, void *userdata)
|
||||
{
|
||||
/* take care not to overwrite anything set in
|
||||
* WM_operatortype_append_ptr before opfunc() is called */
|
||||
@ -134,7 +134,7 @@ void operator_wrapper(wmOperatorType *ot, void *userdata)
|
||||
operator_properties_init(ot);
|
||||
}
|
||||
|
||||
void macro_wrapper(wmOperatorType *ot, void *userdata)
|
||||
void BPY_RNA_operator_macro_wrapper(wmOperatorType *ot, void *userdata)
|
||||
{
|
||||
wmOperatorType *data = (wmOperatorType *)userdata;
|
||||
|
||||
|
@ -33,7 +33,7 @@ struct wmOperatorType;
|
||||
PyObject *PYOP_wrap_macro_define(PyObject *self, PyObject *args);
|
||||
|
||||
/* exposed to rna/wm api */
|
||||
void operator_wrapper(struct wmOperatorType *ot, void *userdata);
|
||||
void macro_wrapper(struct wmOperatorType *ot, void *userdata);
|
||||
void BPY_RNA_operator_wrapper(struct wmOperatorType *ot, void *userdata);
|
||||
void BPY_RNA_operator_macro_wrapper(struct wmOperatorType *ot, void *userdata);
|
||||
|
||||
#endif
|
||||
|
@ -799,7 +799,8 @@ int collada_export(struct Scene *sce,
|
||||
void ED_mesh_calc_tessface(struct Mesh *mesh, bool free_mpoly) RET_NONE
|
||||
|
||||
/* bpy/python internal api */
|
||||
void operator_wrapper(struct wmOperatorType *ot, void *userdata) RET_NONE
|
||||
void BPY_RNA_operator_wrapper(struct wmOperatorType *ot, void *userdata) RET_NONE
|
||||
void BPY_RNA_operator_macro_wrapper(struct wmOperatorType *ot, void *userdata) RET_NONE
|
||||
void BPY_text_free_code(struct Text *text) RET_NONE
|
||||
void BPY_id_release(struct ID *id) RET_NONE
|
||||
int BPY_context_member_get(struct bContext *C, const char *member, struct bContextDataResult *result) RET_ZERO
|
||||
@ -807,7 +808,6 @@ void BPY_pyconstraint_target(struct bPythonConstraint *con, struct bConstraintTa
|
||||
float BPY_driver_exec(PathResolvedRNA *anim_rna, struct ChannelDriver *driver, const float evaltime) RET_ZERO /* might need this one! */
|
||||
void BPY_DECREF(void *pyob_ptr) RET_NONE
|
||||
void BPY_pyconstraint_exec(struct bPythonConstraint *con, struct bConstraintOb *cob, struct ListBase *targets) RET_NONE
|
||||
void macro_wrapper(struct wmOperatorType *ot, void *userdata) RET_NONE
|
||||
bool pyrna_id_FromPyObject(struct PyObject *obj, struct ID **id) RET_ZERO
|
||||
struct PyObject *pyrna_id_CreatePyObject(struct ID *id) RET_NULL
|
||||
bool pyrna_id_CheckPyObject(struct PyObject *obj) RET_ZERO
|
||||
|
Loading…
Reference in New Issue
Block a user