Skip to content

Commit 3c024b9

Browse files
committed
Initial commit for converting to blender plugin
1 parent 5d2e07f commit 3c024b9

164 files changed

Lines changed: 744 additions & 238 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

__init__.py

Lines changed: 0 additions & 123 deletions
This file was deleted.

build_cmf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
blender --command extension build --source-dir "C:\Users\msval\Documents\GitHub\NMSDK\addons\NMSDK\src\addon\nmsdk"

pyproject.toml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
[project]
2+
name = "NMSDK"
3+
description = "Blender plugin to import and export NMS scenes"
4+
readme = "README.md"
5+
requires-python = ">=3.11"
6+
keywords = ["modelling", "games", "modding"]
7+
authors = [
8+
{name = "monkeyman192"}
9+
]
10+
maintainers = [
11+
{name = "monkeyman192"}
12+
]
13+
dependencies = [
14+
"fake-bpy-module",
15+
"hgpaktool"
16+
]
17+
dynamic = ["version"]
18+
19+
[tool.uv]
20+
python-preference = "only-system"
21+
22+
[tool.setuptools.package-dir]
23+
NMSDK = "src/addon/nmsdk"
24+
25+
[tool.setuptools_scm]
26+
local_scheme = "no-local-version"
27+
28+
[tool.ruff]
29+
line-length = 110
30+
31+
[tool.ruff.lint]
32+
select = ["E", "F", "I"]
33+
preview = true
34+
35+
[tool.ruff.lint.pydocstyle]
36+
convention = "numpy"
37+
38+
[tool.ruff.lint.extend-per-file-ignores]
39+
"cpptypes.py" = ["E501"]
40+
41+
[project.urls]
42+
homepage = "https://github.com/monkeyman192/NMSDK"
43+
repository = "https://github.com/monkeyman192/NMSDK.git"
44+
45+
[build-system]
46+
requires = ["setuptools>=64", "wheel", "setuptools-scm>=8", "setuptools_scm_git_semver"]
47+
build-backend = "setuptools.build_meta"

BlenderExtensions/ContextMenu.py renamed to src/addon/nmsdk/BlenderExtensions/ContextMenu.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
import math
66

77
# Local imports
8-
from utils.misc import get_root_node, clone_node
9-
from ModelExporter.utils import get_children
8+
from ..utils.misc import get_root_node, clone_node
9+
from ..ModelExporter.utils import get_children
1010

1111
# Blender imports
1212
import bmesh
File renamed without changes.
File renamed without changes.

BlenderExtensions/NMSObjectsPanels.py renamed to src/addon/nmsdk/BlenderExtensions/NMSObjectsPanels.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from bpy.props import (StringProperty, BoolProperty, EnumProperty,
66
FloatProperty, IntVectorProperty, FloatVectorProperty,
77
IntProperty)
8-
from utils.misc import getParentRefScene
8+
from ..utils.misc import getParentRefScene
99

1010
""" Various properties for each of the different node types """
1111

