svn merge ^/trunk/blender -r42680:42722

This commit is contained in:
Campbell Barton 2011-12-19 10:40:48 +00:00
commit 2457d4f5ab
63 changed files with 1567 additions and 992 deletions

@ -649,10 +649,6 @@ elseif(WIN32)
set(ICONV_LIBPATH ${ICONV}/lib) set(ICONV_LIBPATH ${ICONV}/lib)
endif() endif()
set(PNG "${LIBDIR}/png")
set(PNG_INCLUDE_DIR "${PNG}/include")
set(PNG_LIBPATH ${PNG}/lib) # not cmake defined
set(JPEG "${LIBDIR}/jpeg") set(JPEG "${LIBDIR}/jpeg")
set(JPEG_INCLUDE_DIR "${JPEG}/include") set(JPEG_INCLUDE_DIR "${JPEG}/include")
set(JPEG_LIBPATH ${JPEG}/lib) # not cmake defined set(JPEG_LIBPATH ${JPEG}/lib) # not cmake defined
@ -733,6 +729,10 @@ elseif(WIN32)
set(PNG_LIBRARIES libpng_st) set(PNG_LIBRARIES libpng_st)
endif() endif()
set(JPEG_LIBRARIES libjpeg) set(JPEG_LIBRARIES libjpeg)
set(PNG "${LIBDIR}/png")
set(PNG_INCLUDE_DIR "${PNG}/include")
set(PNG_LIBPATH ${PNG}/lib) # not cmake defined
set(ZLIB_INCLUDE_DIRS ${LIBDIR}/zlib/include) set(ZLIB_INCLUDE_DIRS ${LIBDIR}/zlib/include)
if(CMAKE_CL_64) if(CMAKE_CL_64)
@ -913,6 +913,10 @@ elseif(WIN32)
set(GETTEXT_LIBPATH ${GETTEXT}/lib) set(GETTEXT_LIBPATH ${GETTEXT}/lib)
set(GETTEXT_LIBRARIES intl) set(GETTEXT_LIBRARIES intl)
endif() endif()
set(PNG "${LIBDIR}/gcc/png")
set(PNG_INCLUDE_DIR "${PNG}/include")
set(PNG_LIBPATH ${PNG}/lib) # not cmake defined
set(JPEG_LIBRARIES libjpeg) set(JPEG_LIBRARIES libjpeg)
set(PNG_LIBRARIES png) set(PNG_LIBRARIES png)

@ -64,7 +64,7 @@ BF_JPEG_LIB = 'liblibjpeg'
BF_JPEG_LIBPATH = '${BF_JPEG}/lib' BF_JPEG_LIBPATH = '${BF_JPEG}/lib'
WITH_BF_PNG = True WITH_BF_PNG = True
BF_PNG = LIBDIR + '/png' BF_PNG = LIBDIR + 'gcc/png'
BF_PNG_INC = '${BF_PNG}/include' BF_PNG_INC = '${BF_PNG}/include'
BF_PNG_LIB = 'png' BF_PNG_LIB = 'png'
BF_PNG_LIBPATH = '${BF_PNG}/lib' BF_PNG_LIBPATH = '${BF_PNG}/lib'

