Skip to content

Commit

Permalink
Support Integer 2D custom attributes (#1931)
Browse files Browse the repository at this point in the history
  • Loading branch information
3DSinghVFX authored Dec 23, 2023
1 parent eddb643 commit cb870cf
Show file tree
Hide file tree
Showing 16 changed files with 155 additions and 11 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
- Added Container Type advanced option to object instancer node.
- Added Evaluate FCurves Transforms node.
- Added *Lamp Input* and *Lamp Output* nodes.
- Added *Int2* list and socket type.

### Fixed

Expand All @@ -32,6 +33,7 @@
- Fixed *Set Bevel Vertex Weight* and *Set Bevel Edge Weight* nodes for API changes.
- Fixed *Set Keyframe* node failing when path contains a subscript.
- Fixed symbol not found error on MacOS 10.
- Fixed Custom Attributes for new API changes.

### Changed

Expand Down
4 changes: 2 additions & 2 deletions animation_nodes/data_structures/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ def importDataStructures():
from . lists.base_lists import (
Vector3DList, Vector2DList, Matrix4x4List, EdgeIndicesList, EulerList, ColorList,
BooleanList, FloatList, DoubleList, LongList, IntegerList, UShortList, CharList,
QuaternionList, UIntegerList, ShortList, UShortList
QuaternionList, UIntegerList, ShortList, UShortList, Int2List
)

from . virtual_list.virtual_list import VirtualList, VirtualPyList
from . virtual_list.virtual_clists import (
VirtualVector3DList, VirtualMatrix4x4List, VirtualEulerList, VirtualBooleanList,
VirtualFloatList, VirtualDoubleList, VirtualLongList, VirtualColorList,
VirtualVector2DList, VirtualQuaternionList
VirtualVector2DList, VirtualQuaternionList, VirtualInt2List
)

from . splines.base_spline import Spline
Expand Down
1 change: 1 addition & 0 deletions animation_nodes/data_structures/attributes/attribute.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ cpdef enum AttributeDomain:

cpdef enum AttributeDataType:
INT,
INT32_2D,
FLOAT,
FLOAT2,
FLOAT_VECTOR,
Expand Down
3 changes: 3 additions & 0 deletions animation_nodes/data_structures/attributes/attribute.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ from .. lists.base_lists cimport (
BooleanList,
Vector2DList,
Vector3DList,
Int2List,
)

cListFromDataType = {
INT: LongList,
INT32_2D: Int2List,
FLOAT: FloatList,
FLOAT2: Vector2DList,
FLOAT_VECTOR: Vector3DList,
Expand Down Expand Up @@ -38,6 +40,7 @@ stringFromDomain = {

stringFromDataType = {
INT: "INT",
INT32_2D: "INT32_2D",
FLOAT: "FLOAT",
FLOAT2: "FLOAT2",
FLOAT_VECTOR: "FLOAT_VECTOR",
Expand Down
12 changes: 12 additions & 0 deletions animation_nodes/data_structures/lists/special_list_types.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,5 +91,17 @@
"from ... math.color cimport Color",
"from ... math.conversion cimport setColor, toPyColor, toColor"
]
},
"Int2List" : {
"Type" : "Int2",
"Buffer Type" : "int",
"Equals" : "not memcmp(&(\\1), &(\\2), sizeof(Int2))",
"Try Conversion" : "setInt2(target, value)",
"To PyObject" : "toPyInt2(value)",
"Additional Methods" : "",
"Declarations" : [
"from ... math.vector cimport Int2",
"from ... math.conversion cimport setInt2, toPyInt2"
]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
"Import" : "from ... math.vector cimport Vector2",
"Return" : "Pointer"
},
"Int2List" : {
"Type" : "Int2",
"Import" : "from ... math.vector cimport Int2",
"Return" : "Pointer"
},
"Matrix4x4List" : {
"Type" : "Matrix4",
"Import" : "from ... math.matrix cimport Matrix4",
Expand Down
6 changes: 4 additions & 2 deletions animation_nodes/extend_bpy_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from . utils.depsgraph import getActiveDepsgraph
from . data_structures import (Vector3DList, EdgeIndicesList, PolygonIndicesList,
FloatList, UShortList, UIntegerList, Vector2DList,
ColorList, DoubleList, LongList, BooleanList)
ColorList, DoubleList, LongList, BooleanList, Int2List)

def register():
bpy.types.Context.getActiveAnimationNodeTree = getActiveAnimationNodeTree
Expand Down Expand Up @@ -125,6 +125,8 @@ def getCustomAttribute(self, name):
data = DoubleList(length = amount)
elif attribute.data_type == "INT":
data = LongList(length = amount)
elif attribute.data_type == "INT32_2D":
data = Int2List(length = amount)
elif attribute.data_type == "FLOAT2":
data = Vector2DList(length = amount)
elif attribute.data_type == "FLOAT_VECTOR":
Expand All @@ -134,7 +136,7 @@ def getCustomAttribute(self, name):
else:
data = BooleanList(length = amount)

if attribute.data_type in ("FLOAT", "INT", "BOOLEAN"):
if attribute.data_type in ("FLOAT", "INT", "INT32_2D", "BOOLEAN"):
attribute.data.foreach_get("value", data.asNumpyArray())
elif attribute.data_type in ("FLOAT2", "FLOAT_VECTOR"):
attribute.data.foreach_get("vector", data.asNumpyArray())
Expand Down
6 changes: 5 additions & 1 deletion animation_nodes/math/conversion.pxd
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from . color cimport Color
from . euler cimport Euler3
from . quaternion cimport Quaternion
from . vector cimport Vector2, Vector3, Vector4
from . vector cimport Vector2, Vector3, Vector4, Int2
from . matrix cimport Matrix3, Matrix4, Matrix3_or_Matrix4

cdef Matrix4 toMatrix4(value) except *
Expand All @@ -22,6 +22,10 @@ cdef Vector4 toVector4(value) except *
cdef setVector4(Vector4* v, value)
cdef toPyVector4(Vector4* v)

cdef Int2 toInt2(value) except *
cdef setInt2(Int2* v, value)
cdef toPyInt2(Int2* v)

cdef Euler3 toEuler3(value) except *
cdef setEuler3(Euler3* e, value)
cdef toPyEuler3(Euler3* e)
Expand Down
14 changes: 14 additions & 0 deletions animation_nodes/math/conversion.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,20 @@ cdef setVector4(Vector4* v, value):
cdef toPyVector4(Vector4* v):
return Vector((v.x, v.y, v.z, v.w))

cdef Int2 toInt2(value) except *:
cdef Int2 v
setInt2(&v, value)
return v

cdef setInt2(Int2* v, value):
if len(value) != 2:
raise TypeError("element is not a 2D integer vector")
v.x = value[0]
v.y = value[1]

cdef toPyInt2(Int2* v):
return (v.x, v.y)


# Matrices
##########################################################
Expand Down
3 changes: 3 additions & 0 deletions animation_nodes/math/vector.pxd
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
cdef struct Int2:
int x, y

cdef struct Vector2:
float x, y

Expand Down
22 changes: 21 additions & 1 deletion animation_nodes/nodes/mesh/c_utils.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ from ... data_structures cimport (
Mesh,
VirtualLongList,
VirtualDoubleList,
EdgeIndices
EdgeIndices,
Int2List
)

from ... math cimport (
Expand Down Expand Up @@ -707,3 +708,22 @@ def getReplicatedLoopEdges(UIntegerList loopEdges, Py_ssize_t amount, Py_ssize_t
_newLoopEdges[index] = _loopEdges[j] + offset
index += 1
return newLoopEdges

# Conversion
###################################

def convert_EdgeIndicesList_to_Int2List(EdgeIndicesList values):
cdef Py_ssize_t i
cdef Int2List int2D = Int2List(length = len(values))
for i in range(len(values)):
int2D.data[i].x = <int>values.data[i].v1
int2D.data[i].y = <int>values.data[i].v2
return int2D

def convert_Int2List_to_EdgeIndicesList(Int2List values):
cdef Py_ssize_t i
cdef EdgeIndicesList edges = EdgeIndicesList(length = len(values))
for i in range(len(values)):
edges.data[i].v1 = <unsigned int>values.data[i].x
edges.data[i].v2 = <unsigned int>values.data[i].y
return edges
5 changes: 4 additions & 1 deletion animation_nodes/nodes/mesh/get_custom_attribute.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
("FLOAT_COLOR", "Color", "", "NONE", 4),
("BYTE_COLOR", "Byte Color", "", "NONE", 5),
("BOOLEAN", "Boolean", "", "NONE", 6),
("INT32_2D", "Integer 2D", "", "NONE", 7),
]

class GetCustomAttributeNode(AnimationNode, bpy.types.Node):
Expand All @@ -35,8 +36,10 @@ def create(self):
self.newOutput("Vector List", "Vectors", "data")
elif self.dataType in ("FLOAT_COLOR", "BYTE_COLOR"):
self.newOutput("Color List", "Colors", "data")
else:
elif self.dataType == "BOOLEAN":
self.newOutput("Boolean List", "Values", "data")
else:
self.newOutput("Integer 2D List", "Values", "data")
self.newOutput("Text", "Type", "type", hide = True)
self.newOutput("Text", "Domain ", "domain", hide = True)
self.newOutput("Text", "Data Type ", "dataType", hide = True)
Expand Down
10 changes: 9 additions & 1 deletion animation_nodes/nodes/mesh/insert_custom_attribute.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
Attribute,
AttributeType,
AttributeDomain,
VirtualInt2List,
VirtualLongList,
VirtualColorList,
AttributeDataType,
Expand All @@ -32,6 +33,7 @@
("FLOAT_COLOR", "Color", "", "NONE", 4),
("BYTE_COLOR", "Byte Color", "", "NONE", 5),
("BOOLEAN", "Boolean", "", "NONE", 6),
("INT32_2D", "Integer 2D", "", "NONE", 7),
]

class InsertCustomAttributeNode(AnimationNode, bpy.types.Node):
Expand Down Expand Up @@ -65,9 +67,13 @@ def create(self):
elif self.dataType in ("FLOAT_COLOR", "BYTE_COLOR"):
self.newInput(VectorizedSocket("Color", "useDataList",
("Color", "data"), ("Colors", "data")))
else:
elif self.dataType == "BOOLEAN":
self.newInput(VectorizedSocket("Boolean", "useDataList",
("Value", "data"), ("Values", "data")))
else:
self.newInput(VectorizedSocket("Integer 2D", "useDataList",
("Value", "data"), ("Values", "data")))


self.newOutput("Mesh", "Mesh", "mesh")

Expand All @@ -89,6 +95,8 @@ def execute(self, mesh, customAttributeName, data):

if self.dataType == "INT":
_data = VirtualLongList.create(data, 0).materialize(amount)
elif self.dataType == "INT32_2D":
_data = VirtualInt2List.create(data, (0, 0)).materialize(amount)
elif self.dataType == "FLOAT":
_data = FloatList.fromValues(VirtualDoubleList.create(data, 0).materialize(amount))
elif self.dataType == "FLOAT2":
Expand Down
2 changes: 1 addition & 1 deletion animation_nodes/nodes/mesh/mesh_object_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ def setMesh(self, outMesh, mesh, object):

attributeOut = outMesh.attributes.new(attribute.name, dataType, domain)

if dataType in ("FLOAT", "INT", "BOOLEAN"):
if dataType in ("FLOAT", "INT", "INT32_2D", "BOOLEAN"):
attributeOut.data.foreach_set("value", data.asMemoryView())
elif dataType in ("FLOAT2", "FLOAT_VECTOR"):
attributeOut.data.foreach_set("vector", data.asMemoryView())
Expand Down
11 changes: 9 additions & 2 deletions animation_nodes/nodes/mesh/set_custom_attribute.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from ... data_structures import (
Color,
FloatList,
VirtualInt2List,
VirtualLongList,
VirtualColorList,
VirtualDoubleList,
Expand All @@ -28,6 +29,7 @@
("FLOAT_COLOR", "Color", "", "NONE", 4),
("BYTE_COLOR", "Byte Color", "", "NONE", 5),
("BOOLEAN", "Boolean", "", "NONE", 6),
("INT32_2D", "Integer 2D", "", "NONE", 7),
]

class SetCustomAttributeNode(AnimationNode, bpy.types.Node):
Expand Down Expand Up @@ -61,9 +63,12 @@ def create(self):
elif self.dataType in ("FLOAT_COLOR", "BYTE_COLOR"):
self.newInput(VectorizedSocket("Color", "useDataList",
("Color", "data"), ("Colors", "data")))
else:
elif self.dataType == "BOOLEAN":
self.newInput(VectorizedSocket("Boolean", "useDataList",
("Value", "data"), ("Values", "data")))
else:
self.newInput(VectorizedSocket("Integer 2D", "useDataList",
("Value", "data"), ("Values", "data")))

self.newOutput("Object", "Object", "object")

Expand Down Expand Up @@ -94,6 +99,8 @@ def execute(self, object, customAttributeName, data):

if self.dataType == "INT":
_data = VirtualLongList.create(data, 0).materialize(amount)
elif self.dataType == "INT32_2D":
_data = VirtualInt2List.create(data, (0, 0)).materialize(amount)
elif self.dataType == "FLOAT":
_data = FloatList.fromValues(VirtualDoubleList.create(data, 0).materialize(amount))
elif attribute.data_type == "FLOAT2":
Expand All @@ -105,7 +112,7 @@ def execute(self, object, customAttributeName, data):
else:
_data = VirtualBooleanList.create(data, False).materialize(amount)

if self.dataType in ("FLOAT", "INT", "BOOLEAN"):
if self.dataType in ("FLOAT", "INT", "INT32_2D", "BOOLEAN"):
attribute.data.foreach_set("value", _data.asMemoryView())
elif self.dataType in ("FLOAT2", "FLOAT_VECTOR"):
attribute.data.foreach_set("vector", _data.asMemoryView())
Expand Down
60 changes: 60 additions & 0 deletions animation_nodes/sockets/integer2d.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import bpy
from bpy.props import *
from .. events import propertyChanged
from .. data_structures import Int2List
from .. base_types import AnimationNodeSocket, CListSocket
from . implicit_conversion import registerImplicitConversion


class Integer2DSocket(bpy.types.NodeSocket, AnimationNodeSocket):
bl_idname = "an_Integer2DSocket"
bl_label = "Integer 2D Socket"
dataType = "Integer 2D"
drawColor = (0.35, 0.7, 1.0, 1)
comparable = True
storable = True

value: IntVectorProperty(default = [0, 0], size = 2, update = propertyChanged, subtype = "XYZ")

def drawProperty(self, layout, text, node):
col = layout.column(align = True)
if text != "": col.label(text = text)
col.prop(self, "value", index = 0, text = "X")
col.prop(self, "value", index = 1, text = "Y")

def getValue(self):
return tuple(self.value)

def setProperty(self, data):
self.value = data

@classmethod
def getDefaultValue(cls):
return (0, 0)

@classmethod
def getDefaultValueCode(cls):
return "(0, 0)"

@classmethod
def correctValue(cls, value):
if isinstance(value, tuple) and len(value) == 2: return value, 0
elif isinstance(value, (list, set)) and len(value) == 2: return tuple(value), 1
else: return cls.getDefaultValue(), 2

registerImplicitConversion("Edge Indices", "Integer 2D", "value")
registerImplicitConversion("Integer 2D", "Edge Indices", "value")

class Integer2DListSocket(bpy.types.NodeSocket, CListSocket):
bl_idname = "an_Integer2DListSocket"
bl_label = "Integer 2D List Socket"
dataType = "Integer 2D List"
baseType = Integer2DSocket
drawColor = (0.35, 0.7, 1.0, 0.5)
storable = True
comparable = False
listClass = Int2List

from .. nodes.mesh.c_utils import convert_EdgeIndicesList_to_Int2List, convert_Int2List_to_EdgeIndicesList
registerImplicitConversion("Edge Indices List", "Integer 2D List", convert_EdgeIndicesList_to_Int2List)
registerImplicitConversion("Integer 2D List", "Edge Indices List", convert_Int2List_to_EdgeIndicesList)

0 comments on commit cb870cf

Please sign in to comment.