WIP: Brush assets project #106303
|
@ -29,7 +29,7 @@ extern "C" {
|
|||
|
||||
/* Blender file format version. */
|
||||
#define BLENDER_FILE_VERSION BLENDER_VERSION
|
||||
#define BLENDER_FILE_SUBVERSION 10
|
||||
#define BLENDER_FILE_SUBVERSION 11
|
||||
|
||||
/* Minimum Blender version that supports reading file written with the current
|
||||
* version. Older Blender versions will test this and cancel loading the file, showing a warning to
|
||||
|
|
|
@ -476,6 +476,7 @@ static void write_node_socket_interface(BlendWriter *writer, const bNodeSocket *
|
|||
static bNodeSocket *make_socket(bNodeTree *ntree,
|
||||
const eNodeSocketInOut in_out,
|
||||
const StringRef idname,
|
||||
|
||||
const StringRef name,
|
||||
const StringRef identifier)
|
||||
{
|
||||
|
@ -501,6 +502,59 @@ static bNodeSocket *make_socket(bNodeTree *ntree,
|
|||
return sock;
|
||||
}
|
||||
|
||||
/* Include the subtype suffix for old socket idnames. */
|
||||
static StringRef get_legacy_socket_subtype_idname(StringRef idname, const void *socket_data)
|
||||
{
|
||||
if (idname == "NodeSocketFloat") {
|
||||
const bNodeSocketValueFloat &float_data = *static_cast<const bNodeSocketValueFloat *>(
|
||||
socket_data);
|
||||
switch (float_data.subtype) {
|
||||
case PROP_UNSIGNED:
|
||||
return "NodeSocketFloatUnsigned";
|
||||
case PROP_PERCENTAGE:
|
||||
return "NodeSocketFloatPercentage";
|
||||
case PROP_FACTOR:
|
||||
return "NodeSocketFloatFactor";
|
||||
case PROP_ANGLE:
|
||||
return "NodeSocketFloatAngle";
|
||||
case PROP_TIME:
|
||||
return "NodeSocketFloatTime";
|
||||
case PROP_TIME_ABSOLUTE:
|
||||
return "NodeSocketFloatTimeAbsolute";
|
||||
case PROP_DISTANCE:
|
||||
return "NodeSocketFloatDistance";
|
||||
}
|
||||
}
|
||||
if (idname == "NodeSocketInt") {
|
||||
const bNodeSocketValueInt &int_data = *static_cast<const bNodeSocketValueInt *>(socket_data);
|
||||
switch (int_data.subtype) {
|
||||
case PROP_UNSIGNED:
|
||||
return "NodeSocketIntUnsigned";
|
||||
case PROP_PERCENTAGE:
|
||||
return "NodeSocketIntPercentage";
|
||||
case PROP_FACTOR:
|
||||
return "NodeSocketIntFactor";
|
||||
}
|
||||
}
|
||||
if (idname == "NodeSocketVector") {
|
||||
const bNodeSocketValueVector &vector_data = *static_cast<const bNodeSocketValueVector *>(
|
||||
socket_data);
|
||||
switch (vector_data.subtype) {
|
||||
case PROP_TRANSLATION:
|
||||
return "NodeSocketVectorTranslation";
|
||||
case PROP_DIRECTION:
|
||||
return "NodeSocketVectorDirection";
|
||||
case PROP_VELOCITY:
|
||||
return "NodeSocketVectorVelocity";
|
||||
case PROP_ACCELERATION:
|
||||
return "NodeSocketVectorAcceleration";
|
||||
case PROP_EULER:
|
||||
return "NodeSocketVectorEuler";
|
||||
}
|
||||
}
|
||||
return idname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Socket interface reconstruction for forward compatibility.
|
||||
* To enable previous Blender versions to read the new interface DNA data,
|
||||
|
@ -516,7 +570,11 @@ static void construct_interface_as_legacy_sockets(bNodeTree *ntree)
|
|||
auto make_legacy_socket = [&](const bNodeTreeInterfaceSocket &socket,
|
||||
eNodeSocketInOut in_out) -> bNodeSocket * {
|
||||
bNodeSocket *iosock = make_socket(
|
||||
ntree, in_out, socket.socket_type, socket.name ? socket.name : "", socket.identifier);
|
||||
ntree,
|
||||
in_out,
|
||||
get_legacy_socket_subtype_idname(socket.socket_type, socket.socket_data),
|
||||
socket.name ? socket.name : "",
|
||||
socket.identifier);
|
||||
if (!iosock) {
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -1386,6 +1386,36 @@ static void version_geometry_nodes_use_rotation_socket(bNodeTree &ntree)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Find the base socket name for an idname that may include a subtype. */
|
||||
static blender::StringRef legacy_socket_idname_to_socket_type(blender::StringRef idname)
|
||||
{
|
||||
using string_pair = std::pair<const char *, const char *>;
|
||||
static const string_pair subtypes_map[] = {{"NodeSocketFloatUnsigned", "NodeSocketFloat"},
|
||||
{"NodeSocketFloatPercentage", "NodeSocketFloat"},
|
||||
{"NodeSocketFloatFactor", "NodeSocketFloat"},
|
||||
{"NodeSocketFloatAngle", "NodeSocketFloat"},
|
||||
{"NodeSocketFloatTime", "NodeSocketFloat"},
|
||||
{"NodeSocketFloatTimeAbsolute", "NodeSocketFloat"},
|
||||
{"NodeSocketFloatDistance", "NodeSocketFloat"},
|
||||
{"NodeSocketIntUnsigned", "NodeSocketInt"},
|
||||
{"NodeSocketIntPercentage", "NodeSocketInt"},
|
||||
{"NodeSocketIntFactor", "NodeSocketInt"},
|
||||
{"NodeSocketVectorTranslation", "NodeSocketVector"},
|
||||
{"NodeSocketVectorDirection", "NodeSocketVector"},
|
||||
{"NodeSocketVectorVelocity", "NodeSocketVector"},
|
||||
{"NodeSocketVectorAcceleration", "NodeSocketVector"},
|
||||
{"NodeSocketVectorEuler", "NodeSocketVector"},
|
||||
{"NodeSocketVectorXYZ", "NodeSocketVector"}};
|
||||
for (const string_pair &pair : subtypes_map) {
|
||||
if (pair.first == idname) {
|
||||
return pair.second;
|
||||
}
|
||||
}
|
||||
/* Unchanged socket idname. */
|
||||
return idname;
|
||||
}
|
||||
|
||||
static bNodeTreeInterfaceItem *legacy_socket_move_to_interface(bNodeSocket &legacy_socket,
|
||||
const eNodeSocketInOut in_out)
|
||||
{
|
||||
|
@ -1396,7 +1426,10 @@ static bNodeTreeInterfaceItem *legacy_socket_move_to_interface(bNodeSocket &lega
|
|||
new_socket->name = BLI_strdup(legacy_socket.name);
|
||||
new_socket->identifier = BLI_strdup(legacy_socket.identifier);
|
||||
new_socket->description = BLI_strdup(legacy_socket.description);
|
||||
new_socket->socket_type = BLI_strdup(legacy_socket.idname);
|
||||
/* If the socket idname includes a subtype (e.g. "NodeSocketFloatFactor") this will convert it to
|
||||
* the base type name ("NodeSocketFloat"). */
|
||||
new_socket->socket_type = BLI_strdup(
|
||||
legacy_socket_idname_to_socket_type(legacy_socket.idname).data());
|
||||
new_socket->flag = (in_out == SOCK_IN ? NODE_INTERFACE_SOCKET_INPUT :
|
||||
NODE_INTERFACE_SOCKET_OUTPUT);
|
||||
SET_FLAG_FROM_TEST(
|
||||
|
@ -1444,6 +1477,28 @@ static void versioning_convert_node_tree_socket_lists_to_interface(bNodeTree *nt
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Original node tree interface conversion in did not convert socket idnames with subtype suffixes
|
||||
* to correct socket base types (see #versioning_convert_node_tree_socket_lists_to_interface).
|
||||
*/
|
||||
static void versioning_fix_socket_subtype_idnames(bNodeTree *ntree)
|
||||
{
|
||||
bNodeTreeInterface &tree_interface = ntree->tree_interface;
|
||||
|
||||
tree_interface.foreach_item([](bNodeTreeInterfaceItem &item) -> bool {
|
||||
if (item.item_type == NODE_INTERFACE_SOCKET) {
|
||||
bNodeTreeInterfaceSocket &socket = reinterpret_cast<bNodeTreeInterfaceSocket &>(item);
|
||||
blender::StringRef corrected_socket_type = legacy_socket_idname_to_socket_type(
|
||||
socket.socket_type);
|
||||
if (socket.socket_type != corrected_socket_type) {
|
||||
MEM_freeN(socket.socket_type);
|
||||
socket.socket_type = BLI_strdup(corrected_socket_type.data());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
/* Convert coat inputs on the Principled BSDF. */
|
||||
static void version_principled_bsdf_coat(bNodeTree *ntree)
|
||||
{
|
||||
|
@ -2577,6 +2632,14 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
|
|||
}
|
||||
}
|
||||
|
||||
if (MAIN_VERSION_FILE_ATLEAST(bmain, 400, 20) && !MAIN_VERSION_FILE_ATLEAST(bmain, 401, 11)) {
|
||||
/* Convert old socket lists into new interface items. */
|
||||
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
|
||||
versioning_fix_socket_subtype_idnames(ntree);
|
||||
}
|
||||
FOREACH_NODETREE_END;
|
||||
}
|
||||
|
||||
/**
|
||||
* Always bump subversion in BKE_blender_version.h when adding versioning
|
||||
* code here, and wrap it inside a MAIN_VERSION_FILE_ATLEAST check.
|
||||
|
|
|
@ -14,7 +14,25 @@ import bpy
|
|||
args = None
|
||||
|
||||
|
||||
type_info = {
|
||||
base_idname = {
|
||||
"VALUE": "NodeSocketFloat",
|
||||
"INT": "NodeSocketInt",
|
||||
"BOOLEAN": "NodeSocketBool",
|
||||
"ROTATION": "NodeSocketRotation",
|
||||
"VECTOR": "NodeSocketVector",
|
||||
"RGBA": "NodeSocketColor",
|
||||
"STRING": "NodeSocketString",
|
||||
"SHADER": "NodeSocketShader",
|
||||
"OBJECT": "NodeSocketObject",
|
||||
"IMAGE": "NodeSocketImage",
|
||||
"GEOMETRY": "NodeSocketGeometry",
|
||||
"COLLECTION": "NodeSocketCollection",
|
||||
"TEXTURE": "NodeSocketTexture",
|
||||
"MATERIAL": "NodeSocketMaterial",
|
||||
}
|
||||
|
||||
|
||||
subtype_idname = {
|
||||
("VALUE", "NONE"): "NodeSocketFloat",
|
||||
("VALUE", "UNSIGNED"): "NodeSocketFloatUnsigned",
|
||||
("VALUE", "PERCENTAGE"): "NodeSocketFloatPercentage",
|
||||
|
@ -63,8 +81,12 @@ class SocketSpec():
|
|||
external_links: int = 1
|
||||
|
||||
@property
|
||||
def idname(self):
|
||||
return type_info[(self.type, self.subtype)]
|
||||
def base_idname(self):
|
||||
return base_idname[self.type]
|
||||
|
||||
@property
|
||||
def subtype_idname(self):
|
||||
return subtype_idname[(self.type, self.subtype)]
|
||||
|
||||
|
||||
class AbstractNodeGroupInterfaceTest(unittest.TestCase):
|
||||
|
@ -95,7 +117,7 @@ class AbstractNodeGroupInterfaceTest(unittest.TestCase):
|
|||
|
||||
# Examine the interface item.
|
||||
self.assertEqual(item.name, spec.name)
|
||||
self.assertEqual(item.bl_socket_idname, spec.idname)
|
||||
self.assertEqual(item.bl_socket_idname, spec.base_idname)
|
||||
self.assertEqual(item.identifier, spec.identifier)
|
||||
|
||||
# Types that have subtypes.
|
||||
|
@ -134,7 +156,7 @@ class AbstractNodeGroupInterfaceTest(unittest.TestCase):
|
|||
socket = next(s for s in node.inputs if s.identifier == spec.identifier)
|
||||
self.assertIsNotNone(socket, f"Could not find socket for group input identifier {spec.identifier}")
|
||||
self.assertEqual(socket.name, spec.name)
|
||||
self.assertEqual(socket.bl_idname, spec.idname)
|
||||
self.assertEqual(socket.bl_idname, spec.subtype_idname)
|
||||
self.assertEqual(socket.type, spec.type)
|
||||
self.assertEqual(socket.hide_value, spec.hide_value)
|
||||
if test_links:
|
||||
|
@ -147,7 +169,7 @@ class AbstractNodeGroupInterfaceTest(unittest.TestCase):
|
|||
self.assertIsNotNone(
|
||||
socket, f"Could not find group input socket for group input identifier {spec.identifier}")
|
||||
self.assertEqual(socket.name, spec.name)
|
||||
self.assertEqual(socket.bl_idname, spec.idname)
|
||||
self.assertEqual(socket.bl_idname, spec.subtype_idname)
|
||||
self.assertEqual(socket.type, spec.type)
|
||||
self.assertEqual(socket.hide_value, spec.hide_value)
|
||||
if test_links:
|
||||
|
@ -158,7 +180,7 @@ class AbstractNodeGroupInterfaceTest(unittest.TestCase):
|
|||
socket = next(s for s in node.outputs if s.identifier == spec.identifier)
|
||||
self.assertIsNotNone(socket, f"Could not find socket for group output identifier {spec.identifier}")
|
||||
self.assertEqual(socket.name, spec.name)
|
||||
self.assertEqual(socket.bl_idname, spec.idname)
|
||||
self.assertEqual(socket.bl_idname, spec.subtype_idname)
|
||||
self.assertEqual(socket.type, spec.type)
|
||||
self.assertEqual(socket.hide_value, spec.hide_value)
|
||||
if test_links:
|
||||
|
@ -171,7 +193,7 @@ class AbstractNodeGroupInterfaceTest(unittest.TestCase):
|
|||
self.assertIsNotNone(
|
||||
socket, f"Could not find group output socket for group output identifier {spec.identifier}")
|
||||
self.assertEqual(socket.name, spec.name)
|
||||
self.assertEqual(socket.bl_idname, spec.idname)
|
||||
self.assertEqual(socket.bl_idname, spec.subtype_idname)
|
||||
self.assertEqual(socket.type, spec.type)
|
||||
self.assertEqual(socket.hide_value, spec.hide_value)
|
||||
if test_links:
|
||||
|
|
Loading…
Reference in New Issue