@ -50,28 +50,6 @@ void BlenderSync::find_shader(BL::ID id, vector<uint>& used_shaders, int default
/* Graph */ /* Graph */
static BL::NodeSocket get_node_input(BL::Node *b_group_node, BL::NodeSocket b_in)
{
if(b_group_node) {
BL::NodeTree b_ntree = BL::NodeGroup(*b_group_node).node_tree();
BL::NodeTree::links_iterator b_link;
for(b_ntree.links.begin(b_link); b_link != b_ntree.links.end(); ++b_link) {
if(b_link->to_socket().ptr.data == b_in.ptr.data) {
BL::Node::inputs_iterator b_gin;
for(b_group_node->inputs.begin(b_gin); b_gin != b_group_node->inputs.end(); ++b_gin)
if(b_gin->group_socket().ptr.data == b_link->from_socket().ptr.data)
return *b_gin;
}
}
}
return b_in;
}
static BL::NodeSocket get_node_output(BL::Node b_node, const string& name) static BL::NodeSocket get_node_output(BL::Node b_node, const string& name)
{ {
BL::Node::outputs_iterator b_out; BL::Node::outputs_iterator b_out;
@ -121,7 +99,7 @@ static void get_tex_mapping(TextureMapping *mapping, BL::ShaderNodeMapping b_map
mapping->scale = get_float3(b_mapping.scale()); mapping->scale = get_float3(b_mapping.scale());
} }
static ShaderNode *add_node(BL::BlendData b_data, ShaderGraph *graph, BL::Node *b_group_node, BL::ShaderNode b_node) static ShaderNode *add_node(BL::BlendData b_data, ShaderGraph *graph, BL::ShaderNode b_node)
{ {
ShaderNode *node = NULL; ShaderNode *node = NULL;
@ -470,59 +448,115 @@ static SocketPair node_socket_map_pair(PtrNodeMap& node_map, BL::Node b_node, BL
return SocketPair(node_map[b_node.ptr.data], name); return SocketPair(node_map[b_node.ptr.data], name);
} }
static void add_nodes(BL::BlendData b_data, ShaderGraph *graph, BL::ShaderNodeTree b_ntree, BL::Node *b_group_node, PtrSockMap& sockets_map) static ShaderSocketType convert_socket_type(BL::NodeSocket::type_enum b_type)
{
switch (b_type) {
case BL::NodeSocket::type_VALUE:
return SHADER_SOCKET_FLOAT;
case BL::NodeSocket::type_VECTOR:
return SHADER_SOCKET_VECTOR;
case BL::NodeSocket::type_RGBA:
return SHADER_SOCKET_COLOR;
case BL::NodeSocket::type_SHADER:
return SHADER_SOCKET_CLOSURE;
case BL::NodeSocket::type_BOOLEAN:
case BL::NodeSocket::type_MESH:
case BL::NodeSocket::type_INT:
default:
return SHADER_SOCKET_FLOAT;
}
}
static void set_default_value(ShaderInput *input, BL::NodeSocket sock)
{
/* copy values for non linked inputs */
switch(input->type) {
case SHADER_SOCKET_FLOAT: {
BL::NodeSocketFloatNone value_sock(sock);
input->set(value_sock.default_value());
break;
}
case SHADER_SOCKET_COLOR: {
BL::NodeSocketRGBA rgba_sock(sock);
input->set(get_float3(rgba_sock.default_value()));
break;
}
case SHADER_SOCKET_NORMAL:
case SHADER_SOCKET_POINT:
case SHADER_SOCKET_VECTOR: {
BL::NodeSocketVectorNone vec_sock(sock);
input->set(get_float3(vec_sock.default_value()));
break;
}
case SHADER_SOCKET_CLOSURE:
break;
}
}
static void add_nodes(BL::BlendData b_data, ShaderGraph *graph, BL::ShaderNodeTree b_ntree, PtrSockMap& sockets_map)
{ {
/* add nodes */ /* add nodes */
BL::ShaderNodeTree::nodes_iterator b_node; BL::ShaderNodeTree::nodes_iterator b_node;
PtrNodeMap node_map; PtrNodeMap node_map;
map<void*, PtrSockMap> node_groups; PtrSockMap proxy_map;
for(b_ntree.nodes.begin(b_node); b_node != b_ntree.nodes.end(); ++b_node) { for(b_ntree.nodes.begin(b_node); b_node != b_ntree.nodes.end(); ++b_node) {
if(b_node->is_a(&RNA_NodeGroup)) { if(b_node->is_a(&RNA_NodeGroup)) {
/* add proxy converter nodes for inputs and outputs */
BL::NodeGroup b_gnode(*b_node); BL::NodeGroup b_gnode(*b_node);
BL::ShaderNodeTree b_group_ntree(b_gnode.node_tree()); BL::ShaderNodeTree b_group_ntree(b_gnode.node_tree());
BL::Node::inputs_iterator b_input;
node_groups[b_node->ptr.data] = PtrSockMap(); BL::Node::outputs_iterator b_output;
add_nodes(b_data, graph, b_group_ntree, &b_gnode, node_groups[b_node->ptr.data]);
PtrSockMap group_sockmap;
for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) {
ShaderSocketType extern_type = convert_socket_type(b_input->type());
ShaderSocketType intern_type = convert_socket_type(b_input->group_socket().type());
ShaderNode *proxy = graph->add(new ProxyNode(extern_type, intern_type));
/* map the external node socket to the proxy node socket */
proxy_map[b_input->ptr.data] = SocketPair(proxy, proxy->inputs[0]->name);
/* map the internal group socket to the proxy node socket */
group_sockmap[b_input->group_socket().ptr.data] = SocketPair(proxy, proxy->outputs[0]->name);
/* default input values of the group node */
set_default_value(proxy->inputs[0], *b_input);
}
for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) {
ShaderSocketType extern_type = convert_socket_type(b_output->type());
ShaderSocketType intern_type = convert_socket_type(b_output->group_socket().type());
ShaderNode *proxy = graph->add(new ProxyNode(intern_type, extern_type));
/* map the external node socket to the proxy node socket */
proxy_map[b_output->ptr.data] = SocketPair(proxy, proxy->outputs[0]->name);
/* map the internal group socket to the proxy node socket */
group_sockmap[b_output->group_socket().ptr.data] = SocketPair(proxy, proxy->inputs[0]->name);
/* default input values of internal, unlinked group outputs */
set_default_value(proxy->inputs[0], b_output->group_socket());
}
add_nodes(b_data, graph, b_group_ntree, group_sockmap);
} }
else { else {
ShaderNode *node = add_node(b_data, graph, b_group_node, BL::ShaderNode(*b_node)); ShaderNode *node = add_node(b_data, graph, BL::ShaderNode(*b_node));
if(node) { if(node) {
BL::Node::inputs_iterator b_input; BL::Node::inputs_iterator b_input;
BL::Node::outputs_iterator b_output;
node_map[b_node->ptr.data] = node; node_map[b_node->ptr.data] = node;
for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) { for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) {
SocketPair pair = node_socket_map_pair(node_map, *b_node, *b_input); SocketPair pair = node_socket_map_pair(node_map, *b_node, *b_input);
ShaderInput *input = pair.first->input(pair.second.c_str()); ShaderInput *input = pair.first->input(pair.second.c_str());
BL::NodeSocket sock(get_node_input(b_group_node, *b_input));
assert(input); assert(input);
/* copy values for non linked inputs */ /* copy values for non linked inputs */
switch(input->type) { set_default_value(input, *b_input);
case SHADER_SOCKET_FLOAT: {
BL::NodeSocketFloatNone value_sock(sock);
input->set(value_sock.default_value());
break;
}
case SHADER_SOCKET_COLOR: {
BL::NodeSocketRGBA rgba_sock(sock);
input->set(get_float3(rgba_sock.default_value()));
break;
}
case SHADER_SOCKET_NORMAL:
case SHADER_SOCKET_POINT:
case SHADER_SOCKET_VECTOR: {
BL::NodeSocketVectorNone vec_sock(sock);
input->set(get_float3(vec_sock.default_value()));
break;
}
case SHADER_SOCKET_CLOSURE:
break;
}
} }
} }
} }
@ -539,54 +573,34 @@ static void add_nodes(BL::BlendData b_data, ShaderGraph *graph, BL::ShaderNodeTr
BL::NodeSocket b_from_sock = b_link->from_socket(); BL::NodeSocket b_from_sock = b_link->from_socket();
BL::NodeSocket b_to_sock = b_link->to_socket(); BL::NodeSocket b_to_sock = b_link->to_socket();
/* if link with group socket, add to map so we can connect it later */
if(b_group_node) {
if(!b_from_node) {
sockets_map[b_from_sock.ptr.data] =
node_socket_map_pair(node_map, b_to_node, b_to_sock);
continue;
}
else if(!b_to_node) {
sockets_map[b_to_sock.ptr.data] =
node_socket_map_pair(node_map, b_from_node, b_from_sock);
continue;
}
}
SocketPair from_pair, to_pair; SocketPair from_pair, to_pair;
/* links without a node pointer are connections to group inputs/outputs */
/* from sock */ /* from sock */
if(b_from_node.is_a(&RNA_NodeGroup)) { if(b_from_node) {
/* group node */ if (b_from_node.is_a(&RNA_NodeGroup))
BL::NodeSocket group_sock = b_from_sock.group_socket(); from_pair = proxy_map[b_from_sock.ptr.data];
from_pair = node_groups[b_from_node.ptr.data][group_sock.ptr.data]; else
} from_pair = node_socket_map_pair(node_map, b_from_node, b_from_sock);
else {
/* regular node */
from_pair = node_socket_map_pair(node_map, b_from_node, b_from_sock);
} }
else
from_pair = sockets_map[b_from_sock.ptr.data];
/* to sock */ /* to sock */
if(b_to_node.is_a(&RNA_NodeGroup)) { if(b_to_node) {
/* group node */ if (b_to_node.is_a(&RNA_NodeGroup))
BL::NodeSocket group_sock = b_to_sock.group_socket(); to_pair = proxy_map[b_to_sock.ptr.data];
to_pair = node_groups[b_to_node.ptr.data][group_sock.ptr.data]; else
} to_pair = node_socket_map_pair(node_map, b_to_node, b_to_sock);
else {
/* regular node */
to_pair = node_socket_map_pair(node_map, b_to_node, b_to_sock);
} }
else
to_pair = sockets_map[b_to_sock.ptr.data];
/* in case of groups there may not actually be a node inside the group ShaderOutput *output = from_pair.first->output(from_pair.second.c_str());
that the group socket connects to, so from_node or to_node may be NULL */ ShaderInput *input = to_pair.first->input(to_pair.second.c_str());
if(from_pair.first && to_pair.first) {
ShaderOutput *output = from_pair.first->output(from_pair.second.c_str());
ShaderInput *input = to_pair.first->input(to_pair.second.c_str());
graph->connect(output, input); graph->connect(output, input);
}
} }
} }
@ -613,7 +627,7 @@ void BlenderSync::sync_materials()
PtrSockMap sock_to_node; PtrSockMap sock_to_node;
BL::ShaderNodeTree b_ntree(b_mat->node_tree()); BL::ShaderNodeTree b_ntree(b_mat->node_tree());
add_nodes(b_data, graph, b_ntree, NULL, sock_to_node); add_nodes(b_data, graph, b_ntree, sock_to_node);
} }
else { else {
ShaderNode *closure, *out; ShaderNode *closure, *out;
@ -654,7 +668,7 @@ void BlenderSync::sync_world()
PtrSockMap sock_to_node; PtrSockMap sock_to_node;
BL::ShaderNodeTree b_ntree(b_world.node_tree()); BL::ShaderNodeTree b_ntree(b_world.node_tree());
add_nodes(b_data, graph, b_ntree, NULL, sock_to_node); add_nodes(b_data, graph, b_ntree, sock_to_node);
} }
else if(b_world) { else if(b_world) {
ShaderNode *closure, *out; ShaderNode *closure, *out;
@ -703,7 +717,7 @@ void BlenderSync::sync_lamps()
PtrSockMap sock_to_node; PtrSockMap sock_to_node;
BL::ShaderNodeTree b_ntree(b_lamp->node_tree()); BL::ShaderNodeTree b_ntree(b_lamp->node_tree());
add_nodes(b_data, graph, b_ntree, NULL, sock_to_node); add_nodes(b_data, graph, b_ntree, sock_to_node);
} }
else { else {
ShaderNode *closure, *out; ShaderNode *closure, *out;

@ -292,6 +292,42 @@ void ShaderGraph::copy_nodes(set<ShaderNode*>& nodes, map<ShaderNode*, ShaderNod
} }
} }
void ShaderGraph::remove_proxy_nodes(vector<bool>& removed)
{
foreach(ShaderNode *node, nodes) {
ProxyNode *proxy = dynamic_cast<ProxyNode*>(node);
if (proxy) {
ShaderInput *input = proxy->inputs[0];
ShaderOutput *output = proxy->outputs[0];
/* temp. copy of the output links list.
* output->links is modified when we disconnect!
*/
vector<ShaderInput*> links(output->links);
ShaderOutput *from = input->link;
/* bypass the proxy node */
if (from) {
disconnect(input);
foreach(ShaderInput *to, links) {
disconnect(to);
connect(from, to);
}
}
else {
foreach(ShaderInput *to, links) {
disconnect(to);
/* transfer the default input value to the target socket */
to->set(input->value);
}
}
removed[proxy->id] = true;
}
}
}
void ShaderGraph::break_cycles(ShaderNode *node, vector<bool>& visited, vector<bool>& on_stack) void ShaderGraph::break_cycles(ShaderNode *node, vector<bool>& visited, vector<bool>& on_stack)
{ {
visited[node->id] = true; visited[node->id] = true;
@ -322,15 +358,28 @@ void ShaderGraph::clean()
nodes that don't feed into the output. how cycles are broken is nodes that don't feed into the output. how cycles are broken is
undefined, they are invalid input, the important thing is to not crash */ undefined, they are invalid input, the important thing is to not crash */
vector<bool> removed(nodes.size(), false);
vector<bool> visited(nodes.size(), false); vector<bool> visited(nodes.size(), false);
vector<bool> on_stack(nodes.size(), false); vector<bool> on_stack(nodes.size(), false);
list<ShaderNode*> newnodes;
/* remove proxy nodes */
remove_proxy_nodes(removed);
foreach(ShaderNode *node, nodes) {
if(!removed[node->id])
newnodes.push_back(node);
else
delete node;
}
nodes = newnodes;
newnodes.clear();
/* break cycles */ /* break cycles */
break_cycles(output(), visited, on_stack); break_cycles(output(), visited, on_stack);
/* remove unused nodes */ /* remove unused nodes */
list<ShaderNode*> newnodes;
foreach(ShaderNode *node, nodes) { foreach(ShaderNode *node, nodes) {
if(visited[node->id]) if(visited[node->id])
newnodes.push_back(node); newnodes.push_back(node);

@ -217,6 +217,7 @@ protected:
void find_dependencies(set<ShaderNode*>& dependencies, ShaderInput *input); void find_dependencies(set<ShaderNode*>& dependencies, ShaderInput *input);
void copy_nodes(set<ShaderNode*>& nodes, map<ShaderNode*, ShaderNode*>& nnodemap); void copy_nodes(set<ShaderNode*>& nodes, map<ShaderNode*, ShaderNode*>& nnodemap);
void remove_proxy_nodes(vector<bool>& removed);
void break_cycles(ShaderNode *node, vector<bool>& visited, vector<bool>& on_stack); void break_cycles(ShaderNode *node, vector<bool>& visited, vector<bool>& on_stack);
void clean(); void clean();
void bump_from_displacement(); void bump_from_displacement();

@ -869,6 +869,26 @@ void ConvertNode::compile(OSLCompiler& compiler)
assert(0); assert(0);
} }
/* Proxy */
ProxyNode::ProxyNode(ShaderSocketType from_, ShaderSocketType to_)
: ShaderNode("proxy")
{
from = from_;
to = to_;
add_input("Input", from);
add_output("Output", to);
}
void ProxyNode::compile(SVMCompiler& compiler)
{
}
void ProxyNode::compile(OSLCompiler& compiler)
{
}
/* BSDF Closure */ /* BSDF Closure */
BsdfNode::BsdfNode() BsdfNode::BsdfNode()

@ -158,6 +158,14 @@ public:
ShaderSocketType from, to; ShaderSocketType from, to;
}; };
class ProxyNode : public ShaderNode {
public:
ProxyNode(ShaderSocketType from, ShaderSocketType to);
SHADER_NODE_BASE_CLASS(ProxyNode)
ShaderSocketType from, to;
};
class BsdfNode : public ShaderNode { class BsdfNode : public ShaderNode {
public: public:
SHADER_NODE_CLASS(BsdfNode) SHADER_NODE_CLASS(BsdfNode)

@ -156,6 +156,7 @@ class NODE_MT_node(Menu):
layout.operator("node.mute_toggle") layout.operator("node.mute_toggle")
layout.operator("node.preview_toggle") layout.operator("node.preview_toggle")
layout.operator("node.hide_socket_toggle") layout.operator("node.hide_socket_toggle")
layout.operator("node.options_toggle")
layout.separator() layout.separator()

@ -153,9 +153,9 @@ int CustomData_number_of_layers(const struct CustomData *data, int type);
/* duplicate data of a layer with flag NOFREE, and remove that flag. /* duplicate data of a layer with flag NOFREE, and remove that flag.
* returns the layer data */ * returns the layer data */
void *CustomData_duplicate_referenced_layer(struct CustomData *data, int type); void *CustomData_duplicate_referenced_layer(struct CustomData *data, const int type, const int totelem);
void *CustomData_duplicate_referenced_layer_named(struct CustomData *data, void *CustomData_duplicate_referenced_layer_named(struct CustomData *data,
int type, const char *name); const int type, const char *name, const int totelem);
int CustomData_is_referenced_layer(struct CustomData *data, int type); int CustomData_is_referenced_layer(struct CustomData *data, int type);
/* set the CD_FLAG_NOCOPY flag in custom data layers where the mask is /* set the CD_FLAG_NOCOPY flag in custom data layers where the mask is

@ -218,7 +218,7 @@ static CCGAllocatorIFC *_getStandardAllocatorIFC(void) {
/***/ /***/
static int VertDataEqual(float *a, float *b) { static int VertDataEqual(const float *a, const float *b) {
return a[0]==b[0] && a[1]==b[1] && a[2]==b[2]; return a[0]==b[0] && a[1]==b[1] && a[2]==b[2];
} }
#define VertDataZero(av) { float *_a = (float*) av; _a[0] = _a[1] = _a[2] = 0.0f; } #define VertDataZero(av) { float *_a = (float*) av; _a[0] = _a[1] = _a[2] = 0.0f; }
@ -238,7 +238,7 @@ static int VertDataEqual(float *a, float *b) {
#define NormAdd(av, bv) { float *_a = (float*) av, *_b = (float*) bv; _a[0]+=_b[0]; _a[1]+=_b[1]; _a[2]+=_b[2]; } #define NormAdd(av, bv) { float *_a = (float*) av, *_b = (float*) bv; _a[0]+=_b[0]; _a[1]+=_b[1]; _a[2]+=_b[2]; }
static int _edge_isBoundary(CCGEdge *e); static int _edge_isBoundary(const CCGEdge *e);
/***/ /***/
@ -392,7 +392,7 @@ static void _vert_addFace(CCGVert *v, CCGFace *f, CCGSubSurf *ss) {
v->faces = CCGSUBSURF_realloc(ss, v->faces, (v->numFaces+1)*sizeof(*v->faces), v->numFaces*sizeof(*v->faces)); v->faces = CCGSUBSURF_realloc(ss, v->faces, (v->numFaces+1)*sizeof(*v->faces), v->numFaces*sizeof(*v->faces));
v->faces[v->numFaces++] = f; v->faces[v->numFaces++] = f;
} }
static CCGEdge *_vert_findEdgeTo(CCGVert *v, CCGVert *vQ) { static CCGEdge *_vert_findEdgeTo(const CCGVert *v, const CCGVert *vQ) {
int i; int i;
for (i=0; i<v->numEdges; i++) { for (i=0; i<v->numEdges; i++) {
CCGEdge *e = v->edges[v->numEdges-1-i]; // XXX, note reverse CCGEdge *e = v->edges[v->numEdges-1-i]; // XXX, note reverse
@ -402,7 +402,7 @@ static CCGEdge *_vert_findEdgeTo(CCGVert *v, CCGVert *vQ) {
} }
return NULL; return NULL;
} }
static int _vert_isBoundary(CCGVert *v) { static int _vert_isBoundary(const CCGVert *v) {
int i; int i;
for (i=0; i<v->numEdges; i++) for (i=0; i<v->numEdges; i++)
if (_edge_isBoundary(v->edges[i])) if (_edge_isBoundary(v->edges[i]))
@ -423,7 +423,7 @@ static void _vert_free(CCGVert *v, CCGSubSurf *ss) {
CCGSUBSURF_free(ss, v); CCGSUBSURF_free(ss, v);
} }
static int VERT_seam(CCGVert *v) { static int VERT_seam(const CCGVert *v) {
return ((v->flags & Vert_eSeam) != 0); return ((v->flags & Vert_eSeam) != 0);
} }
@ -462,7 +462,7 @@ static void _edge_addFace(CCGEdge *e, CCGFace *f, CCGSubSurf *ss) {
e->faces = CCGSUBSURF_realloc(ss, e->faces, (e->numFaces+1)*sizeof(*e->faces), e->numFaces*sizeof(*e->faces)); e->faces = CCGSUBSURF_realloc(ss, e->faces, (e->numFaces+1)*sizeof(*e->faces), e->numFaces*sizeof(*e->faces));
e->faces[e->numFaces++] = f; e->faces[e->numFaces++] = f;
} }
static int _edge_isBoundary(CCGEdge *e) { static int _edge_isBoundary(const CCGEdge *e) {
return e->numFaces<2; return e->numFaces<2;
} }
@ -900,7 +900,7 @@ CCGError ccgSubSurf_syncFaceDel(CCGSubSurf *ss, CCGFaceHDL fHDL) {
return eCCGError_None; return eCCGError_None;
} }
CCGError ccgSubSurf_syncVert(CCGSubSurf *ss, CCGVertHDL vHDL, void *vertData, int seam, CCGVert **v_r) { CCGError ccgSubSurf_syncVert(CCGSubSurf *ss, CCGVertHDL vHDL, const void *vertData, int seam, CCGVert **v_r) {
void **prevp; void **prevp;
CCGVert *v = NULL; CCGVert *v = NULL;
short seamflag = (seam)? Vert_eSeam: 0; short seamflag = (seam)? Vert_eSeam: 0;
@ -2484,13 +2484,13 @@ CCGError ccgSubSurf_updateLevels(CCGSubSurf *ss, int lvl, CCGFace **effectedF, i
/*** External API accessor functions ***/ /*** External API accessor functions ***/
int ccgSubSurf_getNumVerts(CCGSubSurf *ss) { int ccgSubSurf_getNumVerts(const CCGSubSurf *ss) {
return ss->vMap->numEntries; return ss->vMap->numEntries;
} }
int ccgSubSurf_getNumEdges(CCGSubSurf *ss) { int ccgSubSurf_getNumEdges(const CCGSubSurf *ss) {
return ss->eMap->numEntries; return ss->eMap->numEntries;
} }
int ccgSubSurf_getNumFaces(CCGSubSurf *ss) { int ccgSubSurf_getNumFaces(const CCGSubSurf *ss) {
return ss->fMap->numEntries; return ss->fMap->numEntries;
} }
@ -2504,23 +2504,23 @@ CCGFace *ccgSubSurf_getFace(CCGSubSurf *ss, CCGFaceHDL f) {
return (CCGFace*) _ehash_lookup(ss->fMap, f); return (CCGFace*) _ehash_lookup(ss->fMap, f);
} }
int ccgSubSurf_getSubdivisionLevels(CCGSubSurf *ss) { int ccgSubSurf_getSubdivisionLevels(const CCGSubSurf *ss) {
return ss->subdivLevels; return ss->subdivLevels;
} }
int ccgSubSurf_getEdgeSize(CCGSubSurf *ss) { int ccgSubSurf_getEdgeSize(const CCGSubSurf *ss) {
return ccgSubSurf_getEdgeLevelSize(ss, ss->subdivLevels); return ccgSubSurf_getEdgeLevelSize(ss, ss->subdivLevels);
} }
int ccgSubSurf_getEdgeLevelSize(CCGSubSurf *ss, int level) { int ccgSubSurf_getEdgeLevelSize(const CCGSubSurf *ss, int level) {
if (level<1 || level>ss->subdivLevels) { if (level<1 || level>ss->subdivLevels) {
return -1; return -1;
} else { } else {
return 1 + (1<<level); return 1 + (1<<level);
} }
} }
int ccgSubSurf_getGridSize(CCGSubSurf *ss) { int ccgSubSurf_getGridSize(const CCGSubSurf *ss) {
return ccgSubSurf_getGridLevelSize(ss, ss->subdivLevels); return ccgSubSurf_getGridLevelSize(ss, ss->subdivLevels);
} }
int ccgSubSurf_getGridLevelSize(CCGSubSurf *ss, int level) { int ccgSubSurf_getGridLevelSize(const CCGSubSurf *ss, int level) {
if (level<1 || level>ss->subdivLevels) { if (level<1 || level>ss->subdivLevels) {
return -1; return -1;
} else { } else {
@ -2736,19 +2736,19 @@ void ccgFaceIterator_free(CCGFaceIterator *vi) {
/*** Extern API final vert/edge/face interface ***/ /*** Extern API final vert/edge/face interface ***/
int ccgSubSurf_getNumFinalVerts(CCGSubSurf *ss) { int ccgSubSurf_getNumFinalVerts(const CCGSubSurf *ss) {
int edgeSize = 1 + (1<<ss->subdivLevels); int edgeSize = 1 + (1<<ss->subdivLevels);
int gridSize = 1 + (1<<(ss->subdivLevels-1)); int gridSize = 1 + (1<<(ss->subdivLevels-1));
int numFinalVerts = ss->vMap->numEntries + ss->eMap->numEntries*(edgeSize-2) + ss->fMap->numEntries + ss->numGrids*((gridSize-2) + ((gridSize-2)*(gridSize-2))); int numFinalVerts = ss->vMap->numEntries + ss->eMap->numEntries*(edgeSize-2) + ss->fMap->numEntries + ss->numGrids*((gridSize-2) + ((gridSize-2)*(gridSize-2)));
return numFinalVerts; return numFinalVerts;
} }
int ccgSubSurf_getNumFinalEdges(CCGSubSurf *ss) { int ccgSubSurf_getNumFinalEdges(const CCGSubSurf *ss) {
int edgeSize = 1 + (1<<ss->subdivLevels); int edgeSize = 1 + (1<<ss->subdivLevels);
int gridSize = 1 + (1<<(ss->subdivLevels-1)); int gridSize = 1 + (1<<(ss->subdivLevels-1));
int numFinalEdges = ss->eMap->numEntries*(edgeSize-1) + ss->numGrids*((gridSize-1) + 2*((gridSize-2)*(gridSize-1))); int numFinalEdges = ss->eMap->numEntries*(edgeSize-1) + ss->numGrids*((gridSize-1) + 2*((gridSize-2)*(gridSize-1)));
return numFinalEdges; return numFinalEdges;
} }
int ccgSubSurf_getNumFinalFaces(CCGSubSurf *ss) { int ccgSubSurf_getNumFinalFaces(const CCGSubSurf *ss) {
int gridSize = 1 + (1<<(ss->subdivLevels-1)); int gridSize = 1 + (1<<(ss->subdivLevels-1));
int numFinalFaces = ss->numGrids*((gridSize-1)*(gridSize-1)); int numFinalFaces = ss->numGrids*((gridSize-1)*(gridSize-1));
return numFinalFaces; return numFinalFaces;

@ -56,7 +56,7 @@ CCGError ccgSubSurf_sync (CCGSubSurf *ss);
CCGError ccgSubSurf_initFullSync (CCGSubSurf *ss); CCGError ccgSubSurf_initFullSync (CCGSubSurf *ss);
CCGError ccgSubSurf_initPartialSync (CCGSubSurf *ss); CCGError ccgSubSurf_initPartialSync (CCGSubSurf *ss);
CCGError ccgSubSurf_syncVert (CCGSubSurf *ss, CCGVertHDL vHDL, void *vertData, int seam, CCGVert **v_r); CCGError ccgSubSurf_syncVert (CCGSubSurf *ss, CCGVertHDL vHDL, const void *vertData, int seam, CCGVert **v_r);
CCGError ccgSubSurf_syncEdge (CCGSubSurf *ss, CCGEdgeHDL eHDL, CCGVertHDL e_vHDL0, CCGVertHDL e_vHDL1, float crease, CCGEdge **e_r); CCGError ccgSubSurf_syncEdge (CCGSubSurf *ss, CCGEdgeHDL eHDL, CCGVertHDL e_vHDL0, CCGVertHDL e_vHDL1, float crease, CCGEdge **e_r);
CCGError ccgSubSurf_syncFace (CCGSubSurf *ss, CCGFaceHDL fHDL, int numVerts, CCGVertHDL *vHDLs, CCGFace **f_r); CCGError ccgSubSurf_syncFace (CCGSubSurf *ss, CCGFaceHDL fHDL, int numVerts, CCGVertHDL *vHDLs, CCGFace **f_r);
@ -84,15 +84,15 @@ CCGError ccgSubSurf_setCalcVertexNormals (CCGSubSurf *ss, int useVertNormals, i
/***/ /***/
int ccgSubSurf_getNumVerts (CCGSubSurf *ss); int ccgSubSurf_getNumVerts (const CCGSubSurf *ss);
int ccgSubSurf_getNumEdges (CCGSubSurf *ss); int ccgSubSurf_getNumEdges (const CCGSubSurf *ss);
int ccgSubSurf_getNumFaces (CCGSubSurf *ss); int ccgSubSurf_getNumFaces (const CCGSubSurf *ss);
int ccgSubSurf_getSubdivisionLevels (CCGSubSurf *ss); int ccgSubSurf_getSubdivisionLevels (const CCGSubSurf *ss);
int ccgSubSurf_getEdgeSize (CCGSubSurf *ss); int ccgSubSurf_getEdgeSize (const CCGSubSurf *ss);
int ccgSubSurf_getEdgeLevelSize (CCGSubSurf *ss, int level); int ccgSubSurf_getEdgeLevelSize (const CCGSubSurf *ss, int level);
int ccgSubSurf_getGridSize (CCGSubSurf *ss); int ccgSubSurf_getGridSize (const CCGSubSurf *ss);
int ccgSubSurf_getGridLevelSize (CCGSubSurf *ss, int level); int ccgSubSurf_getGridLevelSize (const CCGSubSurf *ss, int level);
CCGVert* ccgSubSurf_getVert (CCGSubSurf *ss, CCGVertHDL v); CCGVert* ccgSubSurf_getVert (CCGSubSurf *ss, CCGVertHDL v);
CCGVertHDL ccgSubSurf_getVertVertHandle (CCGVert *v); CCGVertHDL ccgSubSurf_getVertVertHandle (CCGVert *v);
@ -135,9 +135,9 @@ void* ccgSubSurf_getFaceGridEdgeData (CCGSubSurf *ss, CCGFace *f, int gridInde
void* ccgSubSurf_getFaceGridDataArray (CCGSubSurf *ss, CCGFace *f, int gridIndex); void* ccgSubSurf_getFaceGridDataArray (CCGSubSurf *ss, CCGFace *f, int gridIndex);
void* ccgSubSurf_getFaceGridData (CCGSubSurf *ss, CCGFace *f, int gridIndex, int x, int y); void* ccgSubSurf_getFaceGridData (CCGSubSurf *ss, CCGFace *f, int gridIndex, int x, int y);
int ccgSubSurf_getNumFinalVerts (CCGSubSurf *ss); int ccgSubSurf_getNumFinalVerts (const CCGSubSurf *ss);
int ccgSubSurf_getNumFinalEdges (CCGSubSurf *ss); int ccgSubSurf_getNumFinalEdges (const CCGSubSurf *ss);
int ccgSubSurf_getNumFinalFaces (CCGSubSurf *ss); int ccgSubSurf_getNumFinalFaces (const CCGSubSurf *ss);
/***/ /***/

@ -883,67 +883,71 @@ enum {
CALC_WP_AUTO_NORMALIZE= (1<<1) CALC_WP_AUTO_NORMALIZE= (1<<1)
}; };
static void calc_weightpaint_vert_color( void weightpaint_color(unsigned char r_col[4], ColorBand *coba, const float input)
Object *ob, const int defbase_tot, ColorBand *coba, int vert, unsigned char *col, {
const char *dg_flags, int selected, int UNUSED(unselected), const int draw_flag) float colf[4];
if(coba) do_colorband(coba, input, colf);
else weight_to_rgb(colf, input);
r_col[3] = (unsigned char)(colf[0] * 255.0f);
r_col[2] = (unsigned char)(colf[1] * 255.0f);
r_col[1] = (unsigned char)(colf[2] * 255.0f);
r_col[0] = 255;
}
static void calc_weightpaint_vert_color(
unsigned char r_col[4],
MDeformVert *dv, ColorBand *coba,
const int defbase_tot, const int defbase_act,
const char *dg_flags,
const int selected, const int draw_flag)
{ {
Mesh *me = ob->data;
float input = 0.0f; float input = 0.0f;
int make_black= FALSE; int make_black= FALSE;
if (me->dvert) { if ((selected > 1) && (draw_flag & CALC_WP_MULTIPAINT)) {
MDeformVert *dvert= &me->dvert[vert]; int was_a_nonzero= FALSE;
int i;
if ((selected > 1) && (draw_flag & CALC_WP_MULTIPAINT)) { MDeformWeight *dw= dv->dw;
int was_a_nonzero= FALSE; for (i = dv->totweight; i > 0; i--, dw++) {
int i; /* in multipaint, get the average if auto normalize is inactive
* get the sum if it is active */
MDeformWeight *dw= dvert->dw; if (dw->def_nr < defbase_tot) {
for (i = dvert->totweight; i > 0; i--, dw++) { if (dg_flags[dw->def_nr]) {
/* in multipaint, get the average if auto normalize is inactive if (dw->weight) {
* get the sum if it is active */ input += dw->weight;
if (dw->def_nr < defbase_tot) { was_a_nonzero= TRUE;
if (dg_flags[dw->def_nr]) {
if (dw->weight) {
input += dw->weight;
was_a_nonzero= TRUE;
}
} }
} }
} }
}
/* make it black if the selected groups have no weight on a vertex */ /* make it black if the selected groups have no weight on a vertex */
if (was_a_nonzero == FALSE) { if (was_a_nonzero == FALSE) {
make_black = TRUE; make_black = TRUE;
}
else if ((draw_flag & CALC_WP_AUTO_NORMALIZE) == FALSE) {
input /= selected; /* get the average */
}
} }
else { else if ((draw_flag & CALC_WP_AUTO_NORMALIZE) == FALSE) {
/* default, non tricky behavior */ input /= selected; /* get the average */
input= defvert_find_weight(dvert, ob->actdef-1);
} }
} }
if (make_black) {
col[3] = 0;
col[2] = 0;
col[1] = 0;
col[0] = 255;
}
else { else {
float colf[4]; /* default, non tricky behavior */
input= defvert_find_weight(dv, defbase_act);
}
if (make_black) { /* TODO, theme color */
r_col[3] = 0;
r_col[2] = 0;
r_col[1] = 0;
r_col[0] = 255;
}
else {
CLAMP(input, 0.0f, 1.0f); CLAMP(input, 0.0f, 1.0f);
weightpaint_color(r_col, coba, input);
if(coba) do_colorband(coba, input, colf);
else weight_to_rgb(colf, input);
col[3] = (unsigned char)(colf[0] * 255.0f);
col[2] = (unsigned char)(colf[1] * 255.0f);
col[1] = (unsigned char)(colf[2] * 255.0f);
col[0] = 255;
} }
} }
@ -956,7 +960,7 @@ void vDM_ColorBand_store(ColorBand *coba)
static void add_weight_mcol_dm(Object *ob, DerivedMesh *dm, int const draw_flag) static void add_weight_mcol_dm(Object *ob, DerivedMesh *dm, int const draw_flag)
{ {
// Mesh *me = ob->data; // UNUSED Mesh *me = ob->data;
MFace *mf = dm->getTessFaceArray(dm); MFace *mf = dm->getTessFaceArray(dm);
MLoop *mloop = dm->getLoopArray(dm), *ml; MLoop *mloop = dm->getLoopArray(dm), *ml;
MPoly *mp = dm->getPolyArray(dm); MPoly *mp = dm->getPolyArray(dm);
@ -968,21 +972,32 @@ static void add_weight_mcol_dm(Object *ob, DerivedMesh *dm, int const draw_flag)
int *origIndex = dm->getVertDataArray(dm, CD_ORIGINDEX); int *origIndex = dm->getVertDataArray(dm, CD_ORIGINDEX);
int defbase_tot = BLI_countlist(&ob->defbase); int defbase_tot = BLI_countlist(&ob->defbase);
char *defbase_sel = MEM_mallocN(defbase_tot * sizeof(char), __func__); const int defbase_act = ob->actdef-1;
int selected = get_selected_defgroups(ob, defbase_sel, defbase_tot); char *dg_flags = MEM_mallocN(defbase_tot * sizeof(char), __func__);
int unselected = defbase_tot - selected; int selected = get_selected_defgroups(ob, dg_flags, defbase_tot);
wtcol = MEM_callocN (sizeof (unsigned char) * totface*4*4, "weightmap"); wtcol = MEM_callocN (sizeof (unsigned char) * totface*4*4, "weightmap");
/*first add colors to the tesselation faces*/ if (me->dvert) {
memset(wtcol, 0x55, sizeof (unsigned char) * totface*4*4); MDeformVert *dvert= me->dvert;
for (i=0; i<totface; i++, mf++) { /*first add colors to the tesselation faces*/
/*origindex being NULL means we're operating on original mesh data*/ memset(wtcol, 0x55, sizeof (unsigned char) * totface*4*4);
calc_weightpaint_vert_color(ob, defbase_tot, coba, mf->v1, &wtcol[(i*4 + 0)*4], defbase_sel, selected, unselected, draw_flag); for (i=0; i<totface; i++, mf++) {
calc_weightpaint_vert_color(ob, defbase_tot, coba, mf->v2, &wtcol[(i*4 + 1)*4], defbase_sel, selected, unselected, draw_flag); /*origindex being NULL means we're operating on original mesh data*/
calc_weightpaint_vert_color(ob, defbase_tot, coba, mf->v3, &wtcol[(i*4 + 2)*4], defbase_sel, selected, unselected, draw_flag); unsigned int fidx= mf->v4 ? 3:2;
if (mf->v4) do {
calc_weightpaint_vert_color(ob, defbase_tot, coba, mf->v4, &wtcol[(i*4 + 3)*4], defbase_sel, selected, unselected, draw_flag); calc_weightpaint_vert_color(&wtcol[(i*4 + fidx)*4],
&dvert[*(&mf->v1 + fidx)], coba,
defbase_tot, defbase_act,
dg_flags, selected, draw_flag);
} while (fidx--);
}
}
else {
/* no weights, fill in zero */
int col_i;
weightpaint_color((unsigned char *)&col_i, coba, 0.0f);
fill_vn_i((int *)wtcol, totface*4, col_i);
} }
CustomData_add_layer(&dm->faceData, CD_WEIGHT_MCOL, CD_ASSIGN, wtcol, totface); CustomData_add_layer(&dm->faceData, CD_WEIGHT_MCOL, CD_ASSIGN, wtcol, totface);
@ -990,17 +1005,21 @@ static void add_weight_mcol_dm(Object *ob, DerivedMesh *dm, int const draw_flag)
/*now add to loops, so the data can be passed through the modifier stack*/ /*now add to loops, so the data can be passed through the modifier stack*/
totloop = 0; totloop = 0;
for (i=0; i<dm->numPolyData; i++, mp++) { for (i=0; i<dm->numPolyData; i++, mp++) {
MDeformVert *dvert= me->dvert;
ml = mloop + mp->loopstart; ml = mloop + mp->loopstart;
for (j=0; j<mp->totloop; j++, ml++, totloop++) { for (j=0; j<mp->totloop; j++, ml++, totloop++) {
BLI_array_growone(wlcol); BLI_array_growone(wlcol);
calc_weightpaint_vert_color(ob, defbase_tot, coba, origIndex ? origIndex[ml->v] : ml->v, calc_weightpaint_vert_color((unsigned char *)&wlcol[totloop],
(unsigned char *)&wlcol[totloop], defbase_sel, selected, unselected, draw_flag); &dvert[origIndex ? origIndex[ml->v] : ml->v], coba,
defbase_tot, defbase_act,
dg_flags, selected, draw_flag);
} }
} }
MEM_freeN(defbase_sel); MEM_freeN(dg_flags);
CustomData_add_layer(&dm->loopData, CD_WEIGHT_MLOOPCOL, CD_ASSIGN, wlcol, totloop); CustomData_add_layer(&dm->loopData, CD_WEIGHT_MLOOPCOL, CD_ASSIGN, wlcol, totloop);
} }

@ -693,7 +693,7 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
float *nors= dm->getTessFaceDataArray(dm, CD_NORMAL); float *nors= dm->getTessFaceDataArray(dm, CD_NORMAL);
MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE); MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
int i, j, orig, *index = DM_get_tessface_data_layer(dm, CD_ORIGINDEX); int i, j, orig, *index = DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
int startFace = 0, lastFlag = 0xdeadbeef; int startFace = 0 /*, lastFlag = 0xdeadbeef */ /* UNUSED */;
MCol *mcol = dm->getTessFaceDataArray(dm, CD_WEIGHT_MCOL); MCol *mcol = dm->getTessFaceDataArray(dm, CD_WEIGHT_MCOL);
if(!mcol) if(!mcol)
mcol = dm->getTessFaceDataArray(dm, CD_MCOL); mcol = dm->getTessFaceDataArray(dm, CD_MCOL);
@ -812,7 +812,7 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
int next_actualFace= dm->drawObject->triangle_to_mface[0]; int next_actualFace= dm->drawObject->triangle_to_mface[0];
glShadeModel( GL_SMOOTH ); glShadeModel( GL_SMOOTH );
lastFlag = 0; /* lastFlag = 0; */ /* UNUSED */
for(i = 0; i < tottri; i++) { for(i = 0; i < tottri; i++) {
int actualFace = next_actualFace; int actualFace = next_actualFace;
int flag = 1; int flag = 1;
@ -2204,7 +2204,7 @@ void CDDM_apply_vert_coords(DerivedMesh *dm, float (*vertCoords)[3])
int i; int i;
/* this will just return the pointer if it wasn't a referenced layer */ /* this will just return the pointer if it wasn't a referenced layer */
vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT); vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT, dm->numVertData);
cddm->mvert = vert; cddm->mvert = vert;
for(i = 0; i < dm->numVertData; ++i, ++vert) for(i = 0; i < dm->numVertData; ++i, ++vert)
@ -2218,7 +2218,7 @@ void CDDM_apply_vert_normals(DerivedMesh *dm, short (*vertNormals)[3])
int i; int i;
/* this will just return the pointer if it wasn't a referenced layer */ /* this will just return the pointer if it wasn't a referenced layer */
vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT); vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT, dm->numVertData);
cddm->mvert = vert; cddm->mvert = vert;
for(i = 0; i < dm->numVertData; ++i, ++vert) for(i = 0; i < dm->numVertData; ++i, ++vert)
@ -2241,7 +2241,7 @@ void CDDM_calc_normals(DerivedMesh *dm)
* need to take care of the side effects here - campbell */ * need to take care of the side effects here - campbell */
#if 0 #if 0
/* we don't want to overwrite any referenced layers */ /* we don't want to overwrite any referenced layers */
cddm->mvert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT); cddm->mvert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT, dm->numVertData);
#endif #endif
if (dm->numTessFaceData == 0) { if (dm->numTessFaceData == 0) {

@ -1701,7 +1701,7 @@ int CustomData_number_of_layers(const CustomData *data, int type)
return number; return number;
} }
void *CustomData_duplicate_referenced_layer(struct CustomData *data, int type) void *CustomData_duplicate_referenced_layer(struct CustomData *data, const int type, const int totelem)
{ {
CustomDataLayer *layer; CustomDataLayer *layer;
int layer_index; int layer_index;
@ -1713,7 +1713,20 @@ void *CustomData_duplicate_referenced_layer(struct CustomData *data, int type)
layer = &data->layers[layer_index]; layer = &data->layers[layer_index];
if (layer->flag & CD_FLAG_NOFREE) { if (layer->flag & CD_FLAG_NOFREE) {
layer->data = MEM_dupallocN(layer->data); /* MEM_dupallocN wont work in case of complex layers, like e.g.
* CD_MDEFORMVERT, which has pointers to allocated data...
* So in case a custom copy function is defined, use it!
*/
const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
if(typeInfo->copy) {
char *dest_data = MEM_mallocN(typeInfo->size * totelem, "CD duplicate ref layer");
typeInfo->copy(layer->data, dest_data, totelem);
layer->data = dest_data;
}
else
layer->data = MEM_dupallocN(layer->data);
layer->flag &= ~CD_FLAG_NOFREE; layer->flag &= ~CD_FLAG_NOFREE;
} }
@ -1721,7 +1734,7 @@ void *CustomData_duplicate_referenced_layer(struct CustomData *data, int type)
} }
void *CustomData_duplicate_referenced_layer_named(struct CustomData *data, void *CustomData_duplicate_referenced_layer_named(struct CustomData *data,
int type, const char *name) const int type, const char *name, const int totelem)
{ {
CustomDataLayer *layer; CustomDataLayer *layer;
int layer_index; int layer_index;
@ -1733,7 +1746,20 @@ void *CustomData_duplicate_referenced_layer_named(struct CustomData *data,
layer = &data->layers[layer_index]; layer = &data->layers[layer_index];
if (layer->flag & CD_FLAG_NOFREE) { if (layer->flag & CD_FLAG_NOFREE) {
layer->data = MEM_dupallocN(layer->data); /* MEM_dupallocN wont work in case of complex layers, like e.g.
* CD_MDEFORMVERT, which has pointers to allocated data...
* So in case a custom copy function is defined, use it!
*/
const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
if(typeInfo->copy) {
char *dest_data = MEM_mallocN(typeInfo->size * totelem, "CD duplicate ref layer");
typeInfo->copy(layer->data, dest_data, totelem);
layer->data = dest_data;
}
else
layer->data = MEM_dupallocN(layer->data);
layer->flag &= ~CD_FLAG_NOFREE; layer->flag &= ~CD_FLAG_NOFREE;
} }

@ -216,7 +216,7 @@ void defvert_normalize_lock(MDeformVert *dvert, const int def_nr_lock)
dvert->dw[0].weight= 1.0f; dvert->dw[0].weight= 1.0f;
} }
else { else {
MDeformWeight *dw_lock; MDeformWeight *dw_lock = NULL;
MDeformWeight *dw; MDeformWeight *dw;
unsigned int i; unsigned int i;
float tot_weight= 0.0f; float tot_weight= 0.0f;

@ -3214,7 +3214,7 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface,
/* hit data */ /* hit data */
float hitCoord[3]; float hitCoord[3];
int hitFace = -1; int hitFace = -1;
short hitQuad; short hitQuad = 0;
/* Supersampling factor */ /* Supersampling factor */
if (samples > 1 && surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) if (samples > 1 && surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ)
@ -4641,7 +4641,7 @@ static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, Scene *sc
#pragma omp parallel for schedule(static) #pragma omp parallel for schedule(static)
for (index=0; index<sData->total_points; index++) for (index=0; index<sData->total_points; index++)
{ {
float prev_point[3]; float prev_point[3] = {0.0f, 0.0f, 0.0f};
if (do_velocity_data && !new_bdata) { if (do_velocity_data && !new_bdata) {
copy_v3_v3(prev_point, bData->realCoord[bData->s_pos[index]].v); copy_v3_v3(prev_point, bData->realCoord[bData->s_pos[index]].v);
} }

@ -231,6 +231,7 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm,
BLI_array_declare(fverts); BLI_array_declare(fverts);
EdgeHash *ehash; EdgeHash *ehash;
float creaseFactor = (float)ccgSubSurf_getSubdivisionLevels(ss); float creaseFactor = (float)ccgSubSurf_getSubdivisionLevels(ss);
float uv[3]= {0.0f, 0.0f, 0.0f}; /* only first 2 values are written into */
limit[0]= limit[1]= STD_UV_CONNECT_LIMIT; limit[0]= limit[1]= STD_UV_CONNECT_LIMIT;
vmap= make_uv_vert_map(mpoly, mloop, mloopuv, totface, totvert, 0, limit); vmap= make_uv_vert_map(mpoly, mloop, mloopuv, totface, totvert, 0, limit);
@ -254,11 +255,8 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm,
if (v->separate) { if (v->separate) {
CCGVert *ssv; CCGVert *ssv;
CCGVertHDL vhdl = SET_INT_IN_POINTER(v->f*4 + v->tfindex); CCGVertHDL vhdl = SET_INT_IN_POINTER(v->f*4 + v->tfindex);
float uv[3];
uv[0]= mloopuv[mpoly[v->f].loopstart + v->tfindex].uv[0]; copy_v2_v2(uv, mloopuv[mpoly[v->f].loopstart + v->tfindex].uv);
uv[1]= mloopuv[mpoly[v->f].loopstart + v->tfindex].uv[1];
uv[2]= 0.0f;
ccgSubSurf_syncVert(ss, vhdl, uv, seam, &ssv); ccgSubSurf_syncVert(ss, vhdl, uv, seam, &ssv);
} }

@ -1154,7 +1154,7 @@ int BKE_tracking_next(MovieTrackingContext *context)
#pragma omp parallel for private(a) shared(ibuf_new, ok) if(map_size>1) #pragma omp parallel for private(a) shared(ibuf_new, ok) if(map_size>1)
for(a= 0; a<map_size; a++) { for(a= 0; a<map_size; a++) {
TrackContext *track_context; TrackContext *track_context = NULL;
MovieTrackingTrack *track; MovieTrackingTrack *track;
MovieTrackingMarker *marker; MovieTrackingMarker *marker;

@ -199,6 +199,7 @@ double dot_vn_vn(const float *array_src_a, const float *array_src_b, const int s
float normalize_vn_vn(float *array_tar, const float *array_src, const int size); float normalize_vn_vn(float *array_tar, const float *array_src, const int size);
float normalize_vn(float *array_tar, const int size); float normalize_vn(float *array_tar, const int size);
void range_vn_i(int *array_tar, const int size, const int start); void range_vn_i(int *array_tar, const int size, const int start);
void range_vn_fl(float *array_tar, const int size, const float start, const float step);
void negate_vn(float *array_tar, const int size); void negate_vn(float *array_tar, const int size);
void negate_vn_vn(float *array_tar, const float *array_src, const int size); void negate_vn_vn(float *array_tar, const float *array_src, const int size);
void mul_vn_fl(float *array_tar, const int size, const float f); void mul_vn_fl(float *array_tar, const int size, const float f);

@ -279,24 +279,22 @@
# endif # endif
# if defined(__GNUC__) || defined(_MSC_VER) /* check __func__ is available */ # if defined(__GNUC__) || defined(_MSC_VER) /* check __func__ is available */
# define BLI_assert(a) \ # define BLI_assert(a) \
do { \ (void)((!(a)) ? ( \
if (!(a)) { \ ( \
fprintf(stderr, \ fprintf(stderr, \
"BLI_assert failed: %s, %s(), %d at \'%s\'\n", \ "BLI_assert failed: %s, %s(), %d at \'%s\'\n", \
__FILE__, __func__, __LINE__, STRINGIFY(a)); \ __FILE__, __func__, __LINE__, STRINGIFY(a)), \
_dummy_abort(); \ _dummy_abort(), \
} \ NULL)) : NULL)
} while (0)
# else # else
# define BLI_assert(a) \ # define BLI_assert(a) \
do { \ (void)((!(a)) ? ( \
if (0 == (a)) { \ ( \
fprintf(stderr, \ fprintf(stderr, \
"BLI_assert failed: %s, %d at \'%s\'\n", \ "BLI_assert failed: %s, %d at \'%s\'\n", \
__FILE__, __LINE__, STRINGIFY(a)); \ __FILE__, __LINE__, STRINGIFY(a)), \
_dummy_abort(); \ _dummy_abort(), \
} \ NULL)) : NULL)
} while (0)
# endif # endif
#else #else
# define BLI_assert(a) (void)0 # define BLI_assert(a) (void)0

@ -199,7 +199,11 @@ void makeFilesAbsolute(Main *bmain, const char *basedir, ReportList *reports)
- filesize: filesize for the file - filesize: filesize for the file
*/ */
#define MAX_RECUR 16 #define MAX_RECUR 16
static int findFileRecursive(char *filename_new, const char *dirname, const char *filename, int *filesize, int *recur_depth) static int findFileRecursive(char *filename_new,
const char *dirname,
const char *filename,
int *filesize,
int *recur_depth)
{ {
/* file searching stuff */ /* file searching stuff */
DIR *dir; DIR *dir;
@ -314,7 +318,11 @@ static int rewrite_path_fixed(char *path, BPathVisitor visit_cb, const char *abs
} }
} }
static int rewrite_path_fixed_dirfile(char path_dir[FILE_MAXDIR], char path_file[FILE_MAXFILE], BPathVisitor visit_cb, const char *absbase, void *userdata) static int rewrite_path_fixed_dirfile(char path_dir[FILE_MAXDIR],
char path_file[FILE_MAXFILE],
BPathVisitor visit_cb,
const char *absbase,
void *userdata)
{ {
char path_src[FILE_MAX]; char path_src[FILE_MAX];
char path_dst[FILE_MAX]; char path_dst[FILE_MAX];
@ -496,7 +504,8 @@ void bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int fla
SEQ_BEGIN(scene->ed, seq) { SEQ_BEGIN(scene->ed, seq) {
if (SEQ_HAS_PATH(seq)) { if (SEQ_HAS_PATH(seq)) {
if (ELEM(seq->type, SEQ_MOVIE, SEQ_SOUND)) { if (ELEM(seq->type, SEQ_MOVIE, SEQ_SOUND)) {
rewrite_path_fixed_dirfile(seq->strip->dir, seq->strip->stripdata->name, visit_cb, absbase, bpath_user_data); rewrite_path_fixed_dirfile(seq->strip->dir, seq->strip->stripdata->name,
visit_cb, absbase, bpath_user_data);
} }
else if (seq->type == SEQ_IMAGE) { else if (seq->type == SEQ_IMAGE) {
/* might want an option not to loop over all strips */ /* might want an option not to loop over all strips */
@ -510,7 +519,8 @@ void bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int fla
} }
for(i= 0; i < len; i++, se++) { for(i= 0; i < len; i++, se++) {
rewrite_path_fixed_dirfile(seq->strip->dir, se->name, visit_cb, absbase, bpath_user_data); rewrite_path_fixed_dirfile(seq->strip->dir, se->name,
visit_cb, absbase, bpath_user_data);
} }
} }
else { else {

@ -430,6 +430,15 @@ void range_vn_i(int *array_tar, const int size, const int start)
while(i--) { *(array_pt--) = j--; } while(i--) { *(array_pt--) = j--; }
} }
void range_vn_fl(float *array_tar, const int size, const float start, const float step)
{
float *array_pt= array_tar + (size-1);
int i= size;
while(i--) {
*(array_pt--) = start + step * (float)(i);
}
}
void negate_vn(float *array_tar, const int size) void negate_vn(float *array_tar, const int size)
{ {
float *array_pt= array_tar + (size-1); float *array_pt= array_tar + (size-1);

@ -330,7 +330,6 @@ static void uiPanelPop(uiBlock *UNUSED(block))
#endif #endif
/* triangle 'icon' for panel header */ /* triangle 'icon' for panel header */
/* NOTE - this seems to be only used for hiding nodes now */
void UI_DrawTriIcon(float x, float y, char dir) void UI_DrawTriIcon(float x, float y, char dir)
{ {
if(dir=='h') { if(dir=='h') {

@ -1071,18 +1071,16 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but)
/* copy to int, gets projected if possible too */ /* copy to int, gets projected if possible too */
x1= x1f; y1= y1f; x2= x2f; y2= y2f; x1= x1f; y1= y1f; x2= x2f; y2= y2f;
if(butregion) { if(butregion->v2d.cur.xmin != butregion->v2d.cur.xmax) {
if(butregion->v2d.cur.xmin != butregion->v2d.cur.xmax) { UI_view2d_to_region_no_clip(&butregion->v2d, x1f, y1f, &x1, &y1);
UI_view2d_to_region_no_clip(&butregion->v2d, x1f, y1f, &x1, &y1); UI_view2d_to_region_no_clip(&butregion->v2d, x2f, y2f, &x2, &y2);
UI_view2d_to_region_no_clip(&butregion->v2d, x2f, y2f, &x2, &y2);
}
x1 += butregion->winrct.xmin;
x2 += butregion->winrct.xmin;
y1 += butregion->winrct.ymin;
y2 += butregion->winrct.ymin;
} }
x1 += butregion->winrct.xmin;
x2 += butregion->winrct.xmin;
y1 += butregion->winrct.ymin;
y2 += butregion->winrct.ymin;
wm_window_get_size(CTX_wm_window(C), &winx, &winy); wm_window_get_size(CTX_wm_window(C), &winx, &winy);
if(x2 > winx) { if(x2 > winx) {
@ -1096,7 +1094,8 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but)
x2= winx; x2= winx;
} }
} }
if(y1 < 0) { /* XXX butregion NULL check?, there is one above */
if(y1 < 0) {
int newy1; int newy1;
UI_view2d_to_region_no_clip(&butregion->v2d, 0, but->y2 + ofsy, NULL, &newy1); UI_view2d_to_region_no_clip(&butregion->v2d, 0, but->y2 + ofsy, NULL, &newy1);
newy1 += butregion->winrct.ymin; newy1 += butregion->winrct.ymin;

@ -894,7 +894,7 @@ static void moveCloserToDistanceFromPlane(Scene *scene, Object *ob, Mesh *me, in
int totweight = dvert->totweight; int totweight = dvert->totweight;
float oldw = 0; float oldw = 0;
float oldPos[3] = {0}; float oldPos[3] = {0};
float vc, hc, dist; float vc, hc, dist = 0.0f;
int i, k; int i, k;
float (*changes)[2] = MEM_mallocN(sizeof(float *)*totweight*2, "vertHorzChange"); float (*changes)[2] = MEM_mallocN(sizeof(float *)*totweight*2, "vertHorzChange");
float *dists = MEM_mallocN(sizeof(float)*totweight, "distance"); float *dists = MEM_mallocN(sizeof(float)*totweight, "distance");

@ -1688,7 +1688,7 @@ static void calc_flatten_center(Sculpt *sd, Object *ob, PBVHNode **nodes, int to
if(ss->cache->original) { if(ss->cache->original) {
BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) { BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) {
if(sculpt_brush_test_fast(&test, unode->co[vd.i])) { if(sculpt_brush_test_fast(&test, unode->co[vd.i])) {
add_v3_v3(private_fc, vd.co); add_v3_v3(private_fc, unode->co[vd.i]);
private_count++; private_count++;
} }
} }
@ -1758,7 +1758,7 @@ static void calc_area_normal_and_flatten_center(Sculpt *sd, Object *ob, PBVHNode
add_norm_if(ss->cache->view_normal, private_an, private_out_flip, fno); add_norm_if(ss->cache->view_normal, private_an, private_out_flip, fno);
// fc // fc
add_v3_v3(private_fc, vd.co); add_v3_v3(private_fc, unode->co[vd.i]);
private_count++; private_count++;
} }
} }

@ -562,6 +562,18 @@ static void node_draw_preview(bNodePreview *preview, rctf *prv)
} }
/* common handle function for operator buttons that need to select the node first */
static void node_toggle_button_cb(struct bContext *C, void *node_argv, void *op_argv)
{
bNode *node = (bNode*)node_argv;
const char *opname = (const char *)op_argv;
/* select & activate only the button's node */
node_select_single(C, node);
WM_operator_name_call(C, opname, WM_OP_INVOKE_DEFAULT, NULL);
}
static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node) static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node)
{ {
bNodeSocket *sock; bNodeSocket *sock;
@ -601,39 +613,34 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
uiSetRoundBox(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT); uiSetRoundBox(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT);
uiRoundBox(rct->xmin, rct->ymax-NODE_DY, rct->xmax, rct->ymax, BASIS_RAD); uiRoundBox(rct->xmin, rct->ymax-NODE_DY, rct->xmax, rct->ymax, BASIS_RAD);
/* show/hide icons, note this sequence is copied in do_header_node() node_state.c */ /* show/hide icons */
iconofs= rct->xmax - 7.0f; iconofs= rct->xmax - 7.0f;
/* preview */
if(node->typeinfo->flag & NODE_PREVIEW) { if(node->typeinfo->flag & NODE_PREVIEW) {
float alpha = (node->flag & (NODE_ACTIVE_ID|NODE_DO_OUTPUT))? 1.0f: 0.5f; uiBut *but;
iconofs-=iconbutw; iconofs-=iconbutw;
uiDefIconBut(node->block, LABEL, B_REDR, ICON_MATERIAL, iconofs, rct->ymax-NODE_DY, uiBlockSetEmboss(node->block, UI_EMBOSSN);
iconbutw, UI_UNIT_Y, NULL, 0.0, 0.0, 1.0, alpha, ""); but = uiDefIconBut(node->block, TOGBUT, B_REDR, ICON_MATERIAL,
iconofs, rct->ymax-NODE_DY, iconbutw, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
uiButSetFunc(but, node_toggle_button_cb, node, (void*)"NODE_OT_preview_toggle");
/* XXX this does not work when node is activated and the operator called right afterwards,
* since active ID is not updated yet (needs to process the notifier).
* This can only work as visual indicator!
*/
// if (!(node->flag & (NODE_ACTIVE_ID|NODE_DO_OUTPUT)))
// uiButSetFlag(but, UI_BUT_DISABLED);
uiBlockSetEmboss(node->block, UI_EMBOSS);
} }
/* group edit */
if(node->type == NODE_GROUP) { if(node->type == NODE_GROUP) {
uiBut *but;
iconofs-=iconbutw; iconofs-=iconbutw;
uiDefIconBut(node->block, LABEL, B_REDR, ICON_NODETREE, iconofs, rct->ymax-NODE_DY, uiBlockSetEmboss(node->block, UI_EMBOSSN);
iconbutw, UI_UNIT_Y, NULL, 0.0, 0.0, 1.0, 0.5, ""); but = uiDefIconBut(node->block, TOGBUT, B_REDR, ICON_NODETREE,
} iconofs, rct->ymax-NODE_DY, iconbutw, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
if(node->typeinfo->flag & NODE_OPTIONS) { uiButSetFunc(but, node_toggle_button_cb, node, (void*)"NODE_OT_group_edit");
iconofs-=iconbutw; uiBlockSetEmboss(node->block, UI_EMBOSS);
uiDefIconBut(node->block, LABEL, B_REDR, ICON_BUTS, iconofs, rct->ymax-NODE_DY,
iconbutw, UI_UNIT_Y, NULL, 0.0, 0.0, 1.0, 0.5, "");
}
{ /* always hide/reveal unused sockets */
// XXX re-enable
/* int shade;
if(node_has_hidden_sockets(node))
shade= -40;
else
shade= -90; */
iconofs-=iconbutw;
uiDefIconBut(node->block, LABEL, B_REDR, ICON_PLUS, iconofs, rct->ymax-NODE_DY,
iconbutw, UI_UNIT_Y, NULL, 0.0, 0.0, 1.0, 0.5, "");
} }
/* title */ /* title */
@ -643,7 +650,19 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
UI_ThemeColorBlendShade(TH_TEXT, color_id, 0.4f, 10); UI_ThemeColorBlendShade(TH_TEXT, color_id, 0.4f, 10);
/* open/close entirely? */ /* open/close entirely? */
UI_DrawTriIcon(rct->xmin+10.0f, rct->ymax-NODE_DY/2.0f, 'v'); {
uiBut *but;
int but_size = UI_UNIT_X *0.6f;
/* XXX button uses a custom triangle draw below, so make it invisible without icon */
uiBlockSetEmboss(node->block, UI_EMBOSSN);
but = uiDefBut(node->block, TOGBUT, B_REDR, "",
rct->xmin+10.0f-but_size/2, rct->ymax-NODE_DY/2.0f-but_size/2, but_size, but_size, NULL, 0, 0, 0, 0, "");
uiButSetFunc(but, node_toggle_button_cb, node, (void*)"NODE_OT_hide_toggle");
uiBlockSetEmboss(node->block, UI_EMBOSS);
/* custom draw function for this button */
UI_DrawTriIcon(rct->xmin+10.0f, rct->ymax-NODE_DY/2.0f, 'v');
}
/* this isn't doing anything for the label, so commenting out /* this isn't doing anything for the label, so commenting out
if(node->flag & SELECT) if(node->flag & SELECT)
@ -789,7 +808,19 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b
UI_ThemeColorBlendShade(TH_TEXT, color_id, 0.4f, 10); UI_ThemeColorBlendShade(TH_TEXT, color_id, 0.4f, 10);
/* open entirely icon */ /* open entirely icon */
UI_DrawTriIcon(rct->xmin+10.0f, centy, 'h'); {
uiBut *but;
int but_size = UI_UNIT_X *0.6f;
/* XXX button uses a custom triangle draw below, so make it invisible without icon */
uiBlockSetEmboss(node->block, UI_EMBOSSN);
but = uiDefBut(node->block, TOGBUT, B_REDR, "",
rct->xmin+10.0f-but_size/2, centy-but_size/2, but_size, but_size, NULL, 0, 0, 0, 0, "");
uiButSetFunc(but, node_toggle_button_cb, node, (void*)"NODE_OT_hide_toggle");
uiBlockSetEmboss(node->block, UI_EMBOSS);
/* custom draw function for this button */
UI_DrawTriIcon(rct->xmin+10.0f, centy, 'h');
}
/* disable lines */ /* disable lines */
if(node->flag & NODE_MUTED) if(node->flag & NODE_MUTED)

@ -690,108 +690,6 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
} }
} }
static int compare_nodes(bNode *a, bNode *b)
{
bNode *parent;
/* These tell if either the node or any of the parent nodes is selected.
* A selected parent means an unselected node is also in foreground!
*/
int a_select=(a->flag & NODE_SELECT), b_select=(b->flag & NODE_SELECT);
int a_active=(a->flag & NODE_ACTIVE), b_active=(b->flag & NODE_ACTIVE);
/* if one is an ancestor of the other */
/* XXX there might be a better sorting algorithm for stable topological sort, this is O(n^2) worst case */
for (parent = a->parent; parent; parent=parent->parent) {
/* if b is an ancestor, it is always behind a */
if (parent==b)
return 1;
/* any selected ancestor moves the node forward */
if (parent->flag & NODE_ACTIVE)
a_active = 1;
if (parent->flag & NODE_SELECT)
a_select = 1;
}
for (parent = b->parent; parent; parent=parent->parent) {
/* if a is an ancestor, it is always behind b */
if (parent==a)
return 0;
/* any selected ancestor moves the node forward */
if (parent->flag & NODE_ACTIVE)
b_active = 1;
if (parent->flag & NODE_SELECT)
b_select = 1;
}
/* if one of the nodes is in the background and the other not */
if ((a->flag & NODE_BACKGROUND) && !(b->flag & NODE_BACKGROUND))
return 0;
else if (!(a->flag & NODE_BACKGROUND) && (b->flag & NODE_BACKGROUND))
return 1;
/* if one has a higher selection state (active > selected > nothing) */
if (!b_active && a_active)
return 1;
else if (!b_select && (a_active || a_select))
return 1;
return 0;
}
/* Sorts nodes by selection: unselected nodes first, then selected,
* then the active node at the very end. Relative order is kept intact!
*/
void node_sort(bNodeTree *ntree)
{
/* merge sort is the algorithm of choice here */
bNode *first_a, *first_b, *node_a, *node_b, *tmp;
int totnodes= BLI_countlist(&ntree->nodes);
int k, a, b;
k = 1;
while (k < totnodes) {
first_a = first_b = ntree->nodes.first;
do {
/* setup first_b pointer */
for (b=0; b < k && first_b; ++b) {
first_b = first_b->next;
}
/* all batches merged? */
if (first_b==NULL)
break;
/* merge batches */
node_a = first_a;
node_b = first_b;
a = b = 0;
while (a < k && b < k && node_b) {
if (compare_nodes(node_a, node_b)==0) {
node_a = node_a->next;
++a;
}
else {
tmp = node_b;
node_b = node_b->next;
++b;
BLI_remlink(&ntree->nodes, tmp);
BLI_insertlinkbefore(&ntree->nodes, node_a, tmp);
}
}
/* setup first pointers for next batch */
first_b = node_b;
for (; b < k; ++b) {
/* all nodes sorted? */
if (first_b==NULL)
break;
first_b = first_b->next;
}
first_a = first_b;
} while (first_b);
k = k << 1;
}
}
static int inside_rctf(rctf *bounds, rctf *rect) static int inside_rctf(rctf *bounds, rctf *rect)
{ {
return (bounds->xmin <= rect->xmin && bounds->xmax >= rect->xmax return (bounds->xmin <= rect->xmin && bounds->xmax >= rect->xmax
@ -940,7 +838,7 @@ static int node_group_edit_exec(bContext *C, wmOperator *UNUSED(op))
ED_preview_kill_jobs(C); ED_preview_kill_jobs(C);
if (snode->nodetree==snode->edittree) { if (snode->nodetree==snode->edittree) {
bNode *gnode= nodeGetActive(snode->nodetree); bNode *gnode = nodeGetActive(snode->edittree);
snode_make_group_editable(snode, gnode); snode_make_group_editable(snode, gnode);
} }
else else
@ -955,8 +853,11 @@ static int node_group_edit_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(e
{ {
SpaceNode *snode = CTX_wm_space_node(C); SpaceNode *snode = CTX_wm_space_node(C);
bNode *gnode; bNode *gnode;
gnode= nodeGetActive(snode->edittree); gnode = nodeGetActive(snode->edittree);
if (!gnode)
return OPERATOR_CANCELLED;
/* XXX callback? */ /* XXX callback? */
if(gnode && gnode->id && GS(gnode->id->name)==ID_NT && gnode->id->lib) { if(gnode && gnode->id && GS(gnode->id->name)==ID_NT && gnode->id->lib) {
uiPupMenuOkee(C, op->type->idname, "Make group local?"); uiPupMenuOkee(C, op->type->idname, "Make group local?");
@ -1696,90 +1597,8 @@ void NODE_OT_resize(wmOperatorType *ot)
ot->flag= OPTYPE_BLOCKING; ot->flag= OPTYPE_BLOCKING;
} }
/* ********************** select ******************** */
/* ********************** hidden sockets ******************** */
/* no undo here! */
void node_deselectall(SpaceNode *snode)
{
bNode *node;
for(node= snode->edittree->nodes.first; node; node= node->next)
node->flag &= ~SELECT;
}
/* return 1 if we need redraw otherwise zero. */
int node_select_same_type(SpaceNode *snode)
{
bNode *nac, *p;
int redraw;
/* search for the active node. */
for (nac= snode->edittree->nodes.first; nac; nac= nac->next) {
if (nac->flag & SELECT)
break;
}
/* no active node, return. */
if (!nac)
return(0);
redraw= 0;
for (p= snode->edittree->nodes.first; p; p= p->next) {
if (p->type != nac->type && p->flag & SELECT) {
/* if it's selected but different type, unselect */
redraw= 1;
p->flag &= ~SELECT;
}
else if (p->type == nac->type && (!(p->flag & SELECT))) {
/* if it's the same type and is not selected, select! */
redraw= 1;
p->flag |= SELECT;
}
}
return(redraw);
}
/* return 1 if we need redraw, otherwise zero.
* dir can be 0 == next or 0 != prev.
*/
int node_select_same_type_np(SpaceNode *snode, int dir)
{
bNode *nac, *p;
/* search the active one. */
for (nac= snode->edittree->nodes.first; nac; nac= nac->next) {
if (nac->flag & SELECT)
break;
}
/* no active node, return. */
if (!nac)
return(0);
if (dir == 0)
p= nac->next;
else
p= nac->prev;
while (p) {
/* Now search the next with the same type. */
if (p->type == nac->type)
break;
if (dir == 0)
p= p->next;
else
p= p->prev;
}
if (p) {
node_deselectall(snode);
p->flag |= SELECT;
return(1);
}
return(0);
}
int node_has_hidden_sockets(bNode *node) int node_has_hidden_sockets(bNode *node)
{ {
@ -1794,6 +1613,31 @@ int node_has_hidden_sockets(bNode *node)
return 0; return 0;
} }
/* note: call node_tree_verify_groups(snode->nodetree) after this
*/
void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set)
{
bNodeSocket *sock;
if(set==0) {
for(sock= node->inputs.first; sock; sock= sock->next)
sock->flag &= ~SOCK_HIDDEN;
for(sock= node->outputs.first; sock; sock= sock->next)
sock->flag &= ~SOCK_HIDDEN;
}
else {
/* hide unused sockets */
for(sock= node->inputs.first; sock; sock= sock->next) {
if(sock->link==NULL)
sock->flag |= SOCK_HIDDEN;
}
for(sock= node->outputs.first; sock; sock= sock->next) {
if(nodeCountSocketLinks(snode->edittree, sock)==0)
sock->flag |= SOCK_HIDDEN;
}
}
}
static void node_link_viewer(SpaceNode *snode, bNode *tonode) static void node_link_viewer(SpaceNode *snode, bNode *tonode)
{ {
bNode *node; bNode *node;
@ -2232,7 +2076,7 @@ bNode *node_add_node(SpaceNode *snode, Main *bmain, Scene *scene, bNodeTemplate
{ {
bNode *node= NULL, *gnode; bNode *node= NULL, *gnode;
node_deselectall(snode); node_deselect_all(snode);
node = nodeAddNode(snode->edittree, ntemp); node = nodeAddNode(snode->edittree, ntemp);
@ -3130,15 +2974,21 @@ void NODE_OT_group_make(wmOperatorType *ot)
static void node_flag_toggle_exec(SpaceNode *snode, int toggle_flag) static void node_flag_toggle_exec(SpaceNode *snode, int toggle_flag)
{ {
int tot_eq= 0, tot_neq= 0;
bNode *node; bNode *node;
int tot_eq= 0, tot_neq= 0;
/* Toggles the flag on all selected nodes.
* If the flag is set on all nodes it is unset.
* If the flag is not set on all nodes, it is set.
*/
for(node= snode->edittree->nodes.first; node; node= node->next) { for(node= snode->edittree->nodes.first; node; node= node->next) {
if(node->flag & SELECT) { if(node->flag & SELECT) {
if(toggle_flag== NODE_PREVIEW && (node->typeinfo->flag & NODE_PREVIEW)==0) if(toggle_flag== NODE_PREVIEW && (node->typeinfo->flag & NODE_PREVIEW)==0)
continue; continue;
if(toggle_flag== NODE_OPTIONS && (node->typeinfo->flag & NODE_OPTIONS)==0)
continue;
if(node->flag & toggle_flag) if(node->flag & toggle_flag)
tot_eq++; tot_eq++;
else else
@ -3147,10 +2997,12 @@ static void node_flag_toggle_exec(SpaceNode *snode, int toggle_flag)
} }
for(node= snode->edittree->nodes.first; node; node= node->next) { for(node= snode->edittree->nodes.first; node; node= node->next) {
if(node->flag & SELECT) { if(node->flag & SELECT) {
if(toggle_flag== NODE_PREVIEW && (node->typeinfo->flag & NODE_PREVIEW)==0) if(toggle_flag== NODE_PREVIEW && (node->typeinfo->flag & NODE_PREVIEW)==0)
continue; continue;
if(toggle_flag== NODE_OPTIONS && (node->typeinfo->flag & NODE_OPTIONS)==0)
continue;
if( (tot_eq && tot_neq) || tot_eq==0) if( (tot_eq && tot_neq) || tot_eq==0)
node->flag |= toggle_flag; node->flag |= toggle_flag;
else else
@ -3159,7 +3011,7 @@ static void node_flag_toggle_exec(SpaceNode *snode, int toggle_flag)
} }
} }
static int node_hide_exec(bContext *C, wmOperator *UNUSED(op)) static int node_hide_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{ {
SpaceNode *snode= CTX_wm_space_node(C); SpaceNode *snode= CTX_wm_space_node(C);
@ -3182,14 +3034,14 @@ void NODE_OT_hide_toggle(wmOperatorType *ot)
ot->idname= "NODE_OT_hide_toggle"; ot->idname= "NODE_OT_hide_toggle";
/* callbacks */ /* callbacks */
ot->exec= node_hide_exec; ot->exec= node_hide_toggle_exec;
ot->poll= ED_operator_node_active; ot->poll= ED_operator_node_active;
/* flags */ /* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
} }
static int node_preview_exec(bContext *C, wmOperator *UNUSED(op)) static int node_preview_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{ {
SpaceNode *snode= CTX_wm_space_node(C); SpaceNode *snode= CTX_wm_space_node(C);
@ -3214,7 +3066,37 @@ void NODE_OT_preview_toggle(wmOperatorType *ot)
ot->idname= "NODE_OT_preview_toggle"; ot->idname= "NODE_OT_preview_toggle";
/* callbacks */ /* callbacks */
ot->exec= node_preview_exec; ot->exec= node_preview_toggle_exec;
ot->poll= ED_operator_node_active;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
static int node_options_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceNode *snode= CTX_wm_space_node(C);
/* sanity checking (poll callback checks this already) */
if((snode == NULL) || (snode->edittree == NULL))
return OPERATOR_CANCELLED;
node_flag_toggle_exec(snode, NODE_OPTIONS);
snode_notify(C, snode);
return OPERATOR_FINISHED;
}
void NODE_OT_options_toggle(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Toggle Node Options";
ot->description= "Toggle option buttons display for selected nodes";
ot->idname= "NODE_OT_options_toggle";
/* callbacks */
ot->exec= node_options_toggle_exec;
ot->poll= ED_operator_node_active; ot->poll= ED_operator_node_active;
/* flags */ /* flags */
@ -3225,7 +3107,7 @@ static int node_socket_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{ {
SpaceNode *snode= CTX_wm_space_node(C); SpaceNode *snode= CTX_wm_space_node(C);
bNode *node; bNode *node;
int hidden= 0; int hidden;
/* sanity checking (poll callback checks this already) */ /* sanity checking (poll callback checks this already) */
if((snode == NULL) || (snode->edittree == NULL)) if((snode == NULL) || (snode->edittree == NULL))
@ -3233,6 +3115,8 @@ static int node_socket_toggle_exec(bContext *C, wmOperator *UNUSED(op))
ED_preview_kill_jobs(C); ED_preview_kill_jobs(C);
/* Toggle for all selected nodes */
hidden = 0;
for(node= snode->edittree->nodes.first; node; node= node->next) { for(node= snode->edittree->nodes.first; node; node= node->next) {
if(node->flag & SELECT) { if(node->flag & SELECT) {
if(node_has_hidden_sockets(node)) { if(node_has_hidden_sockets(node)) {
@ -3241,7 +3125,7 @@ static int node_socket_toggle_exec(bContext *C, wmOperator *UNUSED(op))
} }
} }
} }
for(node= snode->edittree->nodes.first; node; node= node->next) { for(node= snode->edittree->nodes.first; node; node= node->next) {
if(node->flag & SELECT) { if(node->flag & SELECT) {
node_set_hidden_sockets(snode, node, !hidden); node_set_hidden_sockets(snode, node, !hidden);
@ -3570,7 +3454,7 @@ static int node_add_file_exec(bContext *C, wmOperator *op)
} }
} }
node_deselectall(snode); node_deselect_all(snode);
if (snode->nodetree->type==NTREE_COMPOSIT) if (snode->nodetree->type==NTREE_COMPOSIT)
ntemp.type = CMP_NODE_IMAGE; ntemp.type = CMP_NODE_IMAGE;

@ -82,17 +82,23 @@ void node_operatortypes(void);
void node_keymap(wmKeyConfig *keyconf); void node_keymap(wmKeyConfig *keyconf);
/* node_select.c */ /* node_select.c */
void node_deselect_all(struct SpaceNode *snode);
int node_select_same_type(struct SpaceNode *snode);
int node_select_same_type_np(struct SpaceNode *snode, int dir);
void node_select_single(struct bContext *C, struct bNode *node);
void NODE_OT_select(struct wmOperatorType *ot); void NODE_OT_select(struct wmOperatorType *ot);
void NODE_OT_select_all(wmOperatorType *ot); void NODE_OT_select_all(wmOperatorType *ot);
void NODE_OT_select_linked_to(wmOperatorType *ot); void NODE_OT_select_linked_to(wmOperatorType *ot);
void NODE_OT_select_linked_from(wmOperatorType *ot); void NODE_OT_select_linked_from(wmOperatorType *ot);
void NODE_OT_visibility_toggle(struct wmOperatorType *ot);
void NODE_OT_view_all(struct wmOperatorType *ot);
void NODE_OT_select_border(struct wmOperatorType *ot); void NODE_OT_select_border(struct wmOperatorType *ot);
void NODE_OT_select_same_type(struct wmOperatorType *ot); void NODE_OT_select_same_type(struct wmOperatorType *ot);
void NODE_OT_select_same_type_next(wmOperatorType *ot); void NODE_OT_select_same_type_next(wmOperatorType *ot);
void NODE_OT_select_same_type_prev(wmOperatorType *ot); void NODE_OT_select_same_type_prev(wmOperatorType *ot);
/* node_state.c */
void NODE_OT_view_all(struct wmOperatorType *ot);
/* drawnode.c */ /* drawnode.c */
void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link); void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link);
void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link, int th_col1, int do_shaded, int th_col2, int do_triple, int th_col3 ); void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link, int th_col1, int do_shaded, int th_col2, int do_triple, int th_col3 );
@ -108,10 +114,6 @@ void snode_dag_update(bContext *C, SpaceNode *snode);
bNode *node_add_node(struct SpaceNode *snode, struct Main *bmain, struct Scene *scene, struct bNodeTemplate *ntemp, float locx, float locy); bNode *node_add_node(struct SpaceNode *snode, struct Main *bmain, struct Scene *scene, struct bNodeTemplate *ntemp, float locx, float locy);
void snode_set_context(SpaceNode *snode, Scene *scene); void snode_set_context(SpaceNode *snode, Scene *scene);
void snode_make_group_editable(SpaceNode *snode, bNode *gnode); void snode_make_group_editable(SpaceNode *snode, bNode *gnode);
void node_sort(struct bNodeTree *ntree);
void node_deselectall(SpaceNode *snode);
int node_select_same_type(SpaceNode *snode);
int node_select_same_type_np(SpaceNode *snode, int dir);
void snode_composite_job(const struct bContext *C, ScrArea *sa); void snode_composite_job(const struct bContext *C, ScrArea *sa);
bNode *node_tree_get_editgroup(bNodeTree *ntree); bNode *node_tree_get_editgroup(bNodeTree *ntree);
void node_tree_verify_groups(bNodeTree *nodetree); void node_tree_verify_groups(bNodeTree *nodetree);
@ -141,6 +143,7 @@ void NODE_OT_mute_toggle(struct wmOperatorType *ot);
void NODE_OT_hide_toggle(struct wmOperatorType *ot); void NODE_OT_hide_toggle(struct wmOperatorType *ot);
void NODE_OT_hide_socket_toggle(struct wmOperatorType *ot); void NODE_OT_hide_socket_toggle(struct wmOperatorType *ot);
void NODE_OT_preview_toggle(struct wmOperatorType *ot); void NODE_OT_preview_toggle(struct wmOperatorType *ot);
void NODE_OT_options_toggle(struct wmOperatorType *ot);
void NODE_OT_show_cyclic_dependencies(struct wmOperatorType *ot); void NODE_OT_show_cyclic_dependencies(struct wmOperatorType *ot);
void NODE_OT_link_viewer(struct wmOperatorType *ot); void NODE_OT_link_viewer(struct wmOperatorType *ot);

@ -59,10 +59,11 @@ void node_operatortypes(void)
WM_operatortype_append(NODE_OT_select_same_type_prev); WM_operatortype_append(NODE_OT_select_same_type_prev);
WM_operatortype_append(NODE_OT_view_all); WM_operatortype_append(NODE_OT_view_all);
WM_operatortype_append(NODE_OT_visibility_toggle);
WM_operatortype_append(NODE_OT_mute_toggle); WM_operatortype_append(NODE_OT_mute_toggle);
WM_operatortype_append(NODE_OT_hide_toggle); WM_operatortype_append(NODE_OT_hide_toggle);
WM_operatortype_append(NODE_OT_preview_toggle); WM_operatortype_append(NODE_OT_preview_toggle);
WM_operatortype_append(NODE_OT_options_toggle);
WM_operatortype_append(NODE_OT_hide_socket_toggle); WM_operatortype_append(NODE_OT_hide_socket_toggle);
WM_operatortype_append(NODE_OT_show_cyclic_dependencies); WM_operatortype_append(NODE_OT_show_cyclic_dependencies);
@ -148,7 +149,6 @@ void node_keymap(struct wmKeyConfig *keyconf)
/* each of these falls through if not handled... */ /* each of these falls through if not handled... */
WM_keymap_add_item(keymap, "NODE_OT_link", LEFTMOUSE, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "NODE_OT_link", LEFTMOUSE, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "NODE_OT_resize", LEFTMOUSE, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "NODE_OT_resize", LEFTMOUSE, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "NODE_OT_visibility_toggle", LEFTMOUSE, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "NODE_OT_links_cut", LEFTMOUSE, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "NODE_OT_links_cut", LEFTMOUSE, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "NODE_OT_select_link_viewer", LEFTMOUSE, KM_PRESS, KM_SHIFT|KM_CTRL, 0); WM_keymap_add_item(keymap, "NODE_OT_select_link_viewer", LEFTMOUSE, KM_PRESS, KM_SHIFT|KM_CTRL, 0);

@ -31,6 +31,8 @@
#include <stdio.h> #include <stdio.h>
#include "BLI_listbase.h"
#include "DNA_node_types.h" #include "DNA_node_types.h"
#include "DNA_scene_types.h" #include "DNA_scene_types.h"
@ -68,6 +70,206 @@ static bNode *node_under_mouse(bNodeTree *ntree, int mx, int my)
return NULL; return NULL;
} }
static int compare_nodes(bNode *a, bNode *b)
{
bNode *parent;
/* These tell if either the node or any of the parent nodes is selected.
* A selected parent means an unselected node is also in foreground!
*/
int a_select=(a->flag & NODE_SELECT), b_select=(b->flag & NODE_SELECT);
int a_active=(a->flag & NODE_ACTIVE), b_active=(b->flag & NODE_ACTIVE);
/* if one is an ancestor of the other */
/* XXX there might be a better sorting algorithm for stable topological sort, this is O(n^2) worst case */
for (parent = a->parent; parent; parent=parent->parent) {
/* if b is an ancestor, it is always behind a */
if (parent==b)
return 1;
/* any selected ancestor moves the node forward */
if (parent->flag & NODE_ACTIVE)
a_active = 1;
if (parent->flag & NODE_SELECT)
a_select = 1;
}
for (parent = b->parent; parent; parent=parent->parent) {
/* if a is an ancestor, it is always behind b */
if (parent==a)
return 0;
/* any selected ancestor moves the node forward */
if (parent->flag & NODE_ACTIVE)
b_active = 1;
if (parent->flag & NODE_SELECT)
b_select = 1;
}
/* if one of the nodes is in the background and the other not */
if ((a->flag & NODE_BACKGROUND) && !(b->flag & NODE_BACKGROUND))
return 0;
else if (!(a->flag & NODE_BACKGROUND) && (b->flag & NODE_BACKGROUND))
return 1;
/* if one has a higher selection state (active > selected > nothing) */
if (!b_active && a_active)
return 1;
else if (!b_select && (a_active || a_select))
return 1;
return 0;
}
/* Sorts nodes by selection: unselected nodes first, then selected,
* then the active node at the very end. Relative order is kept intact!
*/
static void node_sort(bNodeTree *ntree)
{
/* merge sort is the algorithm of choice here */
bNode *first_a, *first_b, *node_a, *node_b, *tmp;
int totnodes= BLI_countlist(&ntree->nodes);
int k, a, b;
k = 1;
while (k < totnodes) {
first_a = first_b = ntree->nodes.first;
do {
/* setup first_b pointer */
for (b=0; b < k && first_b; ++b) {
first_b = first_b->next;
}
/* all batches merged? */
if (first_b==NULL)
break;
/* merge batches */
node_a = first_a;
node_b = first_b;
a = b = 0;
while (a < k && b < k && node_b) {
if (compare_nodes(node_a, node_b)==0) {
node_a = node_a->next;
++a;
}
else {
tmp = node_b;
node_b = node_b->next;
++b;
BLI_remlink(&ntree->nodes, tmp);
BLI_insertlinkbefore(&ntree->nodes, node_a, tmp);
}
}
/* setup first pointers for next batch */
first_b = node_b;
for (; b < k; ++b) {
/* all nodes sorted? */
if (first_b==NULL)
break;
first_b = first_b->next;
}
first_a = first_b;
} while (first_b);
k = k << 1;
}
}
/* no undo here! */
void node_deselect_all(SpaceNode *snode)
{
bNode *node;
for(node= snode->edittree->nodes.first; node; node= node->next)
node->flag &= ~SELECT;
}
/* return 1 if we need redraw otherwise zero. */
int node_select_same_type(SpaceNode *snode)
{
bNode *nac, *p;
int redraw;
/* search for the active node. */
for (nac= snode->edittree->nodes.first; nac; nac= nac->next) {
if (nac->flag & SELECT)
break;
}
/* no active node, return. */
if (!nac)
return(0);
redraw= 0;
for (p= snode->edittree->nodes.first; p; p= p->next) {
if (p->type != nac->type && p->flag & SELECT) {
/* if it's selected but different type, unselect */
redraw= 1;
p->flag &= ~SELECT;
}
else if (p->type == nac->type && (!(p->flag & SELECT))) {
/* if it's the same type and is not selected, select! */
redraw= 1;
p->flag |= SELECT;
}
}
return(redraw);
}
/* return 1 if we need redraw, otherwise zero.
* dir can be 0 == next or 0 != prev.
*/
int node_select_same_type_np(SpaceNode *snode, int dir)
{
bNode *nac, *p;
/* search the active one. */
for (nac= snode->edittree->nodes.first; nac; nac= nac->next) {
if (nac->flag & SELECT)
break;
}
/* no active node, return. */
if (!nac)
return(0);
if (dir == 0)
p= nac->next;
else
p= nac->prev;
while (p) {
/* Now search the next with the same type. */
if (p->type == nac->type)
break;
if (dir == 0)
p= p->next;
else
p= p->prev;
}
if (p) {
node_deselect_all(snode);
p->flag |= SELECT;
return(1);
}
return(0);
}
void node_select_single(bContext *C, bNode *node)
{
Main *bmain= CTX_data_main(C);
SpaceNode *snode= CTX_wm_space_node(C);
node_deselect_all(snode);
node->flag |= SELECT;
ED_node_set_active(bmain, snode->edittree, node);
node_sort(snode->edittree);
WM_event_add_notifier(C, NC_NODE|NA_SELECTED, NULL);
}
/* ****** Click Select ****** */ /* ****** Click Select ****** */
static bNode *node_mouse_select(Main *bmain, SpaceNode *snode, ARegion *ar, const int mval[2], short extend) static bNode *node_mouse_select(Main *bmain, SpaceNode *snode, ARegion *ar, const int mval[2], short extend)
@ -86,7 +288,7 @@ static bNode *node_mouse_select(Main *bmain, SpaceNode *snode, ARegion *ar, cons
if (node) { if (node) {
if (extend == 0) { if (extend == 0) {
node_deselectall(snode); node_deselect_all(snode);
node->flag |= SELECT; node->flag |= SELECT;
} }
else else

@ -52,160 +52,6 @@
#include "node_intern.h" #include "node_intern.h"
/* **************** Node Header Buttons ************** */
/* note: call node_tree_verify_groups(snode->nodetree) after this
*/
void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set)
{
bNodeSocket *sock;
if(set==0) {
for(sock= node->inputs.first; sock; sock= sock->next)
sock->flag &= ~SOCK_HIDDEN;
for(sock= node->outputs.first; sock; sock= sock->next)
sock->flag &= ~SOCK_HIDDEN;
}
else {
/* hide unused sockets */
for(sock= node->inputs.first; sock; sock= sock->next) {
if(sock->link==NULL)
sock->flag |= SOCK_HIDDEN;
}
for(sock= node->outputs.first; sock; sock= sock->next) {
if(nodeCountSocketLinks(snode->edittree, sock)==0)
sock->flag |= SOCK_HIDDEN;
}
}
}
static void node_hide_unhide_sockets(SpaceNode *snode, bNode *node)
{
node_set_hidden_sockets(snode, node, !node_has_hidden_sockets(node));
ntreeUpdateTree(snode->edittree);
}
static int do_header_node(SpaceNode *snode, bNode *node, float mx, float my)
{
rctf totr= node->totr;
totr.ymin= totr.ymax-20.0f;
totr.xmax= totr.xmin+15.0f;
if(BLI_in_rctf(&totr, mx, my)) {
node->flag |= NODE_HIDDEN;
return 1;
}
totr.xmax= node->totr.xmax;
totr.xmin= totr.xmax-18.0f;
if(node->typeinfo->flag & NODE_PREVIEW) {
if(BLI_in_rctf(&totr, mx, my)) {
node->flag ^= NODE_PREVIEW;
return 1;
}
totr.xmin-=15.0f;
}
if(node->type == NODE_GROUP) {
if(BLI_in_rctf(&totr, mx, my)) {
snode_make_group_editable(snode, node);
return 1;
}
totr.xmin-=15.0f;
}
if(node->typeinfo->flag & NODE_OPTIONS) {
if(BLI_in_rctf(&totr, mx, my)) {
node->flag ^= NODE_OPTIONS;
return 1;
}
totr.xmin-=15.0f;
}
/* hide unused sockets */
if(BLI_in_rctf(&totr, mx, my)) {
node_hide_unhide_sockets(snode, node);
}
return 0;
}
static int do_header_hidden_node(bNode *node, float mx, float my)
{
rctf totr= node->totr;
totr.xmax= totr.xmin+15.0f;
if(BLI_in_rctf(&totr, mx, my)) {
node->flag &= ~NODE_HIDDEN;
return 1;
}
return 0;
}
static int node_toggle_visibility(SpaceNode *snode, ARegion *ar, const int mval[2])
{
bNode *node;
float mx, my;
mx= (float)mval[0];
my= (float)mval[1];
UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &mx, &my);
for(node=snode->edittree->nodes.last; node; node=node->prev) {
if(node->flag & NODE_HIDDEN) {
if(do_header_hidden_node(node, mx, my)) {
ED_region_tag_redraw(ar);
return 1;
}
}
else {
if(do_header_node(snode, node, mx, my)) {
ED_region_tag_redraw(ar);
return 1;
}
}
}
return 0;
}
static int node_toggle_visibility_exec(bContext *C, wmOperator *op)
{
SpaceNode *snode= CTX_wm_space_node(C);
ARegion *ar= CTX_wm_region(C);
int mval[2];
mval[0] = RNA_int_get(op->ptr, "mouse_x");
mval[1] = RNA_int_get(op->ptr, "mouse_y");
if(node_toggle_visibility(snode, ar, mval))
return OPERATOR_FINISHED;
else
return OPERATOR_CANCELLED|OPERATOR_PASS_THROUGH;
}
static int node_toggle_visibility_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
RNA_int_set(op->ptr, "mouse_x", event->mval[0]);
RNA_int_set(op->ptr, "mouse_y", event->mval[1]);
return node_toggle_visibility_exec(C,op);
}
void NODE_OT_visibility_toggle(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Toggle Visibility";
ot->idname= "NODE_OT_visibility_toggle";
ot->description= "Handle clicks on node header buttons";
/* api callbacks */
ot->invoke= node_toggle_visibility_invoke;
ot->poll= ED_operator_node_active;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
RNA_def_int(ot->srna, "mouse_x", 0, INT_MIN, INT_MAX, "Mouse X", "", INT_MIN, INT_MAX);
RNA_def_int(ot->srna, "mouse_y", 0, INT_MIN, INT_MAX, "Mouse Y", "", INT_MIN, INT_MAX);
}
/* **************** View All Operator ************** */ /* **************** View All Operator ************** */

@ -724,8 +724,7 @@ static void find_nearest_uv_face(Scene *scene, Image *ima, BMEditMesh *em, float
BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
cent[0] += luv->uv[0]; add_v2_v2(cent, luv->uv);
cent[1] += luv->uv[1];
} }
cent[0] /= efa->len; cent[0] /= efa->len;

@ -112,6 +112,8 @@ void GPU_extensions_init(void)
if (!GLEW_ARB_vertex_shader) GG.glslsupport = 0; if (!GLEW_ARB_vertex_shader) GG.glslsupport = 0;
if (!GLEW_ARB_fragment_shader) GG.glslsupport = 0; if (!GLEW_ARB_fragment_shader) GG.glslsupport = 0;
GPU_code_generate_glsl_lib();
glGetIntegerv(GL_RED_BITS, &r); glGetIntegerv(GL_RED_BITS, &r);
glGetIntegerv(GL_GREEN_BITS, &g); glGetIntegerv(GL_GREEN_BITS, &g);
glGetIntegerv(GL_BLUE_BITS, &b); glGetIntegerv(GL_BLUE_BITS, &b);

@ -64,9 +64,13 @@ EnumPropertyItem nodetree_type_items[] = {
EnumPropertyItem node_socket_type_items[] = { EnumPropertyItem node_socket_type_items[] = {
{SOCK_FLOAT, "VALUE", 0, "Value", ""}, {SOCK_FLOAT, "VALUE", 0, "Value", ""},
{SOCK_VECTOR, "VECTOR", 0, "Vector", ""}, {SOCK_VECTOR, "VECTOR", 0, "Vector", ""},
{SOCK_RGBA, "RGBA", 0, "RGBA", ""}, {SOCK_RGBA, "RGBA", 0, "RGBA", ""},
{SOCK_SHADER, "SHADER", 0, "Shader", ""},
{SOCK_BOOLEAN, "BOOLEAN", 0, "Boolean", ""},
{SOCK_MESH, "MESH", 0, "Mesh", ""},
{SOCK_INT, "INT", 0, "Int", ""},
{0, NULL, 0, NULL, NULL}}; {0, NULL, 0, NULL, NULL}};
EnumPropertyItem node_math_items[] = { EnumPropertyItem node_math_items[] = {

@ -810,11 +810,11 @@ static void rna_MaterialSlot_link_set(PointerRNA *ptr, int value)
if(value) { if(value) {
ob->matbits[index]= 1; ob->matbits[index]= 1;
ob->colbits |= (1<<index); /* ob->colbits |= (1<<index); */ /* DEPRECATED */
} }
else { else {
ob->matbits[index]= 0; ob->matbits[index]= 0;
ob->colbits &= ~(1<<index); /* ob->colbits &= ~(1<<index); */ /* DEPRECATED */
} }
} }

@ -191,13 +191,12 @@ Mesh *rna_Object_to_mesh(Object *ob, ReportList *reports, Scene *sce, int apply_
if( tmpcu->mat ) { if( tmpcu->mat ) {
for( i = tmpcu->totcol; i-- > 0; ) { for( i = tmpcu->totcol; i-- > 0; ) {
/* are we an object material or data based? */ /* are we an object material or data based? */
if (ob->colbits & 1<<i)
tmpmesh->mat[i] = ob->mat[i];
else
tmpmesh->mat[i] = tmpcu->mat[i];
if (tmpmesh->mat[i]) tmpmesh->mat[i] = ob->matbits[i] ? ob->mat[i] : tmpcu->mat[i];
if (tmpmesh->mat[i]) {
tmpmesh->mat[i]->id.us++; tmpmesh->mat[i]->id.us++;
}
} }
} }
break; break;
@ -230,12 +229,11 @@ Mesh *rna_Object_to_mesh(Object *ob, ReportList *reports, Scene *sce, int apply_
if( origmesh->mat ) { if( origmesh->mat ) {
for( i = origmesh->totcol; i-- > 0; ) { for( i = origmesh->totcol; i-- > 0; ) {
/* are we an object material or data based? */ /* are we an object material or data based? */
if (ob->colbits & 1<<i) tmpmesh->mat[i] = ob->matbits[i] ? ob->mat[i] : origmesh->mat[i];
tmpmesh->mat[i] = ob->mat[i];
else if (tmpmesh->mat[i]) {
tmpmesh->mat[i] = origmesh->mat[i];
if (tmpmesh->mat[i])
tmpmesh->mat[i]->id.us++; tmpmesh->mat[i]->id.us++;
}
} }
} }
} }

@ -2000,23 +2000,6 @@ static void rna_def_space_sequencer(BlenderRNA *brna)
RNA_def_property_enum_items(prop, proxy_render_size_items); RNA_def_property_enum_items(prop, proxy_render_size_items);
RNA_def_property_ui_text(prop, "Proxy render size", "Draw preview using full resolution or different proxy resolutions"); RNA_def_property_ui_text(prop, "Proxy render size", "Draw preview using full resolution or different proxy resolutions");
RNA_def_property_update(prop, NC_SPACE|ND_SPACE_SEQUENCER, NULL); RNA_def_property_update(prop, NC_SPACE|ND_SPACE_SEQUENCER, NULL);
/* not sure we need rna access to these but adding anyway */
prop= RNA_def_property(srna, "offset_x", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "xof");
RNA_def_property_ui_text(prop, "X Offset", "Offset image horizontally from the view center");
RNA_def_property_update(prop, NC_SPACE|ND_SPACE_SEQUENCER, NULL);
prop= RNA_def_property(srna, "offset_y", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "yof");
RNA_def_property_ui_text(prop, "Y Offset", "Offset image vertically from the view center");
RNA_def_property_update(prop, NC_SPACE|ND_SPACE_SEQUENCER, NULL);
prop= RNA_def_property(srna, "zoom", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "zoom");
RNA_def_property_ui_text(prop, "Zoom", "Display zoom level");
RNA_def_property_update(prop, NC_SPACE|ND_SPACE_SEQUENCER, NULL);
} }
static void rna_def_space_text(BlenderRNA *brna) static void rna_def_space_text(BlenderRNA *brna)

@ -79,8 +79,8 @@ static void dm_calc_normal(DerivedMesh *dm, float (*temp_nors)[3])
/* we don't want to overwrite any referenced layers */ /* we don't want to overwrite any referenced layers */
/* /*
Dosnt work here! Doesn't work here!
mv = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT); mv = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT, numVerts);
cddm->mvert = mv; cddm->mvert = mv;
*/ */

@ -259,11 +259,12 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd,
mul_mat3_m4_v3(projectors[i].ob->obmat, projectors[i].normal); mul_mat3_m4_v3(projectors[i].ob->obmat, projectors[i].normal);
} }
numFaces = dm->getNumTessFaces(dm);
/* make sure we are not modifying the original UV map */ /* make sure we are not modifying the original UV map */
tface = CustomData_duplicate_referenced_layer_named(&dm->faceData, tface = CustomData_duplicate_referenced_layer_named(&dm->faceData,
CD_MTFACE, uvname); CD_MTFACE, uvname, numFaces);
numVerts = dm->getNumVerts(dm); numVerts = dm->getNumVerts(dm);
coords = MEM_callocN(sizeof(*coords) * numVerts, coords = MEM_callocN(sizeof(*coords) * numVerts,
@ -295,15 +296,11 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd,
} }
else { else {
/* apply transformed coords as UVs */ /* apply transformed coords as UVs */
tface->uv[0][0] = coords[mf->v1][0]; copy_v2_v2(tface->uv[0], coords[mf->v1]);
tface->uv[0][1] = coords[mf->v1][1]; copy_v2_v2(tface->uv[1], coords[mf->v2]);
tface->uv[1][0] = coords[mf->v2][0]; copy_v2_v2(tface->uv[2], coords[mf->v3]);
tface->uv[1][1] = coords[mf->v2][1]; if (mf->v4) {
tface->uv[2][0] = coords[mf->v3][0]; copy_v2_v2(tface->uv[3], coords[mf->v4]);
tface->uv[2][1] = coords[mf->v3][1];
if(mf->v4) {
tface->uv[3][0] = coords[mf->v4][0];
tface->uv[3][1] = coords[mf->v4][1];
} }
} }
} else { } else {
@ -358,15 +355,11 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd,
mul_project_m4_v3(best_projector->projmat, co4); mul_project_m4_v3(best_projector->projmat, co4);
/* apply transformed coords as UVs */ /* apply transformed coords as UVs */
tface->uv[0][0] = co1[0]; copy_v2_v2(tface->uv[0], co1);
tface->uv[0][1] = co1[1]; copy_v2_v2(tface->uv[1], co2);
tface->uv[1][0] = co2[0]; copy_v2_v2(tface->uv[2], co3);
tface->uv[1][1] = co2[1]; if (mf->v4) {
tface->uv[2][0] = co3[0]; copy_v2_v2(tface->uv[3], co4);
tface->uv[2][1] = co3[1];
if(mf->v4) {
tface->uv[3][0] = co4[0];
tface->uv[3][1] = co4[1];
} }
} }
} }

@ -449,9 +449,17 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
MEM_freeN(tdw); MEM_freeN(tdw);
/* Get our vertex coordinates. */ /* Get our vertex coordinates. */
v_cos = MEM_mallocN(sizeof(float[3]) * numIdx, "WeightVGProximity Modifier, v_cos"); {
for (i = 0; i < numIdx; i++) /* XXX In some situations, this code can be up to about 50 times more performant
ret->getVertCo(ret, indices[i], v_cos[i]); * than simply using getVertCo for each affected vertex...
*/
float (*tv_cos)[3] = MEM_mallocN(sizeof(float[3]) * numVerts, "WeightVGProximity Modifier, tv_cos");
v_cos = MEM_mallocN(sizeof(float[3]) * numIdx, "WeightVGProximity Modifier, v_cos");
ret->getVertCos(ret, tv_cos);
for (i = 0; i < numIdx; i++)
copy_v3_v3(v_cos[i], tv_cos[indices[i]]);
MEM_freeN(tv_cos);
}
/* Compute wanted distances. */ /* Compute wanted distances. */
if (wmd->proximity_mode == MOD_WVG_PROXIMITY_OBJECT) { if (wmd->proximity_mode == MOD_WVG_PROXIMITY_OBJECT) {

@ -453,7 +453,7 @@ static int Buffer_ass_item(Buffer *self, int i, PyObject *v)
} }
} }
switch(self->type) { switch (self->type) {
case GL_BYTE: case GL_BYTE:
return PyArg_Parse(v, "b:Expected ints", &self->buf.asbyte[i]) ? 0:-1; return PyArg_Parse(v, "b:Expected ints", &self->buf.asbyte[i]) ? 0:-1;
case GL_SHORT: case GL_SHORT:
@ -595,7 +595,7 @@ static PyObject *Buffer_repr(Buffer *self)
PyObject *repr; PyObject *repr;
const char *typestr= "UNKNOWN"; const char *typestr= "UNKNOWN";
switch(self->type) { switch (self->type) {
case GL_BYTE: typestr= "GL_BYTE"; break; case GL_BYTE: typestr= "GL_BYTE"; break;
case GL_SHORT: typestr= "GL_SHORT"; break; case GL_SHORT: typestr= "GL_SHORT"; break;
case GL_INT: typestr= "GL_BYTE"; break; case GL_INT: typestr= "GL_BYTE"; break;

@ -405,7 +405,7 @@ const char *BPy_IDProperty_Map_ValidateAndCreate(PyObject *name_obj, IDProperty
val.array.len = PySequence_Size(ob); val.array.len = PySequence_Size(ob);
switch(val.array.type) { switch (val.array.type) {
case IDP_DOUBLE: case IDP_DOUBLE:
prop = IDP_New(IDP_ARRAY, &val, name); prop = IDP_New(IDP_ARRAY, &val, name);
for (i=0; i<val.array.len; i++) { for (i=0; i<val.array.len; i++) {
@ -565,7 +565,7 @@ static PyObject *BPy_IDGroup_MapDataToPy(IDProperty *prop)
return NULL; return NULL;
} }
switch(prop->subtype) { switch (prop->subtype) {
case IDP_FLOAT: case IDP_FLOAT:
{ {
float *array= (float*)IDP_Array(prop); float *array= (float*)IDP_Array(prop);
@ -976,7 +976,7 @@ static PyObject *BPy_IDArray_repr(BPy_IDArray *self)
static PyObject *BPy_IDArray_GetType(BPy_IDArray *self) static PyObject *BPy_IDArray_GetType(BPy_IDArray *self)
{ {
switch(self->prop->subtype) { switch (self->prop->subtype) {
case IDP_FLOAT: case IDP_FLOAT:
return PyUnicode_FromString("f"); return PyUnicode_FromString("f");
case IDP_DOUBLE: case IDP_DOUBLE:

@ -191,7 +191,7 @@ void PyC_FileAndNum(const char **filename, int *lineno)
void PyC_FileAndNum_Safe(const char **filename, int *lineno) void PyC_FileAndNum_Safe(const char **filename, int *lineno)
{ {
if(!PYC_INTERPRETER_ACTIVE) { if (!PYC_INTERPRETER_ACTIVE) {
return; return;
} }

@ -82,7 +82,7 @@ static PyObject *bpy_app_handlers_persistent_new(PyTypeObject *UNUSED(type), PyO
{ {
PyObject *value; PyObject *value;
if(!PyArg_ParseTuple(args, "O:bpy.app.handlers.persistent", &value)) if (!PyArg_ParseTuple(args, "O:bpy.app.handlers.persistent", &value))
return NULL; return NULL;
if (PyFunction_Check(value)) { if (PyFunction_Check(value)) {
@ -252,12 +252,12 @@ void BPY_app_handlers_reset(const short do_all)
PyObject *item; PyObject *item;
PyObject **dict_ptr; PyObject **dict_ptr;
for(i= PyList_GET_SIZE(ls) - 1; i >= 0; i--) { for (i= PyList_GET_SIZE(ls) - 1; i >= 0; i--) {
if ( (PyFunction_Check((item= PyList_GET_ITEM(ls, i)))) && if ( (PyFunction_Check((item= PyList_GET_ITEM(ls, i)))) &&
(dict_ptr= _PyObject_GetDictPtr(item)) && (dict_ptr= _PyObject_GetDictPtr(item)) &&
(*dict_ptr) && (*dict_ptr) &&
(PyDict_GetItem(*dict_ptr, perm_id_str) != NULL)) (PyDict_GetItem(*dict_ptr, perm_id_str) != NULL))
{ {
/* keep */ /* keep */
} }

@ -971,14 +971,14 @@ static EnumPropertyItem *enum_items_from_py(PyObject *seq_fast, PyObject *def, i
item= PySequence_Fast_GET_ITEM(seq_fast, i); item= PySequence_Fast_GET_ITEM(seq_fast, i);
if ( (PyTuple_CheckExact(item)) && if ( (PyTuple_CheckExact(item)) &&
(item_size= PyTuple_GET_SIZE(item)) && (item_size= PyTuple_GET_SIZE(item)) &&
(item_size == 3 || item_size == 4) && (item_size == 3 || item_size == 4) &&
(tmp.identifier= _PyUnicode_AsStringAndSize(PyTuple_GET_ITEM(item, 0), &id_str_size)) && (tmp.identifier= _PyUnicode_AsStringAndSize(PyTuple_GET_ITEM(item, 0), &id_str_size)) &&
(tmp.name= _PyUnicode_AsStringAndSize(PyTuple_GET_ITEM(item, 1), &name_str_size)) && (tmp.name= _PyUnicode_AsStringAndSize(PyTuple_GET_ITEM(item, 1), &name_str_size)) &&
(tmp.description= _PyUnicode_AsStringAndSize(PyTuple_GET_ITEM(item, 2), &desc_str_size)) && (tmp.description= _PyUnicode_AsStringAndSize(PyTuple_GET_ITEM(item, 2), &desc_str_size)) &&
(item_size < 4 || py_long_as_int(PyTuple_GET_ITEM(item, 3), &tmp.value) != -1) /* TODO, number isnt ensured to be unique from the script author */ (item_size < 4 || py_long_as_int(PyTuple_GET_ITEM(item, 3), &tmp.value) != -1)) /* TODO, number isnt ensured to be unique from the script author */
) { {
if (is_enum_flag) { if (is_enum_flag) {
if (item_size < 4) { if (item_size < 4) {
tmp.value= 1<<i; tmp.value= 1<<i;

@ -624,7 +624,7 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop)
if (!is_thick) if (!is_thick)
ret= pyrna_prop_CreatePyObject(ptr, prop); /* owned by the mathutils PyObject */ ret= pyrna_prop_CreatePyObject(ptr, prop); /* owned by the mathutils PyObject */
switch(subtype) { switch (subtype) {
case PROP_ALL_VECTOR_SUBTYPES: case PROP_ALL_VECTOR_SUBTYPES:
if (len>=2 && len <= 4) { if (len>=2 && len <= 4) {
if (is_thick) { if (is_thick) {
@ -3441,7 +3441,7 @@ static PyObject *pyrna_struct_getattro(BPy_StructRNA *self, PyObject *pyname)
int done= CTX_data_get(C, name, &newptr, &newlb, &newtype); int done= CTX_data_get(C, name, &newptr, &newlb, &newtype);
if (done==1) { /* found */ if (done==1) { /* found */
switch(newtype) { switch (newtype) {
case CTX_DATA_TYPE_POINTER: case CTX_DATA_TYPE_POINTER:
if (newptr.data == NULL) { if (newptr.data == NULL) {
ret= Py_None; ret= Py_None;
@ -4201,7 +4201,7 @@ static int foreach_compat_buffer(RawPropertyType raw_type, int attr_signed, cons
{ {
char f= format ? *format:'B'; /* B is assumed when not set */ char f= format ? *format:'B'; /* B is assumed when not set */
switch(raw_type) { switch (raw_type) {
case PROP_RAW_CHAR: case PROP_RAW_CHAR:
if (attr_signed) return (f=='b') ? 1:0; if (attr_signed) return (f=='b') ? 1:0;
else return (f=='B') ? 1:0; else return (f=='B') ? 1:0;
@ -4265,7 +4265,7 @@ static PyObject *foreach_getset(BPy_PropertyRNA *self, PyObject *args, int set)
for ( ; i<tot; i++) { for ( ; i<tot; i++) {
item= PySequence_GetItem(seq, i); item= PySequence_GetItem(seq, i);
switch(raw_type) { switch (raw_type) {
case PROP_RAW_CHAR: case PROP_RAW_CHAR:
((char *)array)[i]= (char)PyLong_AsLong(item); ((char *)array)[i]= (char)PyLong_AsLong(item);
break; break;
@ -4320,7 +4320,7 @@ static PyObject *foreach_getset(BPy_PropertyRNA *self, PyObject *args, int set)
for ( ; i<tot; i++) { for ( ; i<tot; i++) {
switch(raw_type) { switch (raw_type) {
case PROP_RAW_CHAR: case PROP_RAW_CHAR:
item= PyLong_FromSsize_t((Py_ssize_t) ((char *)array)[i]); item= PyLong_FromSsize_t((Py_ssize_t) ((char *)array)[i]);
break; break;
@ -4616,7 +4616,7 @@ static PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *dat
PyTuple_SET_ITEM(ret, a, PyLong_FromSsize_t((Py_ssize_t)((int*)data)[a])); PyTuple_SET_ITEM(ret, a, PyLong_FromSsize_t((Py_ssize_t)((int*)data)[a]));
break; break;
case PROP_FLOAT: case PROP_FLOAT:
switch(RNA_property_subtype(prop)) { switch (RNA_property_subtype(prop)) {
#ifdef USE_MATHUTILS #ifdef USE_MATHUTILS
case PROP_ALL_VECTOR_SUBTYPES: case PROP_ALL_VECTOR_SUBTYPES:
ret= Vector_CreatePyObject(data, len, Py_NEW, NULL); ret= Vector_CreatePyObject(data, len, Py_NEW, NULL);
@ -6969,10 +6969,10 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
if (err != 0) { if (err != 0) {
ReportList *reports; ReportList *reports;
/* alert the user, else they wont know unless they see the console. */ /* alert the user, else they wont know unless they see the console. */
if ( (!is_static) && if ( (!is_static) &&
(ptr->data) && (ptr->data) &&
(RNA_struct_is_a(ptr->type, &RNA_Operator)) && (RNA_struct_is_a(ptr->type, &RNA_Operator)) &&
(is_valid_wm == (CTX_wm_manager(C) != NULL))) (is_valid_wm == (CTX_wm_manager(C) != NULL)))
{ {
wmOperator *op= ptr->data; wmOperator *op= ptr->data;
reports= op->reports; reports= op->reports;

@ -148,8 +148,8 @@ static int pyrna_struct_anim_args_parse(
/* internal use for insert and delete */ /* internal use for insert and delete */
static int pyrna_struct_keyframe_parse( static int pyrna_struct_keyframe_parse(
PointerRNA *ptr, PyObject *args, PyObject *kw, const char *parse_str, const char *error_prefix, PointerRNA *ptr, PyObject *args, PyObject *kw, const char *parse_str, const char *error_prefix,
const char **path_full, int *index, float *cfra, const char **group_name) /* return values */ const char **path_full, int *index, float *cfra, const char **group_name) /* return values */
{ {
static const char *kwlist[]= {"data_path", "index", "frame", "group", NULL}; static const char *kwlist[]= {"data_path", "index", "frame", "group", NULL};
const char *path; const char *path;

@ -60,7 +60,7 @@ static void cb_region_draw(const bContext *C, ARegion *UNUSED(ar), void *customd
cb_args= PyTuple_GET_ITEM((PyObject *)customdata, 1); cb_args= PyTuple_GET_ITEM((PyObject *)customdata, 1);
result= PyObject_CallObject(cb_func, cb_args); result= PyObject_CallObject(cb_func, cb_args);
if(result) { if (result) {
Py_DECREF(result); Py_DECREF(result);
} }
else { else {
@ -82,21 +82,22 @@ PyObject *pyrna_callback_add(BPy_StructRNA *self, PyObject *args)
if (!PyArg_ParseTuple(args, "OO!|s:bpy_struct.callback_add", &cb_func, &PyTuple_Type, &cb_args, &cb_event_str)) if (!PyArg_ParseTuple(args, "OO!|s:bpy_struct.callback_add", &cb_func, &PyTuple_Type, &cb_args, &cb_event_str))
return NULL; return NULL;
if(!PyCallable_Check(cb_func)) { if (!PyCallable_Check(cb_func)) {
PyErr_SetString(PyExc_TypeError, "callback_add(): first argument isn't callable"); PyErr_SetString(PyExc_TypeError, "callback_add(): first argument isn't callable");
return NULL; return NULL;
} }
if(RNA_struct_is_a(self->ptr.type, &RNA_Region)) { if (RNA_struct_is_a(self->ptr.type, &RNA_Region)) {
if(cb_event_str) { if (cb_event_str) {
static EnumPropertyItem region_draw_mode_items[]= { static EnumPropertyItem region_draw_mode_items[]= {
{REGION_DRAW_POST_PIXEL, "POST_PIXEL", 0, "Post Pixel", ""}, {REGION_DRAW_POST_PIXEL, "POST_PIXEL", 0, "Post Pixel", ""},
{REGION_DRAW_POST_VIEW, "POST_VIEW", 0, "Post View", ""}, {REGION_DRAW_POST_VIEW, "POST_VIEW", 0, "Post View", ""},
{REGION_DRAW_PRE_VIEW, "PRE_VIEW", 0, "Pre View", ""}, {REGION_DRAW_PRE_VIEW, "PRE_VIEW", 0, "Pre View", ""},
{0, NULL, 0, NULL, NULL}}; {0, NULL, 0, NULL, NULL}};
if(pyrna_enum_value_from_id(region_draw_mode_items, cb_event_str, &cb_event, "bpy_struct.callback_add()") < 0) if (pyrna_enum_value_from_id(region_draw_mode_items, cb_event_str, &cb_event, "bpy_struct.callback_add()") < 0) {
return NULL; return NULL;
}
} }
else { else {
cb_event= REGION_DRAW_POST_PIXEL; cb_event= REGION_DRAW_POST_PIXEL;
@ -124,12 +125,12 @@ PyObject *pyrna_callback_remove(BPy_StructRNA *self, PyObject *args)
handle= PyCapsule_GetPointer(py_handle, RNA_CAPSULE_ID); handle= PyCapsule_GetPointer(py_handle, RNA_CAPSULE_ID);
if(handle==NULL) { if (handle==NULL) {
PyErr_SetString(PyExc_ValueError, "callback_remove(handle): NULL handle given, invalid or already removed"); PyErr_SetString(PyExc_ValueError, "callback_remove(handle): NULL handle given, invalid or already removed");
return NULL; return NULL;
} }
if(RNA_struct_is_a(self->ptr.type, &RNA_Region)) { if (RNA_struct_is_a(self->ptr.type, &RNA_Region)) {
customdata= ED_region_draw_cb_customdata(handle); customdata= ED_region_draw_cb_customdata(handle);
Py_DECREF((PyObject *)customdata); Py_DECREF((PyObject *)customdata);

@ -184,7 +184,8 @@ static PyObject* GPU_export_shader(PyObject* UNUSED(self), PyObject *args, PyObj
PyErr_SetString(PyExc_SystemError, "scene.as_pointer() failed"); PyErr_SetString(PyExc_SystemError, "scene.as_pointer() failed");
return NULL; return NULL;
} }
} else { }
else {
PyErr_SetString(PyExc_TypeError, "gpu.export_shader() first argument should be of Scene type"); PyErr_SetString(PyExc_TypeError, "gpu.export_shader() first argument should be of Scene type");
return NULL; return NULL;
} }
@ -204,7 +205,8 @@ static PyObject* GPU_export_shader(PyObject* UNUSED(self), PyObject *args, PyObj
PyErr_SetString(PyExc_SystemError, "scene.as_pointer() failed"); PyErr_SetString(PyExc_SystemError, "scene.as_pointer() failed");
return NULL; return NULL;
} }
} else { }
else {
PyErr_SetString(PyExc_TypeError, "gpu.export_shader() second argument should be of Material type"); PyErr_SetString(PyExc_TypeError, "gpu.export_shader() second argument should be of Material type");
return NULL; return NULL;
} }
@ -260,7 +262,8 @@ static PyObject* GPU_export_shader(PyObject* UNUSED(self), PyObject *args, PyObj
if (attribute->name) { if (attribute->name) {
if (attribute->name[0] != 0) { if (attribute->name[0] != 0) {
PY_DICT_ADD_STRING(dict,attribute,name); PY_DICT_ADD_STRING(dict,attribute,name);
} else { }
else {
val = PyLong_FromLong(0); val = PyLong_FromLong(0);
PyDict_SetItemString(dict, "name", val); PyDict_SetItemString(dict, "name", val);
Py_DECREF(val); Py_DECREF(val);

@ -40,36 +40,13 @@ PyDoc_STRVAR(M_Mathutils_doc,
"This module provides access to matrices, eulers, quaternions and vectors." "This module provides access to matrices, eulers, quaternions and vectors."
); );
static int mathutils_array_parse_fast(float *array, static int mathutils_array_parse_fast(float *array,
int array_min, int array_max, int size,
PyObject *value, const char *error_prefix) PyObject *value_fast,
const char *error_prefix)
{ {
PyObject *value_fast= NULL;
PyObject *item; PyObject *item;
int i, size; int i;
/* non list/tuple cases */
if (!(value_fast=PySequence_Fast(value, error_prefix))) {
/* PySequence_Fast sets the error */
return -1;
}
size= PySequence_Fast_GET_SIZE(value_fast);
if (size > array_max || size < array_min) {
if (array_max == array_min) {
PyErr_Format(PyExc_ValueError,
"%.200s: sequence size is %d, expected %d",
error_prefix, size, array_max);
}
else {
PyErr_Format(PyExc_ValueError,
"%.200s: sequence size is %d, expected [%d - %d]",
error_prefix, size, array_min, array_max);
}
Py_DECREF(value_fast);
return -1;
}
i= size; i= size;
do { do {
@ -93,13 +70,14 @@ static int mathutils_array_parse_fast(float *array,
/* helper functionm returns length of the 'value', -1 on error */ /* helper functionm returns length of the 'value', -1 on error */
int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *value, const char *error_prefix) int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *value, const char *error_prefix)
{ {
#if 1 /* approx 6x speedup for mathutils types */
int size; int size;
if ( (size= VectorObject_Check(value) ? ((VectorObject *)value)->size : 0) || #if 1 /* approx 6x speedup for mathutils types */
(size= EulerObject_Check(value) ? 3 : 0) ||
(size= QuaternionObject_Check(value) ? 4 : 0) || if ( (size= VectorObject_Check(value) ? ((VectorObject *)value)->size : 0) ||
(size= ColorObject_Check(value) ? 3 : 0)) (size= EulerObject_Check(value) ? 3 : 0) ||
(size= QuaternionObject_Check(value) ? 4 : 0) ||
(size= ColorObject_Check(value) ? 3 : 0))
{ {
if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) { if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) {
return -1; return -1;
@ -125,7 +103,85 @@ int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *
else else
#endif #endif
{ {
return mathutils_array_parse_fast(array, array_min, array_max, value, error_prefix); PyObject *value_fast= NULL;
/* non list/tuple cases */
if (!(value_fast=PySequence_Fast(value, error_prefix))) {
/* PySequence_Fast sets the error */
return -1;
}
size= PySequence_Fast_GET_SIZE(value_fast);
if (size > array_max || size < array_min) {
if (array_max == array_min) {
PyErr_Format(PyExc_ValueError,
"%.200s: sequence size is %d, expected %d",
error_prefix, size, array_max);
}
else {
PyErr_Format(PyExc_ValueError,
"%.200s: sequence size is %d, expected [%d - %d]",
error_prefix, size, array_min, array_max);
}
Py_DECREF(value_fast);
return -1;
}
return mathutils_array_parse_fast(array, size, value_fast, error_prefix);
}
}
int mathutils_array_parse_alloc(float **array, int array_min, PyObject *value, const char *error_prefix)
{
int size;
#if 1 /* approx 6x speedup for mathutils types */
if ( (size= VectorObject_Check(value) ? ((VectorObject *)value)->size : 0) ||
(size= EulerObject_Check(value) ? 3 : 0) ||
(size= QuaternionObject_Check(value) ? 4 : 0) ||
(size= ColorObject_Check(value) ? 3 : 0))
{
if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) {
return -1;
}
if (size < array_min) {
PyErr_Format(PyExc_ValueError,
"%.200s: sequence size is %d, expected > %d",
error_prefix, size, array_min);
return -1;
}
*array= PyMem_Malloc(size * sizeof(float));
memcpy(*array, ((BaseMathObject *)value)->data, size * sizeof(float));
return size;
}
else
#endif
{
PyObject *value_fast= NULL;
//*array= NULL;
/* non list/tuple cases */
if (!(value_fast=PySequence_Fast(value, error_prefix))) {
/* PySequence_Fast sets the error */
return -1;
}
size= PySequence_Fast_GET_SIZE(value_fast);
if (size < array_min) {
PyErr_Format(PyExc_ValueError,
"%.200s: sequence size is %d, expected > %d",
error_prefix, size, array_min);
return -1;
}
*array= PyMem_Malloc(size * sizeof(float));
return mathutils_array_parse_fast(*array, size, value_fast, error_prefix);
} }
} }

@ -115,6 +115,7 @@ int _BaseMathObject_WriteIndexCallback(BaseMathObject *self, int index);
/* utility func */ /* utility func */
int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *value, const char *error_prefix); int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *value, const char *error_prefix);
int mathutils_array_parse_alloc(float **array, int array_min, PyObject *value, const char *error_prefix);
int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error_prefix); int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error_prefix);
int column_vector_multiplication(float rvec[4], VectorObject *vec, MatrixObject *mat); int column_vector_multiplication(float rvec[4], VectorObject *vec, MatrixObject *mat);

@ -48,7 +48,7 @@ static PyObject *Color_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return NULL; return NULL;
} }
switch(PyTuple_GET_SIZE(args)) { switch (PyTuple_GET_SIZE(args)) {
case 0: case 0:
break; break;
case 1: case 1:

@ -59,7 +59,7 @@ static PyObject *Euler_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
if (!PyArg_ParseTuple(args, "|Os:mathutils.Euler", &seq, &order_str)) if (!PyArg_ParseTuple(args, "|Os:mathutils.Euler", &seq, &order_str))
return NULL; return NULL;
switch(PyTuple_GET_SIZE(args)) { switch (PyTuple_GET_SIZE(args)) {
case 0: case 0:
break; break;
case 2: case 2:
@ -84,7 +84,7 @@ static const char *euler_order_str(EulerObject *self)
short euler_order_from_string(const char *str, const char *error_prefix) short euler_order_from_string(const char *str, const char *error_prefix)
{ {
if ((str[0] && str[1] && str[2] && str[3]=='\0')) { if ((str[0] && str[1] && str[2] && str[3]=='\0')) {
switch(*((PY_INT32_T *)str)) { switch (*((PY_INT32_T *)str)) {
case 'X'|'Y'<<8|'Z'<<16: return EULER_ORDER_XYZ; case 'X'|'Y'<<8|'Z'<<16: return EULER_ORDER_XYZ;
case 'X'|'Z'<<8|'Y'<<16: return EULER_ORDER_XZY; case 'X'|'Z'<<8|'Y'<<16: return EULER_ORDER_XZY;
case 'Y'|'X'<<8|'Z'<<16: return EULER_ORDER_YXZ; case 'Y'|'X'<<8|'Z'<<16: return EULER_ORDER_YXZ;

@ -52,13 +52,14 @@ static int mathutils_matrix_vector_check(BaseMathObject *bmo)
static int mathutils_matrix_vector_get(BaseMathObject *bmo, int subtype) static int mathutils_matrix_vector_get(BaseMathObject *bmo, int subtype)
{ {
MatrixObject *self= (MatrixObject *)bmo->cb_user; MatrixObject *self= (MatrixObject *)bmo->cb_user;
int i; int index;
if (BaseMath_ReadCallback(self) == -1) if (BaseMath_ReadCallback(self) == -1)
return -1; return -1;
for (i=0; i < self->col_size; i++) for (index=0; index < self->col_size; index++) {
bmo->data[i]= self->matrix[subtype][i]; bmo->data[index] = MATRIX_ITEM(self, subtype, index);
}
return 0; return 0;
} }
@ -66,13 +67,14 @@ static int mathutils_matrix_vector_get(BaseMathObject *bmo, int subtype)
static int mathutils_matrix_vector_set(BaseMathObject *bmo, int subtype) static int mathutils_matrix_vector_set(BaseMathObject *bmo, int subtype)
{ {
MatrixObject *self= (MatrixObject *)bmo->cb_user; MatrixObject *self= (MatrixObject *)bmo->cb_user;
int i; int index;
if (BaseMath_ReadCallback(self) == -1) if (BaseMath_ReadCallback(self) == -1)
return -1; return -1;
for (i=0; i < self->col_size; i++) for (index=0; index < self->col_size; index++) {
self->matrix[subtype][i]= bmo->data[i]; MATRIX_ITEM(self, subtype, index) = bmo->data[index];
}
(void)BaseMath_WriteCallback(self); (void)BaseMath_WriteCallback(self);
return 0; return 0;
@ -85,7 +87,7 @@ static int mathutils_matrix_vector_get_index(BaseMathObject *bmo, int subtype, i
if (BaseMath_ReadCallback(self) == -1) if (BaseMath_ReadCallback(self) == -1)
return -1; return -1;
bmo->data[index]= self->matrix[subtype][index]; bmo->data[index]= MATRIX_ITEM(self, subtype, index);
return 0; return 0;
} }
@ -96,7 +98,7 @@ static int mathutils_matrix_vector_set_index(BaseMathObject *bmo, int subtype, i
if (BaseMath_ReadCallback(self) == -1) if (BaseMath_ReadCallback(self) == -1)
return -1; return -1;
self->matrix[subtype][index]= bmo->data[index]; MATRIX_ITEM(self, subtype, index) = bmo->data[index];
(void)BaseMath_WriteCallback(self); (void)BaseMath_WriteCallback(self);
return 0; return 0;
@ -123,7 +125,7 @@ static PyObject *Matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return NULL; return NULL;
} }
switch(PyTuple_GET_SIZE(args)) { switch (PyTuple_GET_SIZE(args)) {
case 0: case 0:
return Matrix_CreatePyObject(NULL, 4, 4, Py_NEW, type); return Matrix_CreatePyObject(NULL, 4, 4, Py_NEW, type);
case 1: case 1:
@ -620,24 +622,22 @@ static PyObject *C_Matrix_Shear(PyObject *cls, PyObject *args)
void matrix_as_3x3(float mat[3][3], MatrixObject *self) void matrix_as_3x3(float mat[3][3], MatrixObject *self)
{ {
copy_v3_v3(mat[0], self->matrix[0]); copy_v3_v3(mat[0], MATRIX_ROW_PTR(self, 0));
copy_v3_v3(mat[1], self->matrix[1]); copy_v3_v3(mat[1], MATRIX_ROW_PTR(self, 1));
copy_v3_v3(mat[2], self->matrix[2]); copy_v3_v3(mat[2], MATRIX_ROW_PTR(self, 2));
} }
/* assumes rowsize == colsize is checked and the read callback has run */ /* assumes rowsize == colsize is checked and the read callback has run */
static float matrix_determinant_internal(MatrixObject *self) static float matrix_determinant_internal(MatrixObject *self)
{ {
if (self->row_size == 2) { if (self->row_size == 2) {
return determinant_m2(self->matrix[0][0], self->matrix[0][1], return determinant_m2(MATRIX_ITEM(self, 0, 0), MATRIX_ITEM(self, 0, 1),
self->matrix[1][0], self->matrix[1][1]); MATRIX_ITEM(self, 1, 0), MATRIX_ITEM(self, 1, 1));
} }
else if (self->row_size == 3) { else if (self->row_size == 3) {
return determinant_m3(self->matrix[0][0], self->matrix[0][1], return determinant_m3(MATRIX_ITEM(self, 0, 0), MATRIX_ITEM(self, 0, 1), MATRIX_ITEM(self, 0, 2),
self->matrix[0][2], self->matrix[1][0], MATRIX_ITEM(self, 1, 0), MATRIX_ITEM(self, 1, 1), MATRIX_ITEM(self, 1, 2),
self->matrix[1][1], self->matrix[1][2], MATRIX_ITEM(self, 2, 0), MATRIX_ITEM(self, 2, 1), MATRIX_ITEM(self, 2, 2));
self->matrix[2][0], self->matrix[2][1],
self->matrix[2][2]);
} }
else { else {
return determinant_m4((float (*)[4])self->contigPtr); return determinant_m4((float (*)[4])self->contigPtr);
@ -781,10 +781,7 @@ static PyObject *Matrix_resize_4x4(MatrixObject *self)
"problem allocating pointer space"); "problem allocating pointer space");
return NULL; return NULL;
} }
/*set row pointers*/
for (x = 0; x < 4; x++) {
self->matrix[x] = self->contigPtr + (x * 4);
}
/*move data to new spot in array + clean*/ /*move data to new spot in array + clean*/
for (blank_rows = (4 - self->row_size); blank_rows > 0; blank_rows--) { for (blank_rows = (4 - self->row_size); blank_rows > 0; blank_rows--) {
for (x = 0; x < 4; x++) { for (x = 0; x < 4; x++) {
@ -890,7 +887,7 @@ static PyObject *Matrix_to_translation(MatrixObject *self)
return NULL; return NULL;
} }
return Vector_CreatePyObject(self->matrix[3], 3, Py_NEW, NULL); return Vector_CreatePyObject(MATRIX_ROW_PTR(self, 3), 3, Py_NEW, NULL);
} }
PyDoc_STRVAR(Matrix_to_scale_doc, PyDoc_STRVAR(Matrix_to_scale_doc,
@ -964,10 +961,10 @@ static PyObject *Matrix_invert(MatrixObject *self)
if (det != 0) { if (det != 0) {
/*calculate the classical adjoint*/ /*calculate the classical adjoint*/
if (self->row_size == 2) { if (self->row_size == 2) {
mat[0] = self->matrix[1][1]; mat[0] = MATRIX_ITEM(self, 1, 1);
mat[1] = -self->matrix[0][1]; mat[1] = -MATRIX_ITEM(self, 0, 1);
mat[2] = -self->matrix[1][0]; mat[2] = -MATRIX_ITEM(self, 1, 0);
mat[3] = self->matrix[0][0]; mat[3] = MATRIX_ITEM(self, 0, 0);
} }
else if (self->row_size == 3) { else if (self->row_size == 3) {
adjoint_m3_m3((float (*)[3]) mat,(float (*)[3])self->contigPtr); adjoint_m3_m3((float (*)[3]) mat,(float (*)[3])self->contigPtr);
@ -982,7 +979,7 @@ static PyObject *Matrix_invert(MatrixObject *self)
/*set values*/ /*set values*/
for (x = 0; x < self->row_size; x++) { for (x = 0; x < self->row_size; x++) {
for (y = 0; y < self->col_size; y++) { for (y = 0; y < self->col_size; y++) {
self->matrix[x][y] = mat[z]; MATRIX_ITEM(self, x, y) = mat[z];
z++; z++;
} }
} }
@ -1173,8 +1170,6 @@ PyDoc_STRVAR(Matrix_transpose_doc,
); );
static PyObject *Matrix_transpose(MatrixObject *self) static PyObject *Matrix_transpose(MatrixObject *self)
{ {
float t = 0.0f;
if (BaseMath_ReadCallback(self) == -1) if (BaseMath_ReadCallback(self) == -1)
return NULL; return NULL;
@ -1186,9 +1181,9 @@ static PyObject *Matrix_transpose(MatrixObject *self)
} }
if (self->row_size == 2) { if (self->row_size == 2) {
t = self->matrix[1][0]; const float t = MATRIX_ITEM(self, 1, 0);
self->matrix[1][0] = self->matrix[0][1]; MATRIX_ITEM(self, 1, 0) = MATRIX_ITEM(self, 0, 1);
self->matrix[0][1] = t; MATRIX_ITEM(self, 0, 1) = t;
} }
else if (self->row_size == 3) { else if (self->row_size == 3) {
transpose_m3((float (*)[3])self->contigPtr); transpose_m3((float (*)[3])self->contigPtr);
@ -1256,10 +1251,10 @@ static PyObject *Matrix_identity(MatrixObject *self)
} }
if (self->row_size == 2) { if (self->row_size == 2) {
self->matrix[0][0] = 1.0f; MATRIX_ITEM(self, 0, 0) = 1.0f;
self->matrix[0][1] = 0.0f; MATRIX_ITEM(self, 0, 1) = 0.0f;
self->matrix[1][0] = 0.0f; MATRIX_ITEM(self, 1, 0) = 0.0f;
self->matrix[1][1] = 1.0f; MATRIX_ITEM(self, 1, 1) = 1.0f;
} }
else if (self->row_size == 3) { else if (self->row_size == 3) {
unit_m3((float (*)[3])self->contigPtr); unit_m3((float (*)[3])self->contigPtr);
@ -1304,10 +1299,10 @@ static PyObject *Matrix_repr(MatrixObject *self)
for (x = 0; x < self->row_size; x++) { for (x = 0; x < self->row_size; x++) {
rows[x]= PyTuple_New(self->col_size); rows[x]= PyTuple_New(self->col_size);
for (y = 0; y < self->col_size; y++) { for (y = 0; y < self->col_size; y++) {
PyTuple_SET_ITEM(rows[x], y, PyFloat_FromDouble(self->matrix[x][y])); PyTuple_SET_ITEM(rows[x], y, PyFloat_FromDouble(MATRIX_ITEM(self, x, y)));
} }
} }
switch(self->row_size) { switch (self->row_size) {
case 2: return PyUnicode_FromFormat("Matrix((%R,\n" case 2: return PyUnicode_FromFormat("Matrix((%R,\n"
" %R))", rows[0], rows[1]); " %R))", rows[0], rows[1]);
@ -1406,7 +1401,7 @@ static int Matrix_ass_item(MatrixObject *self, int i, PyObject *value)
return -1; return -1;
} }
memcpy(self->matrix[i], vec, self->col_size *sizeof(float)); memcpy(MATRIX_ROW_PTR(self, i), vec, self->col_size * sizeof(float));
(void)BaseMath_WriteCallback(self); (void)BaseMath_WriteCallback(self);
return 0; return 0;
@ -1591,7 +1586,7 @@ static PyObject *Matrix_mul(PyObject *m1, PyObject *m2)
for (x = 0; x < mat2->row_size; x++) { for (x = 0; x < mat2->row_size; x++) {
for (y = 0; y < mat1->col_size; y++) { for (y = 0; y < mat1->col_size; y++) {
for (z = 0; z < mat1->row_size; z++) { for (z = 0; z < mat1->row_size; z++) {
dot += (mat1->matrix[z][y] * mat2->matrix[x][z]); dot += MATRIX_ITEM(mat1, z, y) * MATRIX_ITEM(mat2, x, z);
} }
mat[((x * mat1->col_size) + y)] = (float)dot; mat[((x * mat1->col_size) + y)] = (float)dot;
dot = 0.0f; dot = 0.0f;
@ -1944,31 +1939,18 @@ PyTypeObject matrix_Type = {
NULL /*tp_del*/ NULL /*tp_del*/
}; };
/*------------------------Matrix_CreatePyObject (internal)------------- /* pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
creates a new matrix object * (i.e. it was allocated elsewhere by MEM_mallocN())
self->matrix self->contiguous_ptr (reference to data.xxx) * pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
[0]------------->[0] * (i.e. it must be created here with PyMEM_malloc()) */
[1]
[2]
[1]------------->[3]
[4]
[5]
self->matrix[1][1] = self->contigPtr[4] */
/*pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
(i.e. it was allocated elsewhere by MEM_mallocN())
pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
(i.e. it must be created here with PyMEM_malloc())*/
PyObject *Matrix_CreatePyObject(float *mat, PyObject *Matrix_CreatePyObject(float *mat,
const unsigned short rowSize, const unsigned short colSize, const unsigned short row_size, const unsigned short col_size,
int type, PyTypeObject *base_type) int type, PyTypeObject *base_type)
{ {
MatrixObject *self; MatrixObject *self;
int x, row, col;
/*matrix objects can be any 2-4row x 2-4col matrix*/ /* matrix objects can be any 2-4row x 2-4col matrix */
if (rowSize < 2 || rowSize > 4 || colSize < 2 || colSize > 4) { if (row_size < 2 || row_size > 4 || col_size < 2 || col_size > 4) {
PyErr_SetString(PyExc_RuntimeError, PyErr_SetString(PyExc_RuntimeError,
"Matrix(): " "Matrix(): "
"row and column sizes must be between 2 and 4"); "row and column sizes must be between 2 and 4");
@ -1979,8 +1961,8 @@ PyObject *Matrix_CreatePyObject(float *mat,
(MatrixObject *)PyObject_GC_New(MatrixObject, &matrix_Type); (MatrixObject *)PyObject_GC_New(MatrixObject, &matrix_Type);
if (self) { if (self) {
self->row_size = rowSize; self->row_size = row_size;
self->col_size = colSize; self->col_size = col_size;
/* init callbacks as NULL */ /* init callbacks as NULL */
self->cb_user= NULL; self->cb_user= NULL;
@ -1988,36 +1970,29 @@ PyObject *Matrix_CreatePyObject(float *mat,
if (type == Py_WRAP) { if (type == Py_WRAP) {
self->contigPtr = mat; self->contigPtr = mat;
/*pointer array points to contigous memory*/
for (x = 0; x < rowSize; x++) {
self->matrix[x] = self->contigPtr + (x * colSize);
}
self->wrapped = Py_WRAP; self->wrapped = Py_WRAP;
} }
else if (type == Py_NEW) { else if (type == Py_NEW) {
self->contigPtr = PyMem_Malloc(rowSize * colSize * sizeof(float)); self->contigPtr = PyMem_Malloc(row_size * col_size * sizeof(float));
if (self->contigPtr == NULL) { /*allocation failure*/ if (self->contigPtr == NULL) { /*allocation failure*/
PyErr_SetString(PyExc_MemoryError, PyErr_SetString(PyExc_MemoryError,
"Matrix(): " "Matrix(): "
"problem allocating pointer space"); "problem allocating pointer space");
return NULL; return NULL;
} }
/*pointer array points to contigous memory*/
for (x = 0; x < rowSize; x++) {
self->matrix[x] = self->contigPtr + (x * colSize);
}
/*parse*/
if (mat) { /*if a float array passed*/ if (mat) { /*if a float array passed*/
for (row = 0; row < rowSize; row++) { memcpy(self->contigPtr, mat, row_size * col_size * sizeof(float));
for (col = 0; col < colSize; col++) {
self->matrix[row][col] = mat[(row * colSize) + col];
}
}
} }
else if (rowSize == colSize) { /*or if no arguments are passed return identity matrix for square matrices */ else if (row_size == col_size) {
/* or if no arguments are passed return identity matrix for square matrices */
PyObject *ret_dummy= Matrix_identity(self); PyObject *ret_dummy= Matrix_identity(self);
Py_DECREF(ret_dummy); Py_DECREF(ret_dummy);
} }
else {
/* otherwise zero everything */
memset(self->contigPtr, 0, row_size * col_size * sizeof(float));
}
self->wrapped = Py_NEW; self->wrapped = Py_NEW;
} }
else { else {

@ -38,19 +38,33 @@ extern PyTypeObject matrix_Type;
#define MatrixObject_Check(_v) PyObject_TypeCheck((_v), &matrix_Type) #define MatrixObject_Check(_v) PyObject_TypeCheck((_v), &matrix_Type)
#define MATRIX_MAX_DIM 4 #define MATRIX_MAX_DIM 4
/* matrix[row][col] == MATRIX_ITEM_INDEX(matrix, row, col) */
#ifdef DEBUG
# define MATRIX_ITEM_ASSERT(_mat, _row, _col) (BLI_assert(_row < (_mat)->row_size && _col < (_mat)->col_size))
#else
# define MATRIX_ITEM_ASSERT(_mat, _row, _col) (void)0
#endif
#define MATRIX_ITEM_INDEX(_mat, _row, _col) (MATRIX_ITEM_ASSERT(_mat, _row, _col),(((_mat)->col_size * (_row)) + (_col)))
#define MATRIX_ITEM_PTR( _mat, _row, _col) ((_mat)->contigPtr + MATRIX_ITEM_INDEX(_mat, _row, _col))
#define MATRIX_ITEM( _mat, _row, _col) ((_mat)->contigPtr [MATRIX_ITEM_INDEX(_mat, _row, _col)])
#define MATRIX_ROW_INDEX(_mat, _row) (MATRIX_ITEM_INDEX(_mat, _row, 0))
#define MATRIX_ROW_PTR( _mat, _row) ((_mat)->contigPtr + MATRIX_ROW_INDEX(_mat, _row))
typedef struct { typedef struct {
BASE_MATH_MEMBERS(contigPtr); BASE_MATH_MEMBERS(contigPtr);
float *matrix[MATRIX_MAX_DIM]; /* ptr to the contigPtr (accessor) */
unsigned short row_size; unsigned short row_size;
unsigned short col_size; unsigned short col_size;
} MatrixObject; } MatrixObject;
/*struct data contains a pointer to the actual data that the /* struct data contains a pointer to the actual data that the
object uses. It can use either PyMem allocated data (which will * object uses. It can use either PyMem allocated data (which will
be stored in py_data) or be a wrapper for data allocated through * be stored in py_data) or be a wrapper for data allocated through
blender (stored in blend_data). This is an either/or struct not both*/ * blender (stored in blend_data). This is an either/or struct not both */
/*prototypes*/ /* prototypes */
PyObject *Matrix_CreatePyObject(float *mat, PyObject *Matrix_CreatePyObject(float *mat,
const unsigned short row_size, const unsigned short col_size, const unsigned short row_size, const unsigned short col_size,
int type, PyTypeObject *base_type); int type, PyTypeObject *base_type);

@ -1039,7 +1039,7 @@ static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kw
if (!PyArg_ParseTuple(args, "|Od:mathutils.Quaternion", &seq, &angle)) if (!PyArg_ParseTuple(args, "|Od:mathutils.Quaternion", &seq, &angle))
return NULL; return NULL;
switch(PyTuple_GET_SIZE(args)) { switch (PyTuple_GET_SIZE(args)) {
case 0: case 0:
break; break;
case 1: case 1:
@ -1075,18 +1075,18 @@ static PyObject *quat__apply_to_copy(PyNoArgsFunction quat_func, QuaternionObjec
static void quat__axis_angle_sanitize(float axis[3], float *angle) static void quat__axis_angle_sanitize(float axis[3], float *angle)
{ {
if (axis) { if (axis) {
if ( !finite(axis[0]) || if ( !finite(axis[0]) ||
!finite(axis[1]) || !finite(axis[1]) ||
!finite(axis[2])) !finite(axis[2]))
{ {
axis[0]= 1.0f; axis[0]= 1.0f;
axis[1]= 0.0f; axis[1]= 0.0f;
axis[2]= 0.0f; axis[2]= 0.0f;
} }
else if ( EXPP_FloatsAreEqual(axis[0], 0.0f, 10) && else if ( EXPP_FloatsAreEqual(axis[0], 0.0f, 10) &&
EXPP_FloatsAreEqual(axis[1], 0.0f, 10) && EXPP_FloatsAreEqual(axis[1], 0.0f, 10) &&
EXPP_FloatsAreEqual(axis[2], 0.0f, 10) EXPP_FloatsAreEqual(axis[2], 0.0f, 10))
) { {
axis[0] = 1.0f; axis[0] = 1.0f;
} }
} }

@ -54,15 +54,29 @@ static int row_vector_multiplication(float rvec[MAX_DIMENSIONS], VectorObject *v
*/ */
static PyObject *Vector_new(PyTypeObject *type, PyObject *args, PyObject *UNUSED(kwds)) static PyObject *Vector_new(PyTypeObject *type, PyObject *args, PyObject *UNUSED(kwds))
{ {
float vec[4]= {0.0f, 0.0f, 0.0f, 0.0f}; float *vec= NULL;
int size= 3; /* default to a 3D vector */ int size= 3; /* default to a 3D vector */
switch(PyTuple_GET_SIZE(args)) { switch (PyTuple_GET_SIZE(args)) {
case 0: case 0:
vec= PyMem_Malloc(size * sizeof(float));
if (vec == NULL) {
PyErr_SetString(PyExc_MemoryError,
"Vector(): "
"problem allocating pointer space");
return NULL;
}
fill_vn_fl(vec, size, 0.0f);
break; break;
case 1: case 1:
if ((size=mathutils_array_parse(vec, 2, 4, PyTuple_GET_ITEM(args, 0), "mathutils.Vector()")) == -1) if ((size=mathutils_array_parse_alloc(&vec, 2, PyTuple_GET_ITEM(args, 0), "mathutils.Vector()")) == -1) {
if (vec) {
PyMem_Free(vec);
}
return NULL; return NULL;
}
break; break;
default: default:
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
@ -87,6 +101,215 @@ static PyObject *vec__apply_to_copy(PyNoArgsFunction vec_func, VectorObject *sel
} }
} }
/*-----------------------CLASS-METHODS----------------------------*/
PyDoc_STRVAR(C_Vector_Fill_doc,
".. classmethod:: Fill(size, fill=0.0)\n"
"\n"
" Create a vector of length size with all values set to fill.\n"
"\n"
" :arg size: The length of the vector to be created.\n"
" :type size: int\n"
" :arg fill: The value used to fill the vector.\n"
" :type fill: float\n"
);
static PyObject *C_Vector_Fill(PyObject *cls, PyObject *args)
{
float *vec;
int size;
float fill= 0.0f;
if (!PyArg_ParseTuple(args, "i|f:Vector.Fill", &size, &fill)) {
return NULL;
}
if (size < 2) {
PyErr_SetString(PyExc_RuntimeError,
"Vector(): invalid size");
return NULL;
}
vec= PyMem_Malloc(size * sizeof(float));
if (vec == NULL) {
PyErr_SetString(PyExc_MemoryError,
"Vector.Fill(): "
"problem allocating pointer space");
return NULL;
}
fill_vn_fl(vec, size, fill);
return Vector_CreatePyObject_alloc(vec, size, (PyTypeObject *)cls);
}
PyDoc_STRVAR(C_Vector_Range_doc,
".. classmethod:: Range(start=0, stop, step=1)\n"
"\n"
" Create a filled with a range of values.\n"
"\n"
" :arg start: The start of the range used to fill the vector.\n"
" :type start: int\n"
" :arg stop: The end of the range used to fill the vector.\n"
" :type stop: int\n"
" :arg step: The step between successive values in the vector.\n"
" :type step: int\n"
);
static PyObject *C_Vector_Range(PyObject *cls, PyObject *args)
{
float *vec;
int stop, size;
int start= 0;
int step= 1;
if (!PyArg_ParseTuple(args, "i|ii:Vector.Range", &start, &stop, &step)) {
return NULL;
}
switch (PyTuple_GET_SIZE(args)) {
case 1:
size = start;
start= 0;
break;
case 2:
if (start >= stop) {
PyErr_SetString(PyExc_RuntimeError,
"Start value is larger"
"than the stop value");
return NULL;
}
size= stop - start;
break;
default:
if (start >= stop) {
PyErr_SetString(PyExc_RuntimeError,
"Start value is larger"
"than the stop value");
return NULL;
}
size= (stop - start)/step;
if (size%step)
size++;
break;
}
vec= PyMem_Malloc(size * sizeof(float));
if (vec == NULL) {
PyErr_SetString(PyExc_MemoryError,
"Vector.Range(): "
"problem allocating pointer space");
return NULL;
}
range_vn_fl(vec, size, (float)start, (float)step);
return Vector_CreatePyObject_alloc(vec, size, (PyTypeObject *)cls);
}
PyDoc_STRVAR(C_Vector_Linspace_doc,
".. classmethod:: Linspace(start, stop, size)\n"
"\n"
" Create a vector of the specified size which is filled with linearly spaced values between start and stop values.\n"
"\n"
" :arg start: The start of the range used to fill the vector.\n"
" :type start: int\n"
" :arg stop: The end of the range used to fill the vector.\n"
" :type stop: int\n"
" :arg size: The size of the vector to be created.\n"
" :type size: int\n"
);
static PyObject *C_Vector_Linspace(PyObject *cls, PyObject *args)
{
float *vec;
int size;
float start, end, step;
if (!PyArg_ParseTuple(args, "ffi:Vector.Linspace", &start, &end, &size)) {
return NULL;
}
if (size < 2) {
PyErr_SetString(PyExc_RuntimeError,
"Vector.Linspace(): invalid size");
return NULL;
}
step= (end - start)/(float)(size-1);
vec= PyMem_Malloc(size * sizeof(float));
if (vec == NULL) {
PyErr_SetString(PyExc_MemoryError,
"Vector.Linspace(): "
"problem allocating pointer space");
return NULL;
}
range_vn_fl(vec, size, start, step);
return Vector_CreatePyObject_alloc(vec, size, (PyTypeObject *)cls);
}
PyDoc_STRVAR(C_Vector_Repeat_doc,
".. classmethod:: Repeat(vector, size)\n"
"\n"
" Create a vector by repeating the values in vector until the required size is reached.\n"
"\n"
" :arg tuple: The vector to draw values from.\n"
" :type tuple: :class:`mathutils.Vector`\n"
" :arg size: The size of the vector to be created.\n"
" :type size: int\n"
);
static PyObject *C_Vector_Repeat(PyObject *cls, PyObject *args)
{
float *vec;
float *iter_vec= NULL;
int i, size, value_size;
PyObject *value;
if (!PyArg_ParseTuple(args, "Oi:Vector.Repeat", &value, &size)) {
return NULL;
}
if (size < 2) {
PyErr_SetString(PyExc_RuntimeError,
"Vector.Repeat(): invalid size");
return NULL;
}
if ((value_size=mathutils_array_parse_alloc(&iter_vec, 2, value, "Vector.Repeat(vector, size), invalid 'vector' arg")) == -1) {
PyMem_Free(iter_vec);
return NULL;
}
if (iter_vec == NULL) {
PyErr_SetString(PyExc_MemoryError,
"Vector.Repeat(): "
"problem allocating pointer space");
return NULL;
}
vec= PyMem_Malloc(size * sizeof(float));
if (vec == NULL) {
PyErr_SetString(PyExc_MemoryError,
"Vector.Repeat(): "
"problem allocating pointer space");
return NULL;
}
i= 0;
while (i < size) {
vec[i]= iter_vec[i % value_size];
i++;
}
PyMem_Free(iter_vec);
return Vector_CreatePyObject_alloc(vec, size, (PyTypeObject *)cls);
}
/*-----------------------------METHODS---------------------------- */ /*-----------------------------METHODS---------------------------- */
PyDoc_STRVAR(Vector_zero_doc, PyDoc_STRVAR(Vector_zero_doc,
".. method:: zero()\n" ".. method:: zero()\n"
@ -137,6 +360,101 @@ static PyObject *Vector_normalized(VectorObject *self)
return vec__apply_to_copy((PyNoArgsFunction)Vector_normalize, self); return vec__apply_to_copy((PyNoArgsFunction)Vector_normalize, self);
} }
PyDoc_STRVAR(Vector_resize_doc,
".. method:: resize(size=3)\n"
"\n"
" Resize the vector to have size number of elements.\n"
"\n"
" :return: an instance of itself\n"
" :rtype: :class:`Vector`\n"
);
static PyObject *Vector_resize(VectorObject *self, PyObject *value)
{
int size;
if (self->wrapped==Py_WRAP) {
PyErr_SetString(PyExc_TypeError,
"Vector.resize(): "
"cannot resize wrapped data - only python vectors");
return NULL;
}
if (self->cb_user) {
PyErr_SetString(PyExc_TypeError,
"Vector.resize(): "
"cannot resize a vector that has an owner");
return NULL;
}
if ((size = PyLong_AsLong(value)) == -1) {
PyErr_SetString(PyExc_TypeError,
"Vector.resize(size): "
"expected size argument to be an integer");
return NULL;
}
if (size < 2) {
PyErr_SetString(PyExc_RuntimeError,
"Vector.resize(): invalid size");
return NULL;
}
self->vec = PyMem_Realloc(self->vec, (size * sizeof(float)));
if (self->vec == NULL) {
PyErr_SetString(PyExc_MemoryError,
"Vector.resize(): "
"problem allocating pointer space");
return NULL;
}
/* If the vector has increased in length, set all new elements to 0.0f */
if (size > self->size) {
fill_vn_fl(self->vec + self->size, size - self->size, 0.0f);
}
self->size = size;
Py_RETURN_NONE;
}
PyDoc_STRVAR(Vector_resized_doc,
".. method:: resized(size=3)\n"
"\n"
" Return a resized copy of the vector with size number of elements.\n"
"\n"
" :return: a new vector\n"
" :rtype: :class:`Vector`\n"
);
static PyObject *Vector_resized(VectorObject *self, PyObject *value)
{
int size;
float *vec;
/*if (!PyArg_ParseTuple(args, "i:resize", &size))
return NULL;*/
if ((size = PyLong_AsLong(value)) == -1) {
return NULL;
}
if (size < 2) {
PyErr_SetString(PyExc_RuntimeError,
"Vector.resized(): invalid size");
return NULL;
}
vec= PyMem_Malloc(size * sizeof(float));
if (vec == NULL) {
PyErr_SetString(PyExc_MemoryError,
"Vector.resized(): "
"problem allocating pointer space");
return NULL;
}
fill_vn_fl(vec, size, 0.0f);
memcpy(vec, self->vec, self->size * sizeof(float));
return Vector_CreatePyObject_alloc(vec, size, NULL);
}
PyDoc_STRVAR(Vector_resize_2d_doc, PyDoc_STRVAR(Vector_resize_2d_doc,
".. method:: resize_2d()\n" ".. method:: resize_2d()\n"
"\n" "\n"
@ -394,7 +712,7 @@ static PyObject *Vector_to_track_quat(VectorObject *self, PyObject *args)
if (strlen(strack) == 2) { if (strlen(strack) == 2) {
if (strack[0] == '-') { if (strack[0] == '-') {
switch(strack[1]) { switch (strack[1]) {
case 'X': case 'X':
track = 3; track = 3;
break; break;
@ -415,7 +733,7 @@ static PyObject *Vector_to_track_quat(VectorObject *self, PyObject *args)
} }
} }
else if (strlen(strack) == 1) { else if (strlen(strack) == 1) {
switch(strack[0]) { switch (strack[0]) {
case '-': case '-':
case 'X': case 'X':
track = 0; track = 0;
@ -440,7 +758,7 @@ static PyObject *Vector_to_track_quat(VectorObject *self, PyObject *args)
if (sup) { if (sup) {
const char *axis_err_msg= "only X, Y or Z for up axis"; const char *axis_err_msg= "only X, Y or Z for up axis";
if (strlen(sup) == 1) { if (strlen(sup) == 1) {
switch(*sup) { switch (*sup) {
case 'X': case 'X':
up = 0; up = 0;
break; break;
@ -505,6 +823,12 @@ static PyObject *Vector_reflect(VectorObject *self, PyObject *value)
if ((value_size= mathutils_array_parse(tvec, 2, 4, value, "Vector.reflect(other), invalid 'other' arg")) == -1) if ((value_size= mathutils_array_parse(tvec, 2, 4, value, "Vector.reflect(other), invalid 'other' arg")) == -1)
return NULL; return NULL;
if (self->size < 2 || self->size > 4) {
PyErr_SetString(PyExc_ValueError,
"Vector must be 2D, 3D or 4D");
return NULL;
}
mirror[0] = tvec[0]; mirror[0] = tvec[0];
mirror[1] = tvec[1]; mirror[1] = tvec[1];
if (value_size > 2) mirror[2] = tvec[2]; if (value_size > 2) mirror[2] = tvec[2];
@ -544,6 +868,12 @@ static PyObject *Vector_cross(VectorObject *self, PyObject *value)
if (mathutils_array_parse(tvec, self->size, self->size, value, "Vector.cross(other), invalid 'other' arg") == -1) if (mathutils_array_parse(tvec, self->size, self->size, value, "Vector.cross(other), invalid 'other' arg") == -1)
return NULL; return NULL;
if (self->size != 3) {
PyErr_SetString(PyExc_ValueError,
"Vector must be 3D");
return NULL;
}
ret= (VectorObject *)Vector_CreatePyObject(NULL, 3, Py_NEW, Py_TYPE(self)); ret= (VectorObject *)Vector_CreatePyObject(NULL, 3, Py_NEW, Py_TYPE(self));
cross_v3_v3v3(ret->vec, self->vec, tvec); cross_v3_v3v3(ret->vec, self->vec, tvec);
return (PyObject *)ret; return (PyObject *)ret;
@ -561,15 +891,20 @@ PyDoc_STRVAR(Vector_dot_doc,
); );
static PyObject *Vector_dot(VectorObject *self, PyObject *value) static PyObject *Vector_dot(VectorObject *self, PyObject *value)
{ {
float tvec[MAX_DIMENSIONS]; float *tvec;
if (BaseMath_ReadCallback(self) == -1) if (BaseMath_ReadCallback(self) == -1)
return NULL; return NULL;
if (mathutils_array_parse(tvec, self->size, self->size, value, "Vector.dot(other), invalid 'other' arg") == -1) if (mathutils_array_parse_alloc(&tvec, self->size, value, "Vector.dot(other), invalid 'other' arg") == -1) {
return NULL; goto cleanup;
}
return PyFloat_FromDouble(dot_vn_vn(self->vec, tvec, self->size)); return PyFloat_FromDouble(dot_vn_vn(self->vec, tvec, self->size));
cleanup:
PyMem_Free(tvec);
return NULL;
} }
PyDoc_STRVAR(Vector_angle_doc, PyDoc_STRVAR(Vector_angle_doc,
@ -607,6 +942,12 @@ static PyObject *Vector_angle(VectorObject *self, PyObject *args)
if (mathutils_array_parse(tvec, self->size, self->size, value, "Vector.angle(other), invalid 'other' arg") == -1) if (mathutils_array_parse(tvec, self->size, self->size, value, "Vector.angle(other), invalid 'other' arg") == -1)
return NULL; return NULL;
if (self->size > 4) {
PyErr_SetString(PyExc_ValueError,
"Vector must be 2D, 3D or 4D");
return NULL;
}
for (x = 0; x < size; x++) { for (x = 0; x < size; x++) {
dot_self += (double)self->vec[x] * (double)self->vec[x]; dot_self += (double)self->vec[x] * (double)self->vec[x];
dot_other += (double)tvec[x] * (double)tvec[x]; dot_other += (double)tvec[x] * (double)tvec[x];
@ -647,7 +988,7 @@ static PyObject *Vector_rotation_difference(VectorObject *self, PyObject *value)
{ {
float quat[4], vec_a[3], vec_b[3]; float quat[4], vec_a[3], vec_b[3];
if (self->size < 3) { if (self->size < 3 || self->size > 4) {
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_ValueError,
"vec.difference(value): " "vec.difference(value): "
"expects both vectors to be size 3 or 4"); "expects both vectors to be size 3 or 4");
@ -692,6 +1033,12 @@ static PyObject *Vector_project(VectorObject *self, PyObject *value)
if (mathutils_array_parse(tvec, size, size, value, "Vector.project(other), invalid 'other' arg") == -1) if (mathutils_array_parse(tvec, size, size, value, "Vector.project(other), invalid 'other' arg") == -1)
return NULL; return NULL;
if (self->size > 4) {
PyErr_SetString(PyExc_ValueError,
"Vector must be 2D, 3D or 4D");
return NULL;
}
if (BaseMath_ReadCallback(self) == -1) if (BaseMath_ReadCallback(self) == -1)
return NULL; return NULL;
@ -725,24 +1072,41 @@ static PyObject *Vector_lerp(VectorObject *self, PyObject *args)
const int size= self->size; const int size= self->size;
PyObject *value= NULL; PyObject *value= NULL;
float fac, ifac; float fac, ifac;
float tvec[MAX_DIMENSIONS], vec[MAX_DIMENSIONS]; float *tvec, *vec;
int x; int x;
if (!PyArg_ParseTuple(args, "Of:lerp", &value, &fac)) if (!PyArg_ParseTuple(args, "Of:lerp", &value, &fac))
return NULL; return NULL;
if (mathutils_array_parse(tvec, size, size, value, "Vector.lerp(other), invalid 'other' arg") == -1) if (mathutils_array_parse_alloc(&tvec, size, value, "Vector.lerp(other), invalid 'other' arg") == -1) {
return NULL; goto cleanup;
}
if (BaseMath_ReadCallback(self) == -1) if (BaseMath_ReadCallback(self) == -1) {
goto cleanup;
}
vec= PyMem_Malloc(size * sizeof(float));
if (vec == NULL) {
PyErr_SetString(PyExc_MemoryError,
"Vector.lerp(): "
"problem allocating pointer space");
return NULL; return NULL;
}
ifac= 1.0f - fac; ifac= 1.0f - fac;
for (x = 0; x < size; x++) { for (x = 0; x < size; x++) {
vec[x] = (ifac * self->vec[x]) + (fac * tvec[x]); vec[x] = (ifac * self->vec[x]) + (fac * tvec[x]);
} }
return Vector_CreatePyObject(vec, size, Py_NEW, Py_TYPE(self));
PyMem_Free(tvec);
return Vector_CreatePyObject_alloc(vec, size, Py_TYPE(self));
cleanup:
PyMem_Free(tvec);
return NULL;
} }
PyDoc_STRVAR(Vector_rotate_doc, PyDoc_STRVAR(Vector_rotate_doc,
@ -763,7 +1127,7 @@ static PyObject *Vector_rotate(VectorObject *self, PyObject *value)
if (mathutils_any_to_rotmat(other_rmat, value, "Vector.rotate(value)") == -1) if (mathutils_any_to_rotmat(other_rmat, value, "Vector.rotate(value)") == -1)
return NULL; return NULL;
if (self->size < 3) { if (self->size < 3 || self->size > 4) {
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_ValueError,
"Vector must be 3D or 4D"); "Vector must be 3D or 4D");
return NULL; return NULL;
@ -903,8 +1267,8 @@ static PyObject *Vector_slice(VectorObject *self, int begin, int end)
/* sequence slice (set): vector[a:b] = value */ /* sequence slice (set): vector[a:b] = value */
static int Vector_ass_slice(VectorObject *self, int begin, int end, PyObject *seq) static int Vector_ass_slice(VectorObject *self, int begin, int end, PyObject *seq)
{ {
int y, size = 0; int size = 0;
float vec[MAX_DIMENSIONS]; float *vec= NULL;
if (BaseMath_ReadCallback(self) == -1) if (BaseMath_ReadCallback(self) == -1)
return -1; return -1;
@ -914,18 +1278,30 @@ static int Vector_ass_slice(VectorObject *self, int begin, int end, PyObject *se
begin = MIN2(begin, end); begin = MIN2(begin, end);
size = (end - begin); size = (end - begin);
if (mathutils_array_parse(vec, size, size, seq, "vector[begin:end] = [...]") == -1) if (mathutils_array_parse_alloc(&vec, size, seq, "vector[begin:end] = [...]") == -1) {
goto cleanup;
}
if (vec == NULL) {
PyErr_SetString(PyExc_MemoryError,
"vec[:] = seq: "
"problem allocating pointer space");
return -1; return -1;
}
/*parsed well - now set in vector*/ /*parsed well - now set in vector*/
for (y = 0; y < size; y++) { memcpy(self->vec + begin, vec, size * sizeof(float));
self->vec[begin + y] = vec[y];
}
if (BaseMath_WriteCallback(self) == -1) if (BaseMath_WriteCallback(self) == -1)
return -1; return -1;
PyMem_Free(vec);
return 0; return 0;
cleanup:
PyMem_Free(vec);
return -1;
} }
/* Numeric Protocols */ /* Numeric Protocols */
@ -933,7 +1309,7 @@ static int Vector_ass_slice(VectorObject *self, int begin, int end, PyObject *se
static PyObject *Vector_add(PyObject *v1, PyObject *v2) static PyObject *Vector_add(PyObject *v1, PyObject *v2)
{ {
VectorObject *vec1 = NULL, *vec2 = NULL; VectorObject *vec1 = NULL, *vec2 = NULL;
float vec[MAX_DIMENSIONS]; float *vec= NULL;
if (!VectorObject_Check(v1) || !VectorObject_Check(v2)) { if (!VectorObject_Check(v1) || !VectorObject_Check(v2)) {
PyErr_Format(PyExc_AttributeError, PyErr_Format(PyExc_AttributeError,
@ -956,9 +1332,18 @@ static PyObject *Vector_add(PyObject *v1, PyObject *v2)
return NULL; return NULL;
} }
vec= PyMem_Malloc(vec1->size * sizeof(float));
if (vec == NULL) { /*allocation failure*/
PyErr_SetString(PyExc_MemoryError,
"Vector(): "
"problem allocating pointer space");
return NULL;
}
add_vn_vnvn(vec, vec1->vec, vec2->vec, vec1->size); add_vn_vnvn(vec, vec1->vec, vec2->vec, vec1->size);
return Vector_CreatePyObject(vec, vec1->size, Py_NEW, Py_TYPE(v1)); return Vector_CreatePyObject_alloc(vec, vec1->size, Py_TYPE(v1));
} }
/* addition in-place: obj += obj */ /* addition in-place: obj += obj */
@ -997,7 +1382,7 @@ static PyObject *Vector_iadd(PyObject *v1, PyObject *v2)
static PyObject *Vector_sub(PyObject *v1, PyObject *v2) static PyObject *Vector_sub(PyObject *v1, PyObject *v2)
{ {
VectorObject *vec1 = NULL, *vec2 = NULL; VectorObject *vec1 = NULL, *vec2 = NULL;
float vec[MAX_DIMENSIONS]; float *vec;
if (!VectorObject_Check(v1) || !VectorObject_Check(v2)) { if (!VectorObject_Check(v1) || !VectorObject_Check(v2)) {
PyErr_Format(PyExc_AttributeError, PyErr_Format(PyExc_AttributeError,
@ -1019,9 +1404,18 @@ static PyObject *Vector_sub(PyObject *v1, PyObject *v2)
return NULL; return NULL;
} }
vec= PyMem_Malloc(vec1->size * sizeof(float));
if (vec == NULL) { /*allocation failure*/
PyErr_SetString(PyExc_MemoryError,
"Vector(): "
"problem allocating pointer space");
return NULL;
}
sub_vn_vnvn(vec, vec1->vec, vec2->vec, vec1->size); sub_vn_vnvn(vec, vec1->vec, vec2->vec, vec1->size);
return Vector_CreatePyObject(vec, vec1->size, Py_NEW, Py_TYPE(v1)); return Vector_CreatePyObject_alloc(vec, vec1->size, Py_TYPE(v1));
} }
/* subtraction in-place: obj -= obj */ /* subtraction in-place: obj -= obj */
@ -1093,7 +1487,7 @@ int column_vector_multiplication(float rvec[MAX_DIMENSIONS], VectorObject* vec,
for (x = 0; x < mat->col_size; x++) { for (x = 0; x < mat->col_size; x++) {
for (y = 0; y < mat->row_size; y++) { for (y = 0; y < mat->row_size; y++) {
dot += (double)(mat->matrix[y][x] * vec_cpy[y]); dot += (double)(MATRIX_ITEM(mat, y, x) * vec_cpy[y]);
} }
rvec[z++] = (float)dot; rvec[z++] = (float)dot;
dot = 0.0f; dot = 0.0f;
@ -1104,9 +1498,18 @@ int column_vector_multiplication(float rvec[MAX_DIMENSIONS], VectorObject* vec,
static PyObject *vector_mul_float(VectorObject *vec, const float scalar) static PyObject *vector_mul_float(VectorObject *vec, const float scalar)
{ {
float tvec[MAX_DIMENSIONS]; float *tvec= NULL;
tvec= PyMem_Malloc(vec->size * sizeof(float));
if (tvec == NULL) { /*allocation failure*/
PyErr_SetString(PyExc_MemoryError,
"vec * float: "
"problem allocating pointer space");
return NULL;
}
mul_vn_vn_fl(tvec, vec->vec, vec->size, scalar); mul_vn_vn_fl(tvec, vec->vec, vec->size, scalar);
return Vector_CreatePyObject(tvec, vec->size, Py_NEW, Py_TYPE(vec)); return Vector_CreatePyObject_alloc(tvec, vec->size, Py_TYPE(vec));
} }
static PyObject *Vector_mul(PyObject *v1, PyObject *v2) static PyObject *Vector_mul(PyObject *v1, PyObject *v2)
@ -1277,8 +1680,7 @@ static PyObject *Vector_imul(PyObject *v1, PyObject *v2)
/* divid: obj / obj */ /* divid: obj / obj */
static PyObject *Vector_div(PyObject *v1, PyObject *v2) static PyObject *Vector_div(PyObject *v1, PyObject *v2)
{ {
int i; float *vec= NULL, scalar;
float vec[4], scalar;
VectorObject *vec1 = NULL; VectorObject *vec1 = NULL;
if (!VectorObject_Check(v1)) { /* not a vector */ if (!VectorObject_Check(v1)) { /* not a vector */
@ -1287,7 +1689,7 @@ static PyObject *Vector_div(PyObject *v1, PyObject *v2)
"Vector must be divided by a float"); "Vector must be divided by a float");
return NULL; return NULL;
} }
vec1 = (VectorObject*)v1; /* vector */ vec1 = (VectorObject *)v1; /* vector */
if (BaseMath_ReadCallback(vec1) == -1) if (BaseMath_ReadCallback(vec1) == -1)
return NULL; return NULL;
@ -1306,16 +1708,23 @@ static PyObject *Vector_div(PyObject *v1, PyObject *v2)
return NULL; return NULL;
} }
for (i = 0; i < vec1->size; i++) { vec= PyMem_Malloc(vec1->size * sizeof(float));
vec[i] = vec1->vec[i] / scalar;
if (vec == NULL) { /*allocation failure*/
PyErr_SetString(PyExc_MemoryError,
"vec / value: "
"problem allocating pointer space");
return NULL;
} }
return Vector_CreatePyObject(vec, vec1->size, Py_NEW, Py_TYPE(v1));
mul_vn_vn_fl(vec, vec1->vec, vec1->size, 1.0f/scalar);
return Vector_CreatePyObject_alloc(vec, vec1->size, Py_TYPE(v1));
} }
/* divide in-place: obj /= obj */ /* divide in-place: obj /= obj */
static PyObject *Vector_idiv(PyObject *v1, PyObject *v2) static PyObject *Vector_idiv(PyObject *v1, PyObject *v2)
{ {
int i;
float scalar; float scalar;
VectorObject *vec1 = (VectorObject*)v1; VectorObject *vec1 = (VectorObject*)v1;
@ -1335,9 +1744,8 @@ static PyObject *Vector_idiv(PyObject *v1, PyObject *v2)
"divide by zero error"); "divide by zero error");
return NULL; return NULL;
} }
for (i = 0; i < vec1->size; i++) {
vec1->vec[i] /= scalar; mul_vn_fl(vec1->vec, vec1->size, 1.0f/scalar);
}
(void)BaseMath_WriteCallback(vec1); (void)BaseMath_WriteCallback(vec1);
@ -1349,29 +1757,24 @@ static PyObject *Vector_idiv(PyObject *v1, PyObject *v2)
returns the negative of this object*/ returns the negative of this object*/
static PyObject *Vector_neg(VectorObject *self) static PyObject *Vector_neg(VectorObject *self)
{ {
float tvec[MAX_DIMENSIONS]; float *tvec;
if (BaseMath_ReadCallback(self) == -1) if (BaseMath_ReadCallback(self) == -1)
return NULL; return NULL;
tvec= PyMem_Malloc(self->size * sizeof(float));
negate_vn_vn(tvec, self->vec, self->size); negate_vn_vn(tvec, self->vec, self->size);
return Vector_CreatePyObject(tvec, self->size, Py_NEW, Py_TYPE(self)); return Vector_CreatePyObject_alloc(tvec, self->size, Py_TYPE(self));
} }
/*------------------------vec_magnitude_nosqrt (internal) - for comparing only */ /*------------------------vec_magnitude_nosqrt (internal) - for comparing only */
static double vec_magnitude_nosqrt(float *data, int size) static double vec_magnitude_nosqrt(float *data, int size)
{ {
double dot = 0.0f;
int i;
for (i=0; i<size; i++) {
dot += (double)data[i];
}
/*return (double)sqrt(dot);*/ /*return (double)sqrt(dot);*/
/* warning, line above removed because we are not using the length, /* warning, line above removed because we are not using the length,
rather the comparing the sizes and for this we do not need the sqrt rather the comparing the sizes and for this we do not need the sqrt
for the actual length, the dot must be sqrt'd */ for the actual length, the dot must be sqrt'd */
return dot; return dot_vn_vn(data, data, size);
} }
@ -1606,16 +2009,10 @@ static int Vector_setAxis(VectorObject *self, PyObject *value, void *type)
/* vector.length */ /* vector.length */
static PyObject *Vector_getLength(VectorObject *self, void *UNUSED(closure)) static PyObject *Vector_getLength(VectorObject *self, void *UNUSED(closure))
{ {
double dot = 0.0f;
int i;
if (BaseMath_ReadCallback(self) == -1) if (BaseMath_ReadCallback(self) == -1)
return NULL; return NULL;
for (i = 0; i < self->size; i++) { return PyFloat_FromDouble(sqrt(dot_vn_vn(self->vec, self->vec, self->size)));
dot += (double)(self->vec[i] * self->vec[i]);
}
return PyFloat_FromDouble(sqrt(dot));
} }
static int Vector_setLength(VectorObject *self, PyObject *value) static int Vector_setLength(VectorObject *self, PyObject *value)
@ -2213,7 +2610,7 @@ static int row_vector_multiplication(float rvec[MAX_DIMENSIONS], VectorObject *v
//muliplication //muliplication
for (x = 0; x < mat->row_size; x++) { for (x = 0; x < mat->row_size; x++) {
for (y = 0; y < mat->col_size; y++) { for (y = 0; y < mat->col_size; y++) {
dot += mat->matrix[x][y] * vec_cpy[y]; dot += MATRIX_ITEM(mat, x, y) * vec_cpy[y];
} }
rvec[z++] = (float)dot; rvec[z++] = (float)dot;
dot = 0.0f; dot = 0.0f;
@ -2242,6 +2639,12 @@ static PyObject *Vector_negate(VectorObject *self)
} }
static struct PyMethodDef Vector_methods[] = { static struct PyMethodDef Vector_methods[] = {
/* Class Methods */
{"Fill", (PyCFunction) C_Vector_Fill, METH_VARARGS | METH_CLASS, C_Vector_Fill_doc},
{"Range", (PyCFunction) C_Vector_Range, METH_VARARGS | METH_CLASS, C_Vector_Range_doc},
{"Linspace", (PyCFunction) C_Vector_Linspace, METH_VARARGS | METH_CLASS, C_Vector_Linspace_doc},
{"Repeat", (PyCFunction) C_Vector_Repeat, METH_VARARGS | METH_CLASS, C_Vector_Repeat_doc},
/* in place only */ /* in place only */
{"zero", (PyCFunction) Vector_zero, METH_NOARGS, Vector_zero_doc}, {"zero", (PyCFunction) Vector_zero, METH_NOARGS, Vector_zero_doc},
{"negate", (PyCFunction) Vector_negate, METH_NOARGS, Vector_negate_doc}, {"negate", (PyCFunction) Vector_negate, METH_NOARGS, Vector_negate_doc},
@ -2250,6 +2653,8 @@ static struct PyMethodDef Vector_methods[] = {
{"normalize", (PyCFunction) Vector_normalize, METH_NOARGS, Vector_normalize_doc}, {"normalize", (PyCFunction) Vector_normalize, METH_NOARGS, Vector_normalize_doc},
{"normalized", (PyCFunction) Vector_normalized, METH_NOARGS, Vector_normalized_doc}, {"normalized", (PyCFunction) Vector_normalized, METH_NOARGS, Vector_normalized_doc},
{"resize", (PyCFunction) Vector_resize, METH_O, Vector_resize_doc},
{"resized", (PyCFunction) Vector_resized, METH_O, Vector_resized_doc},
{"to_2d", (PyCFunction) Vector_to_2d, METH_NOARGS, Vector_to_2d_doc}, {"to_2d", (PyCFunction) Vector_to_2d, METH_NOARGS, Vector_to_2d_doc},
{"resize_2d", (PyCFunction) Vector_resize_2d, METH_NOARGS, Vector_resize_2d_doc}, {"resize_2d", (PyCFunction) Vector_resize_2d, METH_NOARGS, Vector_resize_2d_doc},
{"to_3d", (PyCFunction) Vector_to_3d, METH_NOARGS, Vector_to_3d_doc}, {"to_3d", (PyCFunction) Vector_to_3d, METH_NOARGS, Vector_to_3d_doc},
@ -2375,7 +2780,7 @@ PyObject *Vector_CreatePyObject(float *vec, const int size, const int type, PyTy
{ {
VectorObject *self; VectorObject *self;
if (size > 4 || size < 2) { if (size < 2) {
PyErr_SetString(PyExc_RuntimeError, PyErr_SetString(PyExc_RuntimeError,
"Vector(): invalid size"); "Vector(): invalid size");
return NULL; return NULL;
@ -2429,3 +2834,12 @@ PyObject *Vector_CreatePyObject_cb(PyObject *cb_user, int size, int cb_type, int
return (PyObject *)self; return (PyObject *)self;
} }
PyObject *Vector_CreatePyObject_alloc(float *vec, const int size, PyTypeObject *base_type)
{
VectorObject *vect_ob;
vect_ob= (VectorObject *)Vector_CreatePyObject(vec, size, Py_WRAP, base_type);
vect_ob->wrapped= Py_NEW;
return (PyObject *)vect_ob;
}

@ -41,11 +41,12 @@ extern PyTypeObject vector_Type;
typedef struct { typedef struct {
BASE_MATH_MEMBERS(vec); BASE_MATH_MEMBERS(vec);
unsigned char size; /* vec size 2,3 or 4 */ int size; /* vec size 2,3 or 4 */
} VectorObject; } VectorObject;
/*prototypes*/ /*prototypes*/
PyObject *Vector_CreatePyObject(float *vec, const int size, const int type, PyTypeObject *base_type); PyObject *Vector_CreatePyObject(float *vec, const int size, const int type, PyTypeObject *base_type);
PyObject *Vector_CreatePyObject_cb(PyObject *user, int size, int callback_type, int subtype); PyObject *Vector_CreatePyObject_cb(PyObject *user, int size, int callback_type, int subtype);
PyObject *Vector_CreatePyObject_alloc(float *vec, const int size, PyTypeObject *base_type);
#endif /* MATHUTILS_VECTOR_H */ #endif /* MATHUTILS_VECTOR_H */

@ -99,11 +99,11 @@ static PyObject *M_Geometry_intersect_ray_tri(PyObject *UNUSED(self), PyObject*
return NULL; return NULL;
} }
if ( BaseMath_ReadCallback(vec1) == -1 || if ( BaseMath_ReadCallback(vec1) == -1 ||
BaseMath_ReadCallback(vec2) == -1 || BaseMath_ReadCallback(vec2) == -1 ||
BaseMath_ReadCallback(vec3) == -1 || BaseMath_ReadCallback(vec3) == -1 ||
BaseMath_ReadCallback(ray) == -1 || BaseMath_ReadCallback(ray) == -1 ||
BaseMath_ReadCallback(ray_off) == -1) BaseMath_ReadCallback(ray_off) == -1)
{ {
return NULL; return NULL;
} }
@ -199,10 +199,10 @@ static PyObject *M_Geometry_intersect_line_line(PyObject *UNUSED(self), PyObject
return NULL; return NULL;
} }
if ( BaseMath_ReadCallback(vec1) == -1 || if ( BaseMath_ReadCallback(vec1) == -1 ||
BaseMath_ReadCallback(vec2) == -1 || BaseMath_ReadCallback(vec2) == -1 ||
BaseMath_ReadCallback(vec3) == -1 || BaseMath_ReadCallback(vec3) == -1 ||
BaseMath_ReadCallback(vec4) == -1) BaseMath_ReadCallback(vec4) == -1)
{ {
return NULL; return NULL;
} }
@ -298,9 +298,9 @@ static PyObject *M_Geometry_normal(PyObject *UNUSED(self), PyObject* args)
return NULL; return NULL;
} }
if ( BaseMath_ReadCallback(vec1) == -1 || if ( BaseMath_ReadCallback(vec1) == -1 ||
BaseMath_ReadCallback(vec2) == -1 || BaseMath_ReadCallback(vec2) == -1 ||
BaseMath_ReadCallback(vec3) == -1) BaseMath_ReadCallback(vec3) == -1)
{ {
return NULL; return NULL;
} }
@ -327,10 +327,10 @@ static PyObject *M_Geometry_normal(PyObject *UNUSED(self), PyObject* args)
return NULL; return NULL;
} }
if ( BaseMath_ReadCallback(vec1) == -1 || if ( BaseMath_ReadCallback(vec1) == -1 ||
BaseMath_ReadCallback(vec2) == -1 || BaseMath_ReadCallback(vec2) == -1 ||
BaseMath_ReadCallback(vec3) == -1 || BaseMath_ReadCallback(vec3) == -1 ||
BaseMath_ReadCallback(vec4) == -1) BaseMath_ReadCallback(vec4) == -1)
{ {
return NULL; return NULL;
} }
@ -374,9 +374,9 @@ static PyObject *M_Geometry_area_tri(PyObject *UNUSED(self), PyObject* args)
return NULL; return NULL;
} }
if ( BaseMath_ReadCallback(vec1) == -1 || if ( BaseMath_ReadCallback(vec1) == -1 ||
BaseMath_ReadCallback(vec2) == -1 || BaseMath_ReadCallback(vec2) == -1 ||
BaseMath_ReadCallback(vec3) == -1) BaseMath_ReadCallback(vec3) == -1)
{ {
return NULL; return NULL;
} }
@ -424,10 +424,10 @@ static PyObject *M_Geometry_intersect_line_line_2d(PyObject *UNUSED(self), PyObj
return NULL; return NULL;
} }
if ( BaseMath_ReadCallback(line_a1) == -1 || if ( BaseMath_ReadCallback(line_a1) == -1 ||
BaseMath_ReadCallback(line_a2) == -1 || BaseMath_ReadCallback(line_a2) == -1 ||
BaseMath_ReadCallback(line_b1) == -1 || BaseMath_ReadCallback(line_b1) == -1 ||
BaseMath_ReadCallback(line_b2) == -1) BaseMath_ReadCallback(line_b2) == -1)
{ {
return NULL; return NULL;
} }
@ -474,10 +474,10 @@ static PyObject *M_Geometry_intersect_line_plane(PyObject *UNUSED(self), PyObjec
return NULL; return NULL;
} }
if ( BaseMath_ReadCallback(line_a) == -1 || if ( BaseMath_ReadCallback(line_a) == -1 ||
BaseMath_ReadCallback(line_b) == -1 || BaseMath_ReadCallback(line_b) == -1 ||
BaseMath_ReadCallback(plane_co) == -1 || BaseMath_ReadCallback(plane_co) == -1 ||
BaseMath_ReadCallback(plane_no) == -1) BaseMath_ReadCallback(plane_no) == -1)
{ {
return NULL; return NULL;
} }
@ -530,10 +530,10 @@ static PyObject *M_Geometry_intersect_plane_plane(PyObject *UNUSED(self), PyObje
return NULL; return NULL;
} }
if ( BaseMath_ReadCallback(plane_a_co) == -1 || if ( BaseMath_ReadCallback(plane_a_co) == -1 ||
BaseMath_ReadCallback(plane_a_no) == -1 || BaseMath_ReadCallback(plane_a_no) == -1 ||
BaseMath_ReadCallback(plane_b_co) == -1 || BaseMath_ReadCallback(plane_b_co) == -1 ||
BaseMath_ReadCallback(plane_b_no) == -1) BaseMath_ReadCallback(plane_b_no) == -1)
{ {
return NULL; return NULL;
} }
@ -592,9 +592,9 @@ static PyObject *M_Geometry_intersect_line_sphere(PyObject *UNUSED(self), PyObje
return NULL; return NULL;
} }
if ( BaseMath_ReadCallback(line_a) == -1 || if ( BaseMath_ReadCallback(line_a) == -1 ||
BaseMath_ReadCallback(line_b) == -1 || BaseMath_ReadCallback(line_b) == -1 ||
BaseMath_ReadCallback(sphere_co) == -1) BaseMath_ReadCallback(sphere_co) == -1)
{ {
return NULL; return NULL;
} }
@ -612,7 +612,7 @@ static PyObject *M_Geometry_intersect_line_sphere(PyObject *UNUSED(self), PyObje
PyObject *ret= PyTuple_New(2); PyObject *ret= PyTuple_New(2);
switch(isect_line_sphere_v3(line_a->vec, line_b->vec, sphere_co->vec, sphere_radius, isect_a, isect_b)) { switch (isect_line_sphere_v3(line_a->vec, line_b->vec, sphere_co->vec, sphere_radius, isect_a, isect_b)) {
case 1: case 1:
if (!(!clip || (((lambda= line_point_factor_v3(isect_a, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_a= FALSE; if (!(!clip || (((lambda= line_point_factor_v3(isect_a, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_a= FALSE;
use_b= FALSE; use_b= FALSE;
@ -672,9 +672,9 @@ static PyObject *M_Geometry_intersect_line_sphere_2d(PyObject *UNUSED(self), PyO
return NULL; return NULL;
} }
if ( BaseMath_ReadCallback(line_a) == -1 || if ( BaseMath_ReadCallback(line_a) == -1 ||
BaseMath_ReadCallback(line_b) == -1 || BaseMath_ReadCallback(line_b) == -1 ||
BaseMath_ReadCallback(sphere_co) == -1) BaseMath_ReadCallback(sphere_co) == -1)
{ {
return NULL; return NULL;
} }
@ -685,7 +685,7 @@ static PyObject *M_Geometry_intersect_line_sphere_2d(PyObject *UNUSED(self), PyO
PyObject *ret= PyTuple_New(2); PyObject *ret= PyTuple_New(2);
switch(isect_line_sphere_v2(line_a->vec, line_b->vec, sphere_co->vec, sphere_radius, isect_a, isect_b)) { switch (isect_line_sphere_v2(line_a->vec, line_b->vec, sphere_co->vec, sphere_radius, isect_a, isect_b)) {
case 1: case 1:
if (!(!clip || (((lambda= line_point_factor_v2(isect_a, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_a= FALSE; if (!(!clip || (((lambda= line_point_factor_v2(isect_a, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_a= FALSE;
use_b= FALSE; use_b= FALSE;
@ -737,9 +737,9 @@ static PyObject *M_Geometry_intersect_point_line(PyObject *UNUSED(self), PyObjec
return NULL; return NULL;
} }
if ( BaseMath_ReadCallback(pt) == -1 || if ( BaseMath_ReadCallback(pt) == -1 ||
BaseMath_ReadCallback(line_1) == -1 || BaseMath_ReadCallback(line_1) == -1 ||
BaseMath_ReadCallback(line_2) == -1) BaseMath_ReadCallback(line_2) == -1)
{ {
return NULL; return NULL;
} }
@ -791,10 +791,10 @@ static PyObject *M_Geometry_intersect_point_tri_2d(PyObject *UNUSED(self), PyObj
return NULL; return NULL;
} }
if ( BaseMath_ReadCallback(pt_vec) == -1 || if ( BaseMath_ReadCallback(pt_vec) == -1 ||
BaseMath_ReadCallback(tri_p1) == -1 || BaseMath_ReadCallback(tri_p1) == -1 ||
BaseMath_ReadCallback(tri_p2) == -1 || BaseMath_ReadCallback(tri_p2) == -1 ||
BaseMath_ReadCallback(tri_p3) == -1) BaseMath_ReadCallback(tri_p3) == -1)
{ {
return NULL; return NULL;
} }
@ -834,11 +834,11 @@ static PyObject *M_Geometry_intersect_point_quad_2d(PyObject *UNUSED(self), PyOb
return NULL; return NULL;
} }
if ( BaseMath_ReadCallback(pt_vec) == -1 || if ( BaseMath_ReadCallback(pt_vec) == -1 ||
BaseMath_ReadCallback(quad_p1) == -1 || BaseMath_ReadCallback(quad_p1) == -1 ||
BaseMath_ReadCallback(quad_p2) == -1 || BaseMath_ReadCallback(quad_p2) == -1 ||
BaseMath_ReadCallback(quad_p3) == -1 || BaseMath_ReadCallback(quad_p3) == -1 ||
BaseMath_ReadCallback(quad_p4) == -1) BaseMath_ReadCallback(quad_p4) == -1)
{ {
return NULL; return NULL;
} }
@ -872,9 +872,9 @@ static PyObject *M_Geometry_distance_point_to_plane(PyObject *UNUSED(self), PyOb
return NULL; return NULL;
} }
if ( BaseMath_ReadCallback(pt) == -1 || if ( BaseMath_ReadCallback(pt) == -1 ||
BaseMath_ReadCallback(plene_co) == -1 || BaseMath_ReadCallback(plene_co) == -1 ||
BaseMath_ReadCallback(plane_no) == -1) BaseMath_ReadCallback(plane_no) == -1)
{ {
return NULL; return NULL;
} }
@ -993,10 +993,10 @@ static PyObject *M_Geometry_interpolate_bezier(PyObject *UNUSED(self), PyObject*
return NULL; return NULL;
} }
if ( BaseMath_ReadCallback(vec_k1) == -1 || if ( BaseMath_ReadCallback(vec_k1) == -1 ||
BaseMath_ReadCallback(vec_h1) == -1 || BaseMath_ReadCallback(vec_h1) == -1 ||
BaseMath_ReadCallback(vec_k2) == -1 || BaseMath_ReadCallback(vec_k2) == -1 ||
BaseMath_ReadCallback(vec_h2) == -1) BaseMath_ReadCallback(vec_h2) == -1)
{ {
return NULL; return NULL;
} }

@ -201,7 +201,7 @@ static void rand_vn(float *array_tar, const int size)
{ {
float *array_pt= array_tar + (size-1); float *array_pt= array_tar + (size-1);
int i= size; int i= size;
while(i--) { *(array_pt--) = 2.0f * frand() - 1.0f; } while (i--) { *(array_pt--) = 2.0f * frand() - 1.0f; }
} }
/* Fills an array of length 3 with noise values */ /* Fills an array of length 3 with noise values */

@ -177,7 +177,6 @@ void WM_init(bContext *C, int argc, const char **argv)
GPU_extensions_init(); GPU_extensions_init();
GPU_set_mipmap(!(U.gameflags & USER_DISABLE_MIPMAP)); GPU_set_mipmap(!(U.gameflags & USER_DISABLE_MIPMAP));
GPU_set_anisotropic(U.anisotropic_filter); GPU_set_anisotropic(U.anisotropic_filter);
GPU_code_generate_glsl_lib();
UI_init(); UI_init();
} }

@ -431,6 +431,8 @@ void RAS_2DFilterManager::RenderFilters(RAS_ICanvas* canvas)
glViewport(0,0, texturewidth, textureheight); glViewport(0,0, texturewidth, textureheight);
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
// in case the previous material was wire
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
// if the last rendered face had alpha add it would messes with the color of the plane we apply 2DFilter to // if the last rendered face had alpha add it would messes with the color of the plane we apply 2DFilter to
glDisable(GL_BLEND); glDisable(GL_BLEND);
glPushMatrix(); //GL_MODELVIEW glPushMatrix(); //GL_MODELVIEW