11import { Node } from "../rendering/types/node" ;
2- import { vec3 } from "../math/types" ;
3- import type { Line } from "../math/types" ;
2+ import { vec3 , vec4 } from "../math/types" ;
3+ import type { Line , mat4 } from "../math/types" ;
44import { Inspector } from "./inspector" ;
55import { create_arrow } from "../rendering/utils/primitives" ;
66import type { Scene } from "../rendering/types/scene" ;
77import { scale } from "../math/transformations" ;
8+ import { mul_mat4_vec4 , scalar_mult_vec3 } from "../math/matrix_operators" ;
89
910export type EditorMode = "IDLE" | "TRANSLATE_X" | "TRANSLATE_Y" | "TRANSLATE_Z" ;
1011
@@ -52,10 +53,16 @@ export class EditorState {
5253 this . inspector . inspect ( node ) ;
5354
5455 if ( node ) {
55- const scale_amount = node . scale_vec ;
56- this . gizmo_x . scale_vec = scale_amount ;
57- this . gizmo_y . scale_vec = scale_amount ;
58- this . gizmo_z . scale_vec = scale_amount ;
56+ let extent = 0
57+ for ( let i = 0 ; i < 3 ; ++ i ) {
58+ extent = Math . max ( node . radius [ i ] * Math . abs ( node . scale_vec [ i ] ) , extent ) ;
59+ }
60+ const gizmo_size = extent + 0.2 ;
61+
62+
63+ this . gizmo_x . scale_vec = vec3 ( gizmo_size , gizmo_size , gizmo_size ) ;
64+ this . gizmo_y . scale_vec = vec3 ( gizmo_size , gizmo_size , gizmo_size ) ;
65+ this . gizmo_z . scale_vec = vec3 ( gizmo_size , gizmo_size , gizmo_size ) ;
5966 this . update_gizmo_transforms ( ) ;
6067 } else {
6168 this . gizmo_x . scale_vec = vec3 ( 0 , 0 , 0 ) ;
@@ -112,26 +119,45 @@ export class EditorState {
112119 this . select ( null ) ;
113120 }
114121
115- public handle_mouse_move ( mouse_x : number , mouse_y : number ) {
122+ public handle_mouse_move ( mouse_x : number , mouse_y : number , vp : mat4 , width : number , height : number ) {
116123 if ( ! this . is_dragging ) return ;
117124
118125 const dx = mouse_x - this . last_x ;
119126 const dy = mouse_y - this . last_y ;
120-
121127 this . last_x = mouse_x ;
122128 this . last_y = mouse_y ;
123129
124130 if ( ! this . selected_node || this . mode === "IDLE" ) return ;
125131
126- const sensitivity = 0.02 ;
132+ const pos = this . selected_node . position ;
133+
134+ let axis_3d = vec3 ( 0 , 0 , 0 ) ;
135+ if ( this . mode === "TRANSLATE_X" ) axis_3d = vec3 ( 1 , 0 , 0 ) ;
136+ else if ( this . mode === "TRANSLATE_Y" ) axis_3d = vec3 ( 0 , 1 , 0 ) ;
137+ else if ( this . mode === "TRANSLATE_Z" ) axis_3d = vec3 ( 0 , 0 , 1 ) ;
127138
128- if ( this . mode === "TRANSLATE_X" ) {
129- this . selected_node . position [ 0 ] += dx * sensitivity ;
130- } else if ( this . mode === "TRANSLATE_Y" ) {
131- this . selected_node . position [ 1 ] -= dy * sensitivity ;
132- } else if ( this . mode === "TRANSLATE_Z" ) {
133- this . selected_node . position [ 2 ] -= ( dx + dy ) * sensitivity ;
139+ const origin_screen = this . project_to_screen ( pos , vp , width , height ) ;
140+
141+ const point_on_axis = vec3 ( pos [ 0 ] + axis_3d [ 0 ] , pos [ 1 ] + axis_3d [ 1 ] , pos [ 2 ] + axis_3d [ 2 ] ) ;
142+ const axis_screen = this . project_to_screen ( point_on_axis , vp , width , height ) ;
143+
144+ let dir_x = axis_screen [ 0 ] - origin_screen [ 0 ] ;
145+ let dir_y = axis_screen [ 1 ] - origin_screen [ 1 ] ;
146+
147+ const len = Math . sqrt ( dir_x * dir_x + dir_y * dir_y ) ;
148+ if ( len > 0.0001 ) {
149+ dir_x /= len ;
150+ dir_y /= len ;
134151 }
152+ const move_amount = ( dx * dir_x ) + ( dy * dir_y ) ;
153+
154+ const sensitivity = 1 / len ;
155+ const total_move = move_amount * sensitivity ;
156+
157+
158+ this . selected_node . position [ 0 ] += axis_3d [ 0 ] * total_move ;
159+ this . selected_node . position [ 1 ] += axis_3d [ 1 ] * total_move ;
160+ this . selected_node . position [ 2 ] += axis_3d [ 2 ] * total_move ;
135161
136162 this . selected_node . update_matrix ( ) ;
137163 this . update_gizmo_transforms ( ) ;
@@ -148,4 +174,18 @@ export class EditorState {
148174 if ( ! this . selected_node ) return [ ] ;
149175 return [ this . gizmo_x , this . gizmo_y , this . gizmo_z ] ;
150176 }
177+
178+ private project_to_screen ( p :vec3 , vp :mat4 , width :number , height :number ) : [ number , number ] {
179+ const p_clip = mul_mat4_vec4 ( vp , vec4 ( p [ 0 ] , p [ 1 ] , p [ 2 ] , 1.0 ) ) ;
180+
181+ const ndc_x = p_clip [ 0 ] / p_clip [ 3 ] ;
182+ const ndc_y = p_clip [ 1 ] / p_clip [ 3 ] ;
183+
184+
185+ const screen_x = ( ndc_x + 1.0 ) * width / 2 ;
186+ const screen_y = ( 1.0 - ndc_y ) * height / 2 ;
187+
188+ return [ screen_x , screen_y ] ;
189+
190+ }
151191}
0 commit comments