File renamed without changes.
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
import bpy
2+
from bpy.props import StringProperty, IntProperty, CollectionProperty, BoolProperty
3+
from bpy.types import PropertyGroup, UIList, Operator, Panel
4+
5+
class ListItem(PropertyGroup):
6+
"""Group of properties representing an item in the list."""
7+
name: StringProperty( name="Name", description="A name for this item", default="Untitled")
8+
random_prop: StringProperty( name="Any other property you want", description="", default="")
9+
10+
11+
class MY_UL_List(UIList):
12+
"""Demo UIList."""
13+
# Filter by the value of random_prop
14+
filter_by_random_prop: StringProperty(default='')
15+
# Invert the random property filter
16+
invert_filter_by_random: BoolProperty(default=False)
17+
# Order by random prop
18+
order_by_random_prop: BoolProperty(default=False)
19+
20+
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
21+
# We could write some code to decide which icon to use here...
22+
custom_icon = 'OBJECT_DATAMODE'
23+
# Make sure your code supports all 3 layout types
24+
if self.layout_type in {'DEFAULT', 'COMPACT'}:
25+
layout.label(text=item.name, icon = custom_icon)
26+
elif self.layout_type in {'GRID'}:
27+
layout.alignment = 'CENTER'
28+
layout.label(text='', icon = custom_icon)
29+
30+
def draw_filter(self, context, layout):
31+
"""UI code for the filtering/sorting/search area."""
32+
layout.separator()
33+
col = layout.column(align=True)
34+
row = col.row(align=True)
35+
row.prop(self, 'filter_by_random_prop', text='', icon='VIEWZOOM')
36+
row.prop(self, 'invert_filter_by_random', text='', icon='ARROW_LEFTRIGHT')
37+
38+
def filter_items(self, context, data, propname):
39+
"""Filter and order items in the list."""
40+
# We initialize filtered and ordered as empty lists. Notice that
41+
# if all sorting and filtering is disabled, we will return
42+
# these empty.
43+
filtered = []
44+
ordered = []
45+
items = getattr(data, propname)
46+
# Filter
47+
if self.filter_by_random_prop:
48+
# Initialize with all items visible
49+
filtered = [self.bitflag_filter_item] * len(items)
50+
for i, item in enumerate(items):
51+
if item.random_prop != self.filter_by_random_prop:
52+
filtered[i] &= ~self.bitflag_filter_item
53+
# Invert the filter
54+
if filtered and self.invert_filter_by_random:
55+
show_flag = self.bitflag_filter_item & ~self.bitflag_filter_item
56+
for i, bitflag in enumerate(filtered):
57+
if bitflag == show_flag:
58+
filtered[i] = self.bitflag_filter_item
59+
else:
60+
filtered[i] &= ~self.bitflag_filter_item
61+
# Order by the length of random_prop
62+
if self.order_by_random_prop:
63+
sort_items = bpy.types.UI_UL_list.helper_funcs.sort_items_helper
64+
ordered = sort_items(items, lambda i: len(i.random_prop), True)
65+
return filtered, ordered
66+
67+
class LIST_OT_NewItem(Operator):
68+
"""Add a new item to the list."""
69+
bl_idname = "my_list.new_item"
70+
bl_label = "Add a new item"
71+
72+
def execute(self, context):
73+
context.scene.my_list.add()
74+
return{'FINISHED'}
75+
76+
77+
class LIST_OT_DeleteItem(Operator):
78+
"""Delete the selected item from the list."""
79+
bl_idname = "my_list.delete_item"
80+
bl_label = "Deletes an item"
81+
82+
@classmethod
83+
def poll(cls, context):
84+
return context.scene.my_list
85+
86+
def execute(self, context):
87+
my_list = context.scene.my_list
88+
index = context.scene.list_index
89+
my_list.remove(index)
90+
context.scene.list_index = min(max(0, index - 1), len(my_list) - 1)
91+
return{'FINISHED'}
92+
93+
class LIST_OT_MoveItem(Operator):
94+
"""Move an item in the list."""
95+
bl_idname = "my_list.move_item"
96+
bl_label = "Move an item in the list"
97+
direction: bpy.props.EnumProperty(
98+
items=(('UP', 'Up', ""), ('DOWN', 'Down', ""),)
99+
)
100+
101+
@classmethod
102+
def poll(cls, context):
103+
return context.scene.my_list
104+
105+
def move_index(self):
106+
""" Move index of an item render queue while clamping it. """
107+
index = bpy.context.scene.list_index
108+
list_length = len(bpy.context.scene.my_list) - 1 # (index starts at 0)
109+
new_index = index + (-1 if self.direction == 'UP' else 1)
110+
bpy.context.scene.list_index = max(0, min(new_index, list_length))
111+
112+
def execute(self, context):
113+
my_list = context.scene.my_list
114+
index = context.scene.list_index
115+
neighbor = index + (-1 if self.direction == 'UP' else 1)
116+
my_list.move(neighbor, index)
117+
self.move_index()
118+
return{'FINISHED'}
119+
120+
121+
class PT_ListExample(Panel):
122+
"""Demo panel for UI list Tutorial."""
123+
bl_label = "UI_List Demo"
124+
bl_idname = "SCENE_PT_LIST_DEMO"
125+
bl_space_type = 'PROPERTIES'
126+
bl_region_type = 'WINDOW'
127+
bl_context = "scene"
128+
129+
def draw(self, context):
130+
layout = self.layout
131+
scene = context.scene
132+
row = layout.row()
133+
row.template_list("MY_UL_List", "The_List", scene, "my_list", scene, "list_index")
134+
row = layout.row()
135+
row.operator('my_list.new_item', text='NEW')
136+
row.operator('my_list.delete_item', text='REMOVE')
137+
row.operator('my_list.move_item', text='UP').direction = 'UP'
138+
row.operator('my_list.move_item', text='DOWN').direction = 'DOWN'
139+
if scene.list_index >= 0 and scene.my_list:
140+
item = scene.my_list[scene.list_index]
141+
layout.row().prop(item, 'name')
142+
layout.row().prop(item, 'random_prop')
143+
144+
145+
def register():
146+
bpy.utils.register_class(ListItem)
147+
bpy.utils.register_class(MY_UL_List)
148+
bpy.utils.register_class(LIST_OT_NewItem)
149+
bpy.utils.register_class(LIST_OT_DeleteItem)
150+
bpy.utils.register_class(LIST_OT_MoveItem)
151+
bpy.utils.register_class(PT_ListExample)
152+
bpy.types.Scene.my_list = CollectionProperty(type = ListItem)
153+
bpy.types.Scene.list_index = IntProperty(name = "Index for my_list", default = 0)
154+
155+
156+
def unregister():
157+
del bpy.types.Scene.my_list
158+
del bpy.types.Scene.list_index
159+
bpy.utils.unregister_class(ListItem)
160+
bpy.utils.unregister_class(MY_UL_List)
161+
bpy.utils.unregister_class(LIST_OT_NewItem)
162+
bpy.utils.unregister_class(LIST_OT_DeleteItem)
163+
bpy.utils.unregister_class(LIST_OT_MoveItem)
164+
bpy.utils.unregister_class(PT_ListExample)
165+
166+
if __name__ == "__main__":
167+
register()

0 commit comments

Comments
 (0)