167 lines
6.4 KiB
Python
167 lines
6.4 KiB
Python
import unittest
|
|
import numpy as np
|
|
from pathlib import Path
|
|
import tempfile
|
|
import os
|
|
import sys
|
|
|
|
PROJECT_ROOT = Path(__file__).resolve().parent.parent
|
|
sys.path.append(str(PROJECT_ROOT.parent))
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
class DummyBase: pass
|
|
mock_types = MagicMock()
|
|
mock_types.NodeSocket = type("NodeSocket", (DummyBase,), {})
|
|
mock_types.Node = type("Node", (DummyBase,), {})
|
|
mock_types.NodeCustomGroup = type("NodeCustomGroup", (DummyBase,), {})
|
|
mock_types.NodeTree = type("NodeTree", (DummyBase,), {})
|
|
mock_types.PropertyGroup = type("PropertyGroup", (DummyBase,), {})
|
|
mock_types.Operator = type("Operator", (DummyBase,), {})
|
|
mock_types.Panel = type("Panel", (DummyBase,), {})
|
|
mock_types.Object = MagicMock
|
|
mock_types.Mesh = MagicMock
|
|
|
|
mock_bpy = MagicMock()
|
|
mock_bpy.types = mock_types
|
|
mock_bpy.path.abspath = lambda path: path.replace("//", "/abs/")
|
|
|
|
sys.modules['bpy'] = mock_bpy
|
|
sys.modules['bpy.types'] = mock_types
|
|
sys.modules['bpy.props'] = MagicMock()
|
|
sys.modules['bpy.utils'] = MagicMock()
|
|
sys.modules['bpy.utils.previews'] = MagicMock()
|
|
sys.modules['bpy.app'] = MagicMock()
|
|
sys.modules['bpy.app.handlers'] = MagicMock()
|
|
|
|
from NodeSlicer.core.nodeslicer.nodes.inputs import SLICENODE_WipeTower, SLICENODE_OffsetObject
|
|
from NodeSlicer.core.nodeslicer.nodes.mesh import SLICENODE_AssignModifiers
|
|
from NodeSlicer.infra.prusaslicer_profiles.models import ConfigWriter
|
|
from NodeSlicer.infra._3mf_writer._3mf import write_model_xml, write_metadata_xml
|
|
from NodeSlicer.infra.blender.blender_mesh_capture import SlicingObject, SlicingCollection, SlicingGroup
|
|
import xml.etree.ElementTree as ET
|
|
|
|
class TestWipeTowerNode(unittest.TestCase):
|
|
def test_wipe_tower_node_output(self):
|
|
node = SLICENODE_WipeTower()
|
|
node.resolve = lambda key: 180.5 if key == "X Position" else 135.2
|
|
|
|
res = node.evaluate_output("Settings")
|
|
self.assertIn("wipe_tower_position", res)
|
|
self.assertEqual(res["wipe_tower_position"], (180.5, 135.2))
|
|
|
|
def test_offset_object_node_output(self):
|
|
node = SLICENODE_OffsetObject()
|
|
node.resolve = lambda key: {"X Offset": 12.5, "Y Offset": -5.0, "Z Offset": 2.0}.get(key, 0.0)
|
|
|
|
res = node.evaluate_output("Settings")
|
|
self.assertIn("offset_object", res)
|
|
self.assertEqual(res["offset_object"], (12.5, -5.0, 2.0))
|
|
|
|
def test_config_writer_excludes_special_keys(self):
|
|
conf = {
|
|
"layer_height": "0.2",
|
|
"wipe_tower_position": "(180.5, 135.2)",
|
|
"offset_object": "(12.5, -5.0, 2.0)",
|
|
"nozzle_diameter": "0.4"
|
|
}
|
|
writer = ConfigWriter(conf)
|
|
|
|
with tempfile.TemporaryDirectory() as temp_dir:
|
|
ini_path = Path(temp_dir) / "Slic3r_PE.config"
|
|
writer.write_ini_3mf(ini_path)
|
|
|
|
with open(ini_path, 'r', encoding='utf-8') as f:
|
|
content = f.read()
|
|
|
|
self.assertIn("; layer_height = 0.2", content)
|
|
self.assertIn("; nozzle_diameter = 0.4", content)
|
|
self.assertNotIn("wipe_tower_position", content)
|
|
self.assertNotIn("offset_object", content)
|
|
|
|
|
|
class TestAssignModifiersNode(unittest.TestCase):
|
|
def setUp(self):
|
|
self.so = SlicingObject()
|
|
self.so.name = "TestPart"
|
|
self.so.object_type = "ModelPart"
|
|
self.so.extruder = "1"
|
|
self.so.modifiers = [{"param_id": "initial_param", "param_value": "123"}]
|
|
self.so.mesh = np.array([[[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]], dtype=np.float64)
|
|
|
|
self.sc = SlicingCollection([], "TestColl")
|
|
self.sc.objects = [self.so]
|
|
self.sc.mesh_start_ids = [0]
|
|
self.sc.mesh_end_ids = [1]
|
|
|
|
self.sg = SlicingGroup([])
|
|
self.sg.collections = {"TestColl": self.sc}
|
|
|
|
def test_assign_modifiers_to_slicing_object(self):
|
|
node = SLICENODE_AssignModifiers()
|
|
node.part_type = "ParameterModifier"
|
|
node.extruder = "3"
|
|
node.resolve = lambda f: {
|
|
"Geometry": self.so,
|
|
"Modifiers": {"infill_density": "20%", "layer_height": "0.15"}
|
|
}.get(f)
|
|
|
|
result_so = node.evaluate_output("Geometry")
|
|
self.assertIsNotNone(result_so)
|
|
self.assertEqual(result_so.object_type, "ParameterModifier")
|
|
self.assertEqual(result_so.extruder, 3)
|
|
|
|
mod_dict = {m['param_id']: m['param_value'] for m in result_so.modifiers}
|
|
self.assertEqual(mod_dict["initial_param"], "123")
|
|
self.assertEqual(mod_dict["infill_density"], "20%")
|
|
self.assertEqual(mod_dict["layer_height"], "0.15")
|
|
|
|
def test_assign_modifiers_to_slicing_group(self):
|
|
node = SLICENODE_AssignModifiers()
|
|
node.part_type = "NegativeVolume"
|
|
node.extruder = "2"
|
|
node.resolve = lambda f: {
|
|
"Geometry": self.sg,
|
|
"Modifiers": {"perimeters": "4"}
|
|
}.get(f)
|
|
|
|
result_sg = node.evaluate_output("Geometry")
|
|
self.assertIsNotNone(result_sg)
|
|
res_so = result_sg.collections["TestColl"].objects[0]
|
|
self.assertEqual(res_so.object_type, "NegativeVolume")
|
|
self.assertEqual(res_so.extruder, 2)
|
|
|
|
mod_dict = {m['param_id']: m['param_value'] for m in res_so.modifiers}
|
|
self.assertEqual(mod_dict["perimeters"], "4")
|
|
|
|
def test_3mf_metadata_xml_output(self):
|
|
node = SLICENODE_AssignModifiers()
|
|
node.part_type = "ParameterModifier"
|
|
node.extruder = "2"
|
|
node.resolve = lambda f: {
|
|
"Geometry": self.sg,
|
|
"Modifiers": {"fill_density": "30%"}
|
|
}.get(f)
|
|
|
|
modified_sg = node.evaluate_output("Geometry")
|
|
|
|
with tempfile.TemporaryDirectory() as temp_dir:
|
|
xml_path = Path(temp_dir) / "Slic3r_PE_model.config"
|
|
write_metadata_xml(modified_sg, xml_path)
|
|
|
|
tree = ET.parse(xml_path)
|
|
root = tree.getroot()
|
|
|
|
volumes = root.findall(".//volume")
|
|
self.assertEqual(len(volumes), 1)
|
|
vol = volumes[0]
|
|
|
|
meta_entries = {m.get("key"): m.get("value") for m in vol.findall("metadata")}
|
|
self.assertEqual(meta_entries.get("volume_type"), "ParameterModifier")
|
|
self.assertEqual(meta_entries.get("modifier"), "1")
|
|
self.assertEqual(meta_entries.get("extruder"), "2")
|
|
self.assertEqual(meta_entries.get("fill_density"), "30%")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|