Skip to content

Commit de2ee0a

Browse files
committed
Initial work for blender integration
1 parent 22b570e commit de2ee0a

File tree

3 files changed

+146
-1
lines changed

3 files changed

+146
-1
lines changed

src/pyrightconfig.json

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"pythonVersion": "3.10",
33
"pythonPlatform": "Windows",
44
"extraPaths": [
5-
"C:/Users/Shea.Richardson/Desktop/Git/SkinPlusPlus/.dev/venv/310/.venv/Lib/site-packages"
5+
"D:/Code/Git/SkinPlusPlus-latest/.dev/venvs/py310/.venv/Lib/site-packages"
66
],
77
"reportDuplicateImport": "warning",
88
"reportImplicitStringConcatenation": "warning",
@@ -15,4 +15,14 @@
1515
"reportUnusedFunction": "information",
1616
"reportUnusedImport": "information",
1717
"reportUnusedVariable": "information",
18+
"reportMissingModuleSource": "none",
19+
"executionEnvironments": [
20+
{
21+
"root": "D:/Code/Git/SkinPlusPlus-latest/src/skin_plus_plus/dccs/blender",
22+
"extraPaths": [
23+
"C:/Program Files/Blender Foundation/Blender 4.2/4.2/scripts/modules",
24+
"D:/Code/Git/SkinPlusPlus-latest/.dev/venvs/py311/.venv/Lib/site-packages"
25+
]
26+
}
27+
]
1828
}

src/skin_plus_plus/dccs/blender/__init__.py

Whitespace-only changes.
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
from __future__ import annotations
2+
3+
import pathlib
4+
5+
import bpy
6+
import bpy.types as bpy_types
7+
from typing_extensions import override
8+
9+
from .. import core
10+
11+
_typing = False
12+
if _typing:
13+
from collections.abc import Sequence
14+
15+
from ... import _types
16+
del _typing
17+
18+
19+
class IHost(core.IHost[bpy_types.Object]):
20+
@property
21+
@override
22+
def name(self) -> str:
23+
return "blender"
24+
25+
@property
26+
@override
27+
def api_name(self) -> str:
28+
return "bpy"
29+
30+
@override
31+
def _get_version_number(self):
32+
version_info = mxrt.MaxVersion()
33+
version_number = version_info[7]
34+
return version_number
35+
36+
@override
37+
def get_current_file_path(self) -> pathlib.Path:
38+
max_file_path = mxrt.MaxFilePath
39+
if not max_file_path:
40+
raise RuntimeError("File is not saved!")
41+
42+
return pathlib.Path(max_file_path, mxrt.MaxFileName)
43+
44+
@override
45+
def get_selection(self) -> tuple[bpy_types.Object, ...]:
46+
return tuple(mxrt.Selection)
47+
48+
@override
49+
def get_node_name(self, node: bpy_types.Object) -> str:
50+
return node.name
51+
52+
@override
53+
def get_vertex_positions(self, node: bpy_types.Object) -> _types.T_Float64Array:
54+
return self._get_vertex_positions(node.Name)
55+
56+
@override
57+
def get_node_handle(self, node: bpy_types.Object) -> int:
58+
return node.Handle
59+
60+
@override
61+
def extract_skin_data(
62+
self, node: bpy_types.Object, vertex_ids: Sequence[int] | None = None
63+
) -> core.SkinData:
64+
armature = self._get_armature(node)
65+
if armature is None:
66+
raise RuntimeError(f"No armature found for node: {node}")
67+
68+
vertices = node.data.vertices
69+
vertex_group_names = [vertex_group.name for vertex_group in node.vertex_groups]
70+
for bone in armature.pose.bones:
71+
if bone.name not in vertex_group_names:
72+
continue
73+
74+
bone_index = node.vertex_groups[bone.name].index
75+
bone_vertices = (
76+
vertex
77+
for vertex in vertices
78+
if bone_index in {group.group for group in vertex.groups}
79+
)
80+
81+
for bone_vertex in bone_vertices:
82+
weight = bone_vertex.groups[bone_index].weight
83+
print(f"Vertex: {bone_vertex.index} weight: {weight} bone: {bone.name}")
84+
85+
def _get_armature(self, node: bpy_types.Object) -> bpy_types.Object | None:
86+
parent = node.parent
87+
while parent:
88+
if parent.type == "ARMATURE":
89+
return parent
90+
91+
92+
93+
94+
95+
96+
def _get_armature(node: bpy_types.Object) -> bpy_types.Object | None:
97+
parent = node.parent
98+
while parent:
99+
if parent.type == "ARMATURE":
100+
return parent
101+
102+
def extract_skin_data(
103+
node: bpy_types.Object, vertex_ids: Sequence[int] | None = None
104+
):
105+
armature = _get_armature(node)
106+
if armature is None:
107+
raise RuntimeError(f"No armature found for node: {node}")
108+
109+
vertices = node.data.vertices
110+
skin_data = [[0.0, 0.0]] * len(vertices)
111+
vertex_group_names = [vertex_group.name for vertex_group in node.vertex_groups]
112+
for bone in armature.pose.bones:
113+
if (bone_name := bone.name) not in vertex_group_names:
114+
continue
115+
116+
# bone_index = node.vertex_groups[bone_name].index
117+
# bone_vertices = (
118+
# vertex
119+
# for vertex in vertices
120+
# if bone_index in {group.group for group in vertex.groups}
121+
# )
122+
for vertex in vertices:
123+
for influence in vertex.groups:
124+
skin_data[vertex.index][influence.group] = influence.weight
125+
126+
# for bone_vertex in bone_vertices:
127+
# weight = bone_vertex.groups[bone_index].weight
128+
# # print(f"Vertex: {bone_vertex.index} weight: {weight} bone: {bone.name}")
129+
# skin_data[bone_vertex.index][bone_index] = weight
130+
# print(f"[{bone_vertex.index}][{bone_index}] = {weight}")
131+
132+
for weights in skin_data:
133+
print(weights)
134+
135+

0 commit comments

Comments
 (0)