ft-scout 9.4.4 → 9.4.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,130 +0,0 @@
1
- import { getMCPManager } from '../bin/src/mcp/index.js';
2
- import fs from 'fs';
3
- import path from 'path';
4
-
5
- async function main() {
6
- const mgr = getMCPManager();
7
-
8
- const pyCode = `
9
- import bpy
10
- import math
11
-
12
- # 1. Clean up default objects except camera/light
13
- for obj in list(bpy.data.objects):
14
- if obj.type == 'MESH':
15
- bpy.data.objects.remove(obj, do_unlink=True)
16
-
17
- # Helper to create PBR material
18
- def make_mat(name, base_color, metallic=0.0, roughness=0.5, emission=None, emission_strength=1.0):
19
- mat = bpy.data.materials.new(name=name)
20
- mat.use_nodes = True
21
- nodes = mat.node_tree.nodes
22
- bsdf = nodes.get('Principled BSDF')
23
- if bsdf:
24
- bsdf.inputs['Base Color'].default_value = base_color
25
- bsdf.inputs['Metallic'].default_value = metallic
26
- bsdf.inputs['Roughness'].default_value = roughness
27
- if emission:
28
- if 'Emission Color' in bsdf.inputs:
29
- bsdf.inputs['Emission Color'].default_value = emission
30
- bsdf.inputs['Emission Strength'].default_value = emission_strength
31
- elif 'Emission' in bsdf.inputs:
32
- bsdf.inputs['Emission'].default_value = emission
33
- if 'Emission Strength' in bsdf.inputs:
34
- bsdf.inputs['Emission Strength'].default_value = emission_strength
35
- return mat
36
-
37
- mat_hull = make_mat('Hull_Obsidian', (0.05, 0.06, 0.08, 1.0), metallic=0.92, roughness=0.22)
38
- mat_gold = make_mat('Accent_Gold', (0.95, 0.72, 0.18, 1.0), metallic=0.98, roughness=0.18)
39
- mat_cyan_glow = make_mat('Core_CyanGlow', (0.0, 0.9, 1.0, 1.0), emission=(0.0, 0.9, 1.0, 1.0), emission_strength=12.0)
40
- mat_plasma = make_mat('Thruster_Plasma', (0.65, 0.1, 1.0, 1.0), emission=(0.65, 0.1, 1.0, 1.0), emission_strength=16.0)
41
-
42
- # 2. Main Aerodynamic Chassis
43
- bpy.ops.mesh.primitive_uv_sphere_add(segments=32, ring_count=24, radius=1.0, location=(0, 0, 0))
44
- body = bpy.context.active_object
45
- body.name = 'Scout_Chassis'
46
- body.scale = (1.35, 1.65, 0.62)
47
- bpy.ops.object.transform_apply(scale=True)
48
- body.data.materials.append(mat_hull)
49
-
50
- # 3. Cockpit Sensor Eye (Front Core)
51
- bpy.ops.mesh.primitive_uv_sphere_add(segments=24, ring_count=16, radius=0.38, location=(0, 1.5, 0.08))
52
- eye = bpy.context.active_object
53
- eye.name = 'Scout_SensorEye'
54
- eye.scale = (1.1, 0.5, 0.6)
55
- bpy.ops.object.transform_apply(scale=True)
56
- eye.data.materials.append(mat_cyan_glow)
57
-
58
- # 4. Center Power Ring
59
- bpy.ops.mesh.primitive_torus_add(major_radius=0.78, minor_radius=0.08, location=(0, 0, 0.35))
60
- ring = bpy.context.active_object
61
- ring.name = 'Scout_PowerRing'
62
- ring.scale = (1.15, 1.3, 0.8)
63
- bpy.ops.object.transform_apply(scale=True)
64
- ring.data.materials.append(mat_gold)
65
-
66
- # 5. Four Thruster Arms & Turbine Pods
67
- angles = [45, 135, 225, 315]
68
- for i, deg in enumerate(angles):
69
- rad = math.radians(deg)
70
- arm_x = math.cos(rad) * 1.6
71
- arm_y = math.sin(rad) * 1.8
72
-
73
- # Arm strut
74
- bpy.ops.mesh.primitive_cube_add(size=0.18, location=(arm_x * 0.55, arm_y * 0.55, 0))
75
- arm = bpy.context.active_object
76
- arm.name = f'Scout_Arm_{i+1}'
77
- arm.scale = (2.2, 0.5, 0.4)
78
- arm.rotation_euler = (0, 0, rad)
79
- arm.data.materials.append(mat_gold)
80
-
81
- # Thruster outer nacelle
82
- bpy.ops.mesh.primitive_cylinder_add(radius=0.45, depth=0.8, location=(arm_x, arm_y, 0))
83
- thruster = bpy.context.active_object
84
- thruster.name = f'Scout_Thruster_{i+1}'
85
- thruster.rotation_euler = (math.radians(15) if arm_y > 0 else math.radians(-15), 0, 0)
86
- thruster.data.materials.append(mat_hull)
87
-
88
- # Inner plasma exhaust
89
- bpy.ops.mesh.primitive_cylinder_add(radius=0.32, depth=0.15, location=(arm_x, arm_y, -0.35))
90
- plasma = bpy.context.active_object
91
- plasma.name = f'Scout_Plasma_{i+1}'
92
- plasma.data.materials.append(mat_plasma)
93
-
94
- # 6. Twin High-Gain Communication Antennas (Rear)
95
- for side in [-0.4, 0.4]:
96
- bpy.ops.mesh.primitive_cylinder_add(radius=0.025, depth=0.9, location=(side, -1.3, 0.5))
97
- ant = bpy.context.active_object
98
- ant.name = f'Scout_Antenna_{"L" if side < 0 else "R"}'
99
- ant.rotation_euler = (math.radians(-25), math.radians(side * 15), 0)
100
- ant.data.materials.append(mat_gold)
101
-
102
- # Antenna LED tip
103
- bpy.ops.mesh.primitive_uv_sphere_add(radius=0.06, location=(side * 1.25, -1.65, 0.9))
104
- tip = bpy.context.active_object
105
- tip.name = f'Scout_AntennaTip_{"L" if side < 0 else "R"}'
106
- tip.data.materials.append(mat_cyan_glow)
107
-
108
- # Smooth shading across all meshes
109
- for obj in bpy.data.objects:
110
- if obj.type == 'MESH':
111
- for poly in obj.data.polygons:
112
- poly.use_smooth = True
113
-
114
- print('SCOUT_3D_DRONE_CREATED_SUCCESSFULLY')
115
- `;
116
-
117
- console.log('Sending 3D Model Python code to Blender MCP...');
118
- const result = await mgr.executeTool('execute_blender_code', {
119
- code: pyCode,
120
- user_prompt: 'Generate a 3D Sci-Fi Autonomous Scout Drone model with PBR metallic hull and glowing cyan core'
121
- });
122
-
123
- console.log('Status:', result.status);
124
- console.log('Output Summary:', result.outputSummary);
125
- if (result.error) {
126
- console.error('Error:', result.error);
127
- }
128
- }
129
-
130
- main().catch(console.error);
@@ -1,48 +0,0 @@
1
- import { getMCPManager } from '../bin/src/mcp/index.js';
2
- import fs from 'fs';
3
- import path from 'path';
4
-
5
- async function main() {
6
- const mgr = getMCPManager();
7
-
8
- console.log('1. Querying updated Blender scene...');
9
- const sceneInfo = await mgr.executeTool('get_scene_info', {});
10
- console.log('Scene Info:', sceneInfo.result);
11
-
12
- const artifactsDir = path.resolve('artifacts');
13
- if (!fs.existsSync(artifactsDir)) {
14
- fs.mkdirSync(artifactsDir, { recursive: true });
15
- }
16
-
17
- const glbPath = path.resolve('artifacts', 'scout_drone_3d.glb');
18
- console.log('\n2. Exporting 3D Drone Scene to GLB at:', glbPath);
19
- const exportRes = await mgr.executeTool('export_scene', {
20
- filepath: glbPath,
21
- format: 'glb',
22
- apply_modifiers: true,
23
- user_prompt: 'Export the complete Scout 3D Drone model to GLB format'
24
- });
25
- console.log('Export Result:', exportRes.outputSummary);
26
-
27
- console.log('\n3. Capturing Viewport Screenshot from Blender...');
28
- const shotRes = await mgr.executeTool('get_viewport_screenshot', {
29
- user_prompt: 'Capture high-res viewport screenshot of Scout 3D Drone'
30
- });
31
- console.log('Screenshot Status:', shotRes.status);
32
- if (shotRes.result) {
33
- try {
34
- const parsed = typeof shotRes.result === 'string' ? JSON.parse(shotRes.result) : shotRes.result;
35
- if (parsed && parsed.image_base64) {
36
- const imgPath = path.resolve('artifacts', 'scout_drone_3d_render.png');
37
- fs.writeFileSync(imgPath, Buffer.from(parsed.image_base64, 'base64'));
38
- console.log('Saved 3D render to:', imgPath);
39
- }
40
- } catch (e) {
41
- console.log('Screenshot raw result snippet:', String(shotRes.result).slice(0, 200));
42
- }
43
- }
44
-
45
- console.log('\nAll 3D modeling and export steps complete!');
46
- }
47
-
48
- main().catch(console.error);
@@ -1,94 +0,0 @@
1
- import { getMCPManager } from '../bin/src/mcp/index.js';
2
- import fs from 'fs';
3
- import path from 'path';
4
-
5
- async function main() {
6
- const mgr = getMCPManager();
7
-
8
- const artifactsDir = path.resolve('artifacts');
9
- if (!fs.existsSync(artifactsDir)) {
10
- fs.mkdirSync(artifactsDir, { recursive: true });
11
- }
12
-
13
- const glbPath = path.resolve(artifactsDir, 'scout_drone_3d.glb').replace(/\\/g, '/');
14
- const renderPath = path.resolve(artifactsDir, 'scout_drone_3d_render.png').replace(/\\/g, '/');
15
-
16
- const pyCode = `
17
- import bpy
18
- import math
19
-
20
- # 1. Setup Camera for dramatic isometric perspective
21
- cam = bpy.data.objects.get('Camera')
22
- if not cam:
23
- bpy.ops.object.camera_add(location=(4.5, -4.5, 3.2))
24
- cam = bpy.context.active_object
25
- else:
26
- cam.location = (4.5, -4.5, 3.2)
27
-
28
- # Point camera at drone center (0, 0, 0.2)
29
- cam.rotation_euler = (math.radians(62), 0, math.radians(45))
30
- bpy.context.scene.camera = cam
31
-
32
- # 2. Studio Lighting Setup
33
- # Key Light (Warm gold rim)
34
- light_key = bpy.data.objects.get('Light')
35
- if not light_key:
36
- bpy.ops.object.light_add(type='POINT', location=(3.5, 2.5, 4.0))
37
- light_key = bpy.context.active_object
38
- light_key.location = (3.5, 2.5, 4.0)
39
- light_key.data.energy = 800
40
- light_key.data.color = (1.0, 0.85, 0.6)
41
-
42
- # Fill Light (Cool cyan accent)
43
- bpy.ops.object.light_add(type='POINT', location=(-3.5, -2.5, 2.5))
44
- light_fill = bpy.context.active_object
45
- light_fill.name = 'Light_Fill'
46
- light_fill.data.energy = 500
47
- light_fill.data.color = (0.2, 0.8, 1.0)
48
-
49
- # Underglow Rim Light (Purple/Violet rim)
50
- bpy.ops.object.light_add(type='POINT', location=(0, 0, -2.0))
51
- light_under = bpy.context.active_object
52
- light_under.name = 'Light_Underglow'
53
- light_under.data.energy = 400
54
- light_under.data.color = (0.7, 0.2, 1.0)
55
-
56
- # 3. Export to GLB
57
- bpy.ops.export_scene.gltf(
58
- filepath='${glbPath}',
59
- export_format='GLB',
60
- use_selection=False,
61
- export_apply=True
62
- )
63
- print('EXPORTED_GLB_TO: ${glbPath}')
64
-
65
- # 4. Render Still Screenshot to PNG
66
- bpy.context.scene.render.resolution_x = 1280
67
- bpy.context.scene.render.resolution_y = 720
68
- bpy.context.scene.render.image_settings.file_format = 'PNG'
69
- bpy.context.scene.render.filepath = '${renderPath}'
70
- bpy.ops.render.render(write_still=True)
71
- print('RENDERED_PNG_TO: ${renderPath}')
72
- `;
73
-
74
- console.log('Running GLB Export and Camera Render in Blender via MCP...');
75
- const result = await mgr.executeTool('execute_blender_code', {
76
- code: pyCode,
77
- user_prompt: 'Export 3D Scout Drone to GLB and render studio PNG image'
78
- });
79
-
80
- console.log('Result Status:', result.status);
81
- console.log('Result Output:', result.outputSummary);
82
-
83
- if (fs.existsSync(glbPath)) {
84
- const stats = fs.statSync(glbPath);
85
- console.log(`\n Verified GLB file: ${glbPath} (${stats.size} bytes)`);
86
- }
87
-
88
- if (fs.existsSync(renderPath)) {
89
- const stats = fs.statSync(renderPath);
90
- console.log(` Verified Render Image: ${renderPath} (${stats.size} bytes)`);
91
- }
92
- }
93
-
94
- main().catch(console.error);
@@ -1,76 +0,0 @@
1
- import { getMCPManager } from '../bin/src/mcp/index.js';
2
- import fs from 'fs';
3
- import path from 'path';
4
-
5
- async function main() {
6
- const mgr = getMCPManager();
7
-
8
- const artifactsDir = path.resolve('artifacts');
9
- const glbPath = path.resolve(artifactsDir, 'scout_drone_3d.glb').replace(/\\/g, '/');
10
- const renderPath = path.resolve(artifactsDir, 'scout_drone_3d_render.png').replace(/\\/g, '/');
11
-
12
- const pyCode = `
13
- import bpy
14
- import math
15
-
16
- # Position camera in front-three-quarter view (looking directly at the glowing front cockpit eye)
17
- cam = bpy.data.objects.get('Camera')
18
- if not cam:
19
- bpy.ops.object.camera_add(location=(3.6, 3.8, 2.4))
20
- cam = bpy.context.active_object
21
- else:
22
- cam.location = (3.6, 3.8, 2.4)
23
-
24
- cam.rotation_euler = (math.radians(64), 0, math.radians(138))
25
- bpy.context.scene.camera = cam
26
-
27
- # Adjust lights for cinematic drama
28
- # Front Key light on the glowing eye and gold ring
29
- light_key = bpy.data.objects.get('Light')
30
- if light_key:
31
- light_key.location = (2.5, 4.0, 3.5)
32
- light_key.data.energy = 900
33
- light_key.data.color = (1.0, 0.92, 0.8)
34
-
35
- # Cool cyan rim fill on the opposite flank
36
- light_fill = bpy.data.objects.get('Light_Fill')
37
- if light_fill:
38
- light_fill.location = (-4.0, 2.0, 2.8)
39
- light_fill.data.energy = 650
40
- light_fill.data.color = (0.0, 0.85, 1.0)
41
-
42
- # Back rim light for separation
43
- light_under = bpy.data.objects.get('Light_Underglow')
44
- if light_under:
45
- light_under.location = (-1.0, -3.5, 3.0)
46
- light_under.data.energy = 700
47
- light_under.data.color = (0.9, 0.4, 1.0)
48
-
49
- # Export updated GLB with all materials
50
- bpy.ops.export_scene.gltf(
51
- filepath='${glbPath}',
52
- export_format='GLB',
53
- use_selection=False,
54
- export_apply=True
55
- )
56
-
57
- # Render cinematic 1280x720 still
58
- bpy.context.scene.render.resolution_x = 1280
59
- bpy.context.scene.render.resolution_y = 720
60
- bpy.context.scene.render.image_settings.file_format = 'PNG'
61
- bpy.context.scene.render.filepath = '${renderPath}'
62
- bpy.ops.render.render(write_still=True)
63
- print('FRONT_CINEMATIC_RENDER_COMPLETE')
64
- `;
65
-
66
- console.log('Rendering front cinematic view in Blender...');
67
- const result = await mgr.executeTool('execute_blender_code', {
68
- code: pyCode,
69
- user_prompt: 'Render front cinematic camera angle of 3D Scout Drone'
70
- });
71
-
72
- console.log('Result Status:', result.status);
73
- console.log('Output Summary:', result.outputSummary);
74
- }
75
-
76
- main().catch(console.error);