628 lines
23 KiB
TypeScript
628 lines
23 KiB
TypeScript
import { ToolDefinition, ToolResponse, ToolExecutor } from '../types';
|
|
|
|
export class SceneViewTools implements ToolExecutor {
|
|
getTools(): ToolDefinition[] {
|
|
return [
|
|
{
|
|
name: 'change_gizmo_tool',
|
|
description: 'Change Gizmo tool',
|
|
inputSchema: {
|
|
type: 'object',
|
|
properties: {
|
|
name: {
|
|
type: 'string',
|
|
description: 'Tool name',
|
|
enum: ['position', 'rotation', 'scale', 'rect']
|
|
}
|
|
},
|
|
required: ['name']
|
|
}
|
|
},
|
|
{
|
|
name: 'query_gizmo_tool_name',
|
|
description: 'Get current Gizmo tool name',
|
|
inputSchema: {
|
|
type: 'object',
|
|
properties: {}
|
|
}
|
|
},
|
|
{
|
|
name: 'change_gizmo_pivot',
|
|
description: 'Change transform pivot point',
|
|
inputSchema: {
|
|
type: 'object',
|
|
properties: {
|
|
name: {
|
|
type: 'string',
|
|
description: 'Pivot point',
|
|
enum: ['pivot', 'center']
|
|
}
|
|
},
|
|
required: ['name']
|
|
}
|
|
},
|
|
{
|
|
name: 'query_gizmo_pivot',
|
|
description: 'Get current Gizmo pivot point',
|
|
inputSchema: {
|
|
type: 'object',
|
|
properties: {}
|
|
}
|
|
},
|
|
{
|
|
name: 'query_gizmo_view_mode',
|
|
description: 'Query view mode (view/select)',
|
|
inputSchema: {
|
|
type: 'object',
|
|
properties: {}
|
|
}
|
|
},
|
|
{
|
|
name: 'change_gizmo_coordinate',
|
|
description: 'Change coordinate system',
|
|
inputSchema: {
|
|
type: 'object',
|
|
properties: {
|
|
type: {
|
|
type: 'string',
|
|
description: 'Coordinate system',
|
|
enum: ['local', 'global']
|
|
}
|
|
},
|
|
required: ['type']
|
|
}
|
|
},
|
|
{
|
|
name: 'query_gizmo_coordinate',
|
|
description: 'Get current coordinate system',
|
|
inputSchema: {
|
|
type: 'object',
|
|
properties: {}
|
|
}
|
|
},
|
|
{
|
|
name: 'change_view_mode_2d_3d',
|
|
description: 'Change 2D/3D view mode',
|
|
inputSchema: {
|
|
type: 'object',
|
|
properties: {
|
|
is2D: {
|
|
type: 'boolean',
|
|
description: '2D/3D view mode (true for 2D, false for 3D)'
|
|
}
|
|
},
|
|
required: ['is2D']
|
|
}
|
|
},
|
|
{
|
|
name: 'query_view_mode_2d_3d',
|
|
description: 'Get current view mode',
|
|
inputSchema: {
|
|
type: 'object',
|
|
properties: {}
|
|
}
|
|
},
|
|
{
|
|
name: 'set_grid_visible',
|
|
description: 'Show/hide grid',
|
|
inputSchema: {
|
|
type: 'object',
|
|
properties: {
|
|
visible: {
|
|
type: 'boolean',
|
|
description: 'Grid visibility'
|
|
}
|
|
},
|
|
required: ['visible']
|
|
}
|
|
},
|
|
{
|
|
name: 'query_grid_visible',
|
|
description: 'Query grid visibility status',
|
|
inputSchema: {
|
|
type: 'object',
|
|
properties: {}
|
|
}
|
|
},
|
|
{
|
|
name: 'set_icon_gizmo_3d',
|
|
description: 'Set IconGizmo to 3D or 2D mode',
|
|
inputSchema: {
|
|
type: 'object',
|
|
properties: {
|
|
is3D: {
|
|
type: 'boolean',
|
|
description: '3D/2D IconGizmo (true for 3D, false for 2D)'
|
|
}
|
|
},
|
|
required: ['is3D']
|
|
}
|
|
},
|
|
{
|
|
name: 'query_icon_gizmo_3d',
|
|
description: 'Query IconGizmo mode',
|
|
inputSchema: {
|
|
type: 'object',
|
|
properties: {}
|
|
}
|
|
},
|
|
{
|
|
name: 'set_icon_gizmo_size',
|
|
description: 'Set IconGizmo size',
|
|
inputSchema: {
|
|
type: 'object',
|
|
properties: {
|
|
size: {
|
|
type: 'number',
|
|
description: 'IconGizmo size',
|
|
minimum: 10,
|
|
maximum: 100
|
|
}
|
|
},
|
|
required: ['size']
|
|
}
|
|
},
|
|
{
|
|
name: 'query_icon_gizmo_size',
|
|
description: 'Query IconGizmo size',
|
|
inputSchema: {
|
|
type: 'object',
|
|
properties: {}
|
|
}
|
|
},
|
|
{
|
|
name: 'focus_camera_on_nodes',
|
|
description: 'Focus scene camera on nodes',
|
|
inputSchema: {
|
|
type: 'object',
|
|
properties: {
|
|
uuids: {
|
|
oneOf: [
|
|
{ type: 'array', items: { type: 'string' } },
|
|
{ type: 'null' }
|
|
],
|
|
description: 'Node UUIDs to focus on (null for all)'
|
|
}
|
|
},
|
|
required: ['uuids']
|
|
}
|
|
},
|
|
{
|
|
name: 'align_camera_with_view',
|
|
description: 'Apply scene camera position and angle to selected node',
|
|
inputSchema: {
|
|
type: 'object',
|
|
properties: {}
|
|
}
|
|
},
|
|
{
|
|
name: 'align_view_with_node',
|
|
description: 'Apply selected node position and angle to current view',
|
|
inputSchema: {
|
|
type: 'object',
|
|
properties: {}
|
|
}
|
|
},
|
|
{
|
|
name: 'get_scene_view_status',
|
|
description: 'Get comprehensive scene view status',
|
|
inputSchema: {
|
|
type: 'object',
|
|
properties: {}
|
|
}
|
|
},
|
|
{
|
|
name: 'reset_scene_view',
|
|
description: 'Reset scene view to default settings',
|
|
inputSchema: {
|
|
type: 'object',
|
|
properties: {}
|
|
}
|
|
}
|
|
];
|
|
}
|
|
|
|
async execute(toolName: string, args: any): Promise<ToolResponse> {
|
|
switch (toolName) {
|
|
case 'change_gizmo_tool':
|
|
return await this.changeGizmoTool(args.name);
|
|
case 'query_gizmo_tool_name':
|
|
return await this.queryGizmoToolName();
|
|
case 'change_gizmo_pivot':
|
|
return await this.changeGizmoPivot(args.name);
|
|
case 'query_gizmo_pivot':
|
|
return await this.queryGizmoPivot();
|
|
case 'query_gizmo_view_mode':
|
|
return await this.queryGizmoViewMode();
|
|
case 'change_gizmo_coordinate':
|
|
return await this.changeGizmoCoordinate(args.type);
|
|
case 'query_gizmo_coordinate':
|
|
return await this.queryGizmoCoordinate();
|
|
case 'change_view_mode_2d_3d':
|
|
return await this.changeViewMode2D3D(args.is2D);
|
|
case 'query_view_mode_2d_3d':
|
|
return await this.queryViewMode2D3D();
|
|
case 'set_grid_visible':
|
|
return await this.setGridVisible(args.visible);
|
|
case 'query_grid_visible':
|
|
return await this.queryGridVisible();
|
|
case 'set_icon_gizmo_3d':
|
|
return await this.setIconGizmo3D(args.is3D);
|
|
case 'query_icon_gizmo_3d':
|
|
return await this.queryIconGizmo3D();
|
|
case 'set_icon_gizmo_size':
|
|
return await this.setIconGizmoSize(args.size);
|
|
case 'query_icon_gizmo_size':
|
|
return await this.queryIconGizmoSize();
|
|
case 'focus_camera_on_nodes':
|
|
return await this.focusCameraOnNodes(args.uuids);
|
|
case 'align_camera_with_view':
|
|
return await this.alignCameraWithView();
|
|
case 'align_view_with_node':
|
|
return await this.alignViewWithNode();
|
|
case 'get_scene_view_status':
|
|
return await this.getSceneViewStatus();
|
|
case 'reset_scene_view':
|
|
return await this.resetSceneView();
|
|
default:
|
|
throw new Error(`Unknown tool: ${toolName}`);
|
|
}
|
|
}
|
|
|
|
private async changeGizmoTool(name: string): Promise<ToolResponse> {
|
|
return new Promise((resolve) => {
|
|
Editor.Message.request('scene', 'change-gizmo-tool', name).then(() => {
|
|
resolve({
|
|
success: true,
|
|
message: `Gizmo tool changed to '${name}'`
|
|
});
|
|
}).catch((err: Error) => {
|
|
resolve({ success: false, error: err.message });
|
|
});
|
|
});
|
|
}
|
|
|
|
private async queryGizmoToolName(): Promise<ToolResponse> {
|
|
return new Promise((resolve) => {
|
|
Editor.Message.request('scene', 'query-gizmo-tool-name').then((toolName: string) => {
|
|
resolve({
|
|
success: true,
|
|
data: {
|
|
currentTool: toolName,
|
|
message: `Current Gizmo tool: ${toolName}`
|
|
}
|
|
});
|
|
}).catch((err: Error) => {
|
|
resolve({ success: false, error: err.message });
|
|
});
|
|
});
|
|
}
|
|
|
|
private async changeGizmoPivot(name: string): Promise<ToolResponse> {
|
|
return new Promise((resolve) => {
|
|
Editor.Message.request('scene', 'change-gizmo-pivot', name).then(() => {
|
|
resolve({
|
|
success: true,
|
|
message: `Gizmo pivot changed to '${name}'`
|
|
});
|
|
}).catch((err: Error) => {
|
|
resolve({ success: false, error: err.message });
|
|
});
|
|
});
|
|
}
|
|
|
|
private async queryGizmoPivot(): Promise<ToolResponse> {
|
|
return new Promise((resolve) => {
|
|
Editor.Message.request('scene', 'query-gizmo-pivot').then((pivotName: string) => {
|
|
resolve({
|
|
success: true,
|
|
data: {
|
|
currentPivot: pivotName,
|
|
message: `Current Gizmo pivot: ${pivotName}`
|
|
}
|
|
});
|
|
}).catch((err: Error) => {
|
|
resolve({ success: false, error: err.message });
|
|
});
|
|
});
|
|
}
|
|
|
|
private async queryGizmoViewMode(): Promise<ToolResponse> {
|
|
return new Promise((resolve) => {
|
|
Editor.Message.request('scene', 'query-gizmo-view-mode').then((viewMode: string) => {
|
|
resolve({
|
|
success: true,
|
|
data: {
|
|
viewMode: viewMode,
|
|
message: `Current view mode: ${viewMode}`
|
|
}
|
|
});
|
|
}).catch((err: Error) => {
|
|
resolve({ success: false, error: err.message });
|
|
});
|
|
});
|
|
}
|
|
|
|
private async changeGizmoCoordinate(type: string): Promise<ToolResponse> {
|
|
return new Promise((resolve) => {
|
|
Editor.Message.request('scene', 'change-gizmo-coordinate', type).then(() => {
|
|
resolve({
|
|
success: true,
|
|
message: `Coordinate system changed to '${type}'`
|
|
});
|
|
}).catch((err: Error) => {
|
|
resolve({ success: false, error: err.message });
|
|
});
|
|
});
|
|
}
|
|
|
|
private async queryGizmoCoordinate(): Promise<ToolResponse> {
|
|
return new Promise((resolve) => {
|
|
Editor.Message.request('scene', 'query-gizmo-coordinate').then((coordinate: string) => {
|
|
resolve({
|
|
success: true,
|
|
data: {
|
|
coordinate: coordinate,
|
|
message: `Current coordinate system: ${coordinate}`
|
|
}
|
|
});
|
|
}).catch((err: Error) => {
|
|
resolve({ success: false, error: err.message });
|
|
});
|
|
});
|
|
}
|
|
|
|
private async changeViewMode2D3D(is2D: boolean): Promise<ToolResponse> {
|
|
return new Promise((resolve) => {
|
|
Editor.Message.request('scene', 'change-is2D', is2D).then(() => {
|
|
resolve({
|
|
success: true,
|
|
message: `View mode changed to ${is2D ? '2D' : '3D'}`
|
|
});
|
|
}).catch((err: Error) => {
|
|
resolve({ success: false, error: err.message });
|
|
});
|
|
});
|
|
}
|
|
|
|
private async queryViewMode2D3D(): Promise<ToolResponse> {
|
|
return new Promise((resolve) => {
|
|
Editor.Message.request('scene', 'query-is2D').then((is2D: boolean) => {
|
|
resolve({
|
|
success: true,
|
|
data: {
|
|
is2D: is2D,
|
|
viewMode: is2D ? '2D' : '3D',
|
|
message: `Current view mode: ${is2D ? '2D' : '3D'}`
|
|
}
|
|
});
|
|
}).catch((err: Error) => {
|
|
resolve({ success: false, error: err.message });
|
|
});
|
|
});
|
|
}
|
|
|
|
private async setGridVisible(visible: boolean): Promise<ToolResponse> {
|
|
return new Promise((resolve) => {
|
|
Editor.Message.request('scene', 'set-grid-visible', visible).then(() => {
|
|
resolve({
|
|
success: true,
|
|
message: `Grid ${visible ? 'shown' : 'hidden'}`
|
|
});
|
|
}).catch((err: Error) => {
|
|
resolve({ success: false, error: err.message });
|
|
});
|
|
});
|
|
}
|
|
|
|
private async queryGridVisible(): Promise<ToolResponse> {
|
|
return new Promise((resolve) => {
|
|
Editor.Message.request('scene', 'query-is-grid-visible').then((visible: boolean) => {
|
|
resolve({
|
|
success: true,
|
|
data: {
|
|
visible: visible,
|
|
message: `Grid is ${visible ? 'visible' : 'hidden'}`
|
|
}
|
|
});
|
|
}).catch((err: Error) => {
|
|
resolve({ success: false, error: err.message });
|
|
});
|
|
});
|
|
}
|
|
|
|
private async setIconGizmo3D(is3D: boolean): Promise<ToolResponse> {
|
|
return new Promise((resolve) => {
|
|
Editor.Message.request('scene', 'set-icon-gizmo-3d', is3D).then(() => {
|
|
resolve({
|
|
success: true,
|
|
message: `IconGizmo set to ${is3D ? '3D' : '2D'} mode`
|
|
});
|
|
}).catch((err: Error) => {
|
|
resolve({ success: false, error: err.message });
|
|
});
|
|
});
|
|
}
|
|
|
|
private async queryIconGizmo3D(): Promise<ToolResponse> {
|
|
return new Promise((resolve) => {
|
|
Editor.Message.request('scene', 'query-is-icon-gizmo-3d').then((is3D: boolean) => {
|
|
resolve({
|
|
success: true,
|
|
data: {
|
|
is3D: is3D,
|
|
mode: is3D ? '3D' : '2D',
|
|
message: `IconGizmo is in ${is3D ? '3D' : '2D'} mode`
|
|
}
|
|
});
|
|
}).catch((err: Error) => {
|
|
resolve({ success: false, error: err.message });
|
|
});
|
|
});
|
|
}
|
|
|
|
private async setIconGizmoSize(size: number): Promise<ToolResponse> {
|
|
return new Promise((resolve) => {
|
|
Editor.Message.request('scene', 'set-icon-gizmo-size', size).then(() => {
|
|
resolve({
|
|
success: true,
|
|
message: `IconGizmo size set to ${size}`
|
|
});
|
|
}).catch((err: Error) => {
|
|
resolve({ success: false, error: err.message });
|
|
});
|
|
});
|
|
}
|
|
|
|
private async queryIconGizmoSize(): Promise<ToolResponse> {
|
|
return new Promise((resolve) => {
|
|
Editor.Message.request('scene', 'query-icon-gizmo-size').then((size: number) => {
|
|
resolve({
|
|
success: true,
|
|
data: {
|
|
size: size,
|
|
message: `IconGizmo size: ${size}`
|
|
}
|
|
});
|
|
}).catch((err: Error) => {
|
|
resolve({ success: false, error: err.message });
|
|
});
|
|
});
|
|
}
|
|
|
|
private async focusCameraOnNodes(uuids: string[] | null): Promise<ToolResponse> {
|
|
return new Promise((resolve) => {
|
|
Editor.Message.request('scene', 'focus-camera', uuids || []).then(() => {
|
|
const message = uuids === null ?
|
|
'Camera focused on all nodes' :
|
|
`Camera focused on ${uuids.length} node(s)`;
|
|
resolve({
|
|
success: true,
|
|
message: message
|
|
});
|
|
}).catch((err: Error) => {
|
|
resolve({ success: false, error: err.message });
|
|
});
|
|
});
|
|
}
|
|
|
|
private async alignCameraWithView(): Promise<ToolResponse> {
|
|
return new Promise((resolve) => {
|
|
Editor.Message.request('scene', 'align-with-view').then(() => {
|
|
resolve({
|
|
success: true,
|
|
message: 'Scene camera aligned with current view'
|
|
});
|
|
}).catch((err: Error) => {
|
|
resolve({ success: false, error: err.message });
|
|
});
|
|
});
|
|
}
|
|
|
|
private async alignViewWithNode(): Promise<ToolResponse> {
|
|
return new Promise((resolve) => {
|
|
Editor.Message.request('scene', 'align-with-view-node').then(() => {
|
|
resolve({
|
|
success: true,
|
|
message: 'View aligned with selected node'
|
|
});
|
|
}).catch((err: Error) => {
|
|
resolve({ success: false, error: err.message });
|
|
});
|
|
});
|
|
}
|
|
|
|
private async getSceneViewStatus(): Promise<ToolResponse> {
|
|
return new Promise(async (resolve) => {
|
|
try {
|
|
// Gather all view status information
|
|
const [
|
|
gizmoTool,
|
|
gizmoPivot,
|
|
gizmoCoordinate,
|
|
viewMode2D3D,
|
|
gridVisible,
|
|
iconGizmo3D,
|
|
iconGizmoSize
|
|
] = await Promise.allSettled([
|
|
this.queryGizmoToolName(),
|
|
this.queryGizmoPivot(),
|
|
this.queryGizmoCoordinate(),
|
|
this.queryViewMode2D3D(),
|
|
this.queryGridVisible(),
|
|
this.queryIconGizmo3D(),
|
|
this.queryIconGizmoSize()
|
|
]);
|
|
|
|
const status: any = {
|
|
timestamp: new Date().toISOString()
|
|
};
|
|
|
|
// Extract data from fulfilled promises
|
|
if (gizmoTool.status === 'fulfilled' && gizmoTool.value.success) {
|
|
status.gizmoTool = gizmoTool.value.data.currentTool;
|
|
}
|
|
if (gizmoPivot.status === 'fulfilled' && gizmoPivot.value.success) {
|
|
status.gizmoPivot = gizmoPivot.value.data.currentPivot;
|
|
}
|
|
if (gizmoCoordinate.status === 'fulfilled' && gizmoCoordinate.value.success) {
|
|
status.coordinate = gizmoCoordinate.value.data.coordinate;
|
|
}
|
|
if (viewMode2D3D.status === 'fulfilled' && viewMode2D3D.value.success) {
|
|
status.is2D = viewMode2D3D.value.data.is2D;
|
|
status.viewMode = viewMode2D3D.value.data.viewMode;
|
|
}
|
|
if (gridVisible.status === 'fulfilled' && gridVisible.value.success) {
|
|
status.gridVisible = gridVisible.value.data.visible;
|
|
}
|
|
if (iconGizmo3D.status === 'fulfilled' && iconGizmo3D.value.success) {
|
|
status.iconGizmo3D = iconGizmo3D.value.data.is3D;
|
|
}
|
|
if (iconGizmoSize.status === 'fulfilled' && iconGizmoSize.value.success) {
|
|
status.iconGizmoSize = iconGizmoSize.value.data.size;
|
|
}
|
|
|
|
resolve({
|
|
success: true,
|
|
data: status
|
|
});
|
|
|
|
} catch (err: any) {
|
|
resolve({
|
|
success: false,
|
|
error: `Failed to get scene view status: ${err.message}`
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
private async resetSceneView(): Promise<ToolResponse> {
|
|
return new Promise(async (resolve) => {
|
|
try {
|
|
// Reset scene view to default settings
|
|
const resetActions = [
|
|
this.changeGizmoTool('position'),
|
|
this.changeGizmoPivot('pivot'),
|
|
this.changeGizmoCoordinate('local'),
|
|
this.changeViewMode2D3D(false), // 3D mode
|
|
this.setGridVisible(true),
|
|
this.setIconGizmo3D(true),
|
|
this.setIconGizmoSize(60)
|
|
];
|
|
|
|
await Promise.all(resetActions);
|
|
|
|
resolve({
|
|
success: true,
|
|
message: 'Scene view reset to default settings'
|
|
});
|
|
|
|
} catch (err: any) {
|
|
resolve({
|
|
success: false,
|
|
error: `Failed to reset scene view: ${err.message}`
|
|
});
|
|
}
|
|
});
|
|
}
|
|
} |