1%% 2%% wings_menu_util.erl -- 3%% 4%% Menu utilities and helpers. 5%% 6%% Copyright (c) 2002-2011 Bjorn Gustavsson 7%% 8%% See the file "license.terms" for information on usage and redistribution 9%% of this file, and for a DISCLAIMER OF ALL WARRANTIES. 10%% 11%% $Id$ 12%% 13 14-module(wings_menu_util). 15-export([directions/1,directions/2,scale/1,rotate/1,flatten/0,all_xyz/0, 16 crossmark/1]). 17 18-include("wings.hrl"). 19 20directions(#st{selmode=Mode}) -> 21 fun(B, Ns) -> 22 dirs(B, Mode, Ns) 23 end. 24 25dirs(1, Mode, Ns) -> dirs_1(Mode, Ns); 26dirs(2, body, [duplicate|_]) -> {body,duplicate}; 27dirs(2, body, [move|_]) -> ignore; 28dirs(2, body, [move_light|_]) -> ignore; 29dirs(2, face, [extrude|_]) -> {face,{extrude,{faces,{'ASK',{[axis],[]}}}}}; 30dirs(2, face, [extract|_]) -> {face,{extract,{faces,{'ASK',{[axis],[]}}}}}; 31dirs(2, _Mode, Ns) -> 32 case magnet_props(normal, Ns) of 33 [] -> 34 wings_menu:build_command(normal, Ns); 35 Flags -> 36 wings_menu:build_command({'ASK',{[],[normal],Flags}}, Ns) 37 end; 38dirs(3, face, [extrude|_]) -> {face,{extrude,{region,{'ASK',{[axis],[]}}}}}; 39dirs(3, face, [extract|_]) -> {face,{extract,{region,{'ASK',{[axis],[]}}}}}; 40dirs(3, _Mode, Ns) -> 41 Flags = magnet_props(some_axis, Ns), 42 wings_menu:build_command({'ASK',{[axis],[],Flags}}, Ns); 43dirs(help, body, [move|_]) -> 44 {?STR(dirs,1,"Move along std. axis"),[],?STR(dirs,2,"Pick axis to move along")}; 45dirs(help, _Mode, Ns) -> dirs_help(Ns). 46 47dirs_help([move|_]) -> 48 {?STR(dirs,3,"Move along std. axis"), 49 ?STR(dirs,4,"Move along selection's normal"), 50 ?STR(dirs,5,"Pick axis to move along")}; 51dirs_help([extrude,face]) -> 52 {?STR(dirs,6,"Extrude along std. axis"), 53 ?__(18,"Pick axis to extrude each face along"), 54 ?__(19,"Pick axis to extrude each region of faces along")}; 55dirs_help([extrude|_]) -> 56 {?STR(dirs,6,"Extrude along std. axis"), 57 ?STR(dirs,7,"Extrude along selection's normal"), 58 ?STR(dirs,8,"Pick axis to extrude along")}; 59dirs_help([extract|_]) -> 60 {?STR(dirs,12,"Extract along std. axis"), 61 ?__(20,"Pick axis to extract each face along"), 62 ?__(21,"Pick axis to extract each region of faces along")}; 63dirs_help([duplicate|_]) -> 64 {?STR(dirs,15,"Duplicate; move along std. axis"), 65 ?STR(dirs,16,"Duplicate; don't move"), 66 ?STR(dirs,17,"Duplicate; pick axis to move along")}; 67dirs_help([shell_extrude|_]) -> 68 {?STR(dirs,22,"Extract Shell and Extrude along std. axis"), 69 ?STR(dirs,23,"Extract Shell and Extrude along selection's normal"), 70 ?STR(dirs,24,"Pick axis to Extract Shell and Extrude along")}; 71dirs_help(_) -> "". 72 73dirs_1(body, Ns) -> directions([free,x,y,z], Ns); 74dirs_1(_, Ns) -> 75 directions([normal,free,x,y,z], Ns). 76 77all_xyz() -> 78 [{wings_s:dir(all),all}, 79 {wings_s:dir(x),x}, 80 {wings_s:dir(y),y}, 81 {wings_s:dir(z),z}]. 82 83%%% 84%%% Scale sub-menu. 85%%% 86 87scale(#st{selmode=body}) -> adv_scale_1([]); 88scale(_) -> adv_scale_1([magnet]). 89 90adv_scale_1(MagFlags) -> 91 [{?STR(adv_scale_1,1,"Scale Uniform"),{scale,fun(B, Ns) -> uniform_scale(B, Ns, MagFlags) end}, 92 [],MagFlags}, 93 {?STR(adv_scale_1,2,"Scale Axis"),{scale,fun(B, Ns) -> scale(B, Ns, [], MagFlags) end}, 94 [],MagFlags}, 95 {?STR(adv_scale_1,3,"Scale Radial"),{scale,fun(B, Ns) -> scale(B, Ns, [radial], MagFlags) end}, 96 [],MagFlags}]. 97 98uniform_scale(help, _, _) -> 99 ChoosePoint = ?STR(uniform_scale,1,"Choose point to scale from"), 100 {?STR(uniform_scale,2,"Scale uniformly from midpoint of selection"),ChoosePoint,ChoosePoint}; 101uniform_scale(1, Ns, Flags) -> 102 wings_menu:build_command({'ASK',{[],[center,uniform],Flags}}, Ns); 103uniform_scale(_, Ns, Flags) -> 104 wings_menu:build_command({'ASK',{[point],[],Flags}}, Ns). 105 106scale(help, _, [radial],_) -> 107 {?STR(scale,1,"Scale outward from std. axis"), 108 ?STR(scale,2,"Pick axis and point to scale from"), 109 ?STR(scale,3,"Pick axis to scale out from")}; 110scale(help, _, [], _) -> 111 {?STR(scale,4,"Scale along std. axis"), 112 ?STR(scale,5,"Pick axis and point to scale from"), 113 ?STR(scale,6,"Pick axis to scale along")}; 114scale(1, Ns, Flags, _MagFlags) -> 115 [scale_fun(x, Ns, Flags), 116 scale_fun(y, Ns, Flags), 117 scale_fun(z, Ns, Flags), 118 separator, 119 scale_fun(last_axis, Ns, Flags), 120 scale_fun(default_axis, Ns, Flags)]; 121scale(2, Ns, Flags, MagFlags) -> 122 wings_menu:build_command({'ASK',{[axis,point],Flags,MagFlags}}, Ns); 123scale(3, Ns, Flags, MagFlags) -> 124 wings_menu:build_command({'ASK',{[axis_point],Flags,MagFlags}}, Ns). 125 126scale_fun(Dir, Names, [radial]) -> 127 scale_fun({radial,Dir}, Names, []); 128scale_fun(Dir, Names, _Flags) -> 129 DirString = wings_s:dir(Dir), 130 F = magnet_scale_rot_fun(Dir, center), 131 Help0 = dir_help(Dir, Names), 132 Help = {Help0,[],?STR(scale_fun,1,"Pick point to scale from")}, 133 {DirString,F,Help,magnet_props(Dir, Names)}. 134 135 136 137%%% 138%%% Rotate sub-menu. 139%%% 140 141rotate(#st{selmode=body}) -> rotate_1([]); 142rotate(_) -> rotate_1([magnet]). 143 144rotate_1(Flags) -> 145 {?STR(rotate_1,1,"Rotate"),{rotate,fun rotate/2},[],Flags}. 146 147rotate(help, _) -> 148 {?STR(rotate,1,"Rotate around std. axis"), 149 ?STR(rotate,2,"Pick axis and ref point"), 150 ?STR(rotate,3,"Pick axis to rotate around")}; 151rotate(1, [rotate,Mode]=Ns) when Mode == vertex; Mode == body -> 152 rotate_common(Ns); 153rotate(1, Ns) -> 154 [rotate_fun(normal, Ns)|rotate_common(Ns)]; 155rotate(2, Ns) -> 156 MagFlags = magnet_props(any, Ns), 157 wings_menu:build_command({'ASK',{[axis,point],[],MagFlags}}, Ns); 158rotate(3, Ns) -> 159 MagFlags = magnet_props(any, Ns), 160 wings_menu:build_command({'ASK',{[axis_point],[],MagFlags}}, Ns). 161 162rotate_common(Ns) -> 163 164 [ 165 rotate_fun(free,Ns), 166 rotate_fun(x, Ns), 167 rotate_fun(y, Ns), 168 rotate_fun(z, Ns), 169 separator, 170 rotate_fun(last_axis, Ns), 171 rotate_fun(default_axis, Ns) 172 ]. 173 174rotate_fun(Dir, Names) -> 175 DirString = wings_util:cap(wings_s:dir(Dir)), 176 F = magnet_scale_rot_fun(Dir, center), 177 Help0 = dir_help(Dir, Names), 178 Help = {Help0, ?STR(rotate_fun,2,"Through Origin"), ?STR(rotate_fun,1,"Pick point for axis to pass through")}, 179 Ps = magnet_props(Dir, Names), 180 {DirString,F,Help,Ps}. 181 182magnet_scale_rot_fun(Vec, Point) -> 183 fun(1, Ns) -> 184 MagFlags = magnet_props(Vec, Ns), 185 wings_menu:build_command({'ASK',{[],[Point,Vec],MagFlags}}, Ns); 186 (2, Ns) -> 187 {Vec1,Point1} = 188 case Vec of 189 x -> {{1.0,0.0,0.0},{0.0,0.0,0.0}}; 190 y -> {{0.0,1.0,0.0},{0.0,0.0,0.0}}; 191 z -> {{0.0,0.0,1.0},{0.0,0.0,0.0}}; 192 _Other -> {_Other,{0.0,0.0,0.0}} 193 end, 194 MagFlags = magnet_props(Vec1, Ns), 195 wings_menu:build_command({'ASK',{[],[Point1,Vec1],MagFlags}}, Ns); 196 (3, Ns) -> 197 MagFlags = magnet_props(Vec, Ns), 198 wings_menu:build_command({'ASK',{[point],[Vec],MagFlags}}, Ns) 199 end. 200 201%%% 202%%% Flatten submenu. 203%%% 204 205flatten() -> 206 {?STR(flatten,1,"Flatten"),{flatten,fun flatten/2}}. 207 208flatten(help, _) -> 209 {?STR(flatten,2,"Flatten to std. planes"), 210 ?STR(flatten,3,"Pick plane and ref point on plane"), 211 ?STR(flatten,4,"Pick plane")}; 212flatten(1, [flatten,vertex]) -> 213 %% Vertex mode flatten. 214 flatten_common(); 215flatten(1, [flatten,edge]) -> 216 %% Edge mode flatten. 217 [flatten_common()|flatten_edge_loops()]; 218flatten(1, _) -> 219 %% Face mode flatten. 220 [flatten_fun(normal)|flatten_common()]; 221flatten(2, Ns) -> 222 wings_menu:build_command({'ASK',{[axis,point],[],[]}}, Ns); 223flatten(3, Ns) -> 224 wings_menu:build_command({'ASK',{[axis],[],[]}}, Ns). 225 226flatten_common() -> 227 [flatten_fun(x), 228 flatten_fun(y), 229 flatten_fun(z), 230 separator, 231 flatten_fun(last_axis), 232 flatten_fun(default_axis)]. 233 234flatten_fun(Vec) -> 235 flatten_fun_1(Vec, Vec, wings_util:cap(wings_s:dir(Vec))). 236 237flatten_fun_1(Vec, Axis, String) -> 238 F = fun(1, Ns) -> 239 wings_menu:build_command(Vec, Ns); 240 (2, _Ns) -> 241 ignore; 242 (3, Ns) -> 243 wings_menu:build_command({'ASK',{[point],[Vec]}}, Ns) 244 end, 245 Help0 = dir_help(Axis, [flatten]), 246 Help = {Help0,[],?STR(flatten_fun_1,1,"Pick point on plane")}, 247 {String,F,Help,[]}. 248 249flatten_edge_loops() -> 250 [separator, 251 {?__(1,"Edge Loops"),edge_loop, 252 ?__(2,"Flatten each closed edge loop to its normal")}]. 253 254%%% 255%%% General directions. 256%%% 257 258directions([D|Dirs], Ns) -> 259 [direction(D, Ns)|directions(Dirs, Ns)]; 260directions([], Ns) -> 261 [separator, 262 direction(last_axis, Ns), 263 direction(default_axis, Ns)]. 264 265direction(Dir, [extrude,face]) -> 266 Str = wings_util:cap(wings_s:dir(Dir)), 267 Help = {dir_help(Dir, [extrude_region]),[],dir_help(Dir, [extrude])}, 268 F = fun 269 (1,_Ns) -> {face,{extrude,{region,Dir}}}; 270 (3,_Ns) -> {face,{extrude,{faces,Dir}}}; 271 (_, _) -> ignore 272 end, 273 {Str,F,Help,[]}; 274direction(Dir, [extract,face]) -> 275 Str = wings_util:cap(wings_s:dir(Dir)), 276 Help = {dir_help(Dir, [extract_region]),[],dir_help(Dir, [extract])}, 277 F = fun 278 (1,_Ns) -> {face,{extract,{region,Dir}}}; 279 (3,_Ns) -> {face,{extract,{faces,Dir}}}; 280 (_, _) -> ignore 281 end, 282 {Str,F,Help,[]}; 283direction(Dir, Ns) -> 284 Str = wings_util:cap(wings_s:dir(Dir)), 285 Help = dir_help(Dir, Ns), 286 Ps = magnet_props(Dir, Ns), 287 {Str,Dir,Help,Ps}. 288 289magnet_props(normal, [rotate|_]) -> []; 290magnet_props(_, [_,body]) -> []; 291magnet_props(_, [move|_]) -> [magnet]; 292magnet_props(_, [scale|_]) -> [magnet]; 293magnet_props(_, [rotate|_]) -> [magnet]; 294magnet_props(_, _) -> []. 295 296dir_help(Axis, Ns) when Axis == x; Axis == y; Axis == z -> 297 dir_help_1(Ns, wings_s:dir_axis(Axis)); 298dir_help(last_axis, Ns) -> 299 dir_help_1(Ns, ?STR(dir_help,3,"the last axis")); 300dir_help(default_axis, Ns) -> 301 dir_help_1(Ns, ?STR(dir_help,4,"the default axis")); 302dir_help({radial,Axis}, Ns) -> 303 dir_help_1(Ns, [around|wings_s:dir_axis(Axis)]); 304dir_help(radial_x, Ns) -> 305 dir_help_1(Ns, [around|?STR(dir_help,7,"around") ++ " " ++ wings_s:dir_axis(x)]); 306dir_help(radial_y, Ns) -> 307 dir_help_1(Ns, [around|?STR(dir_help,7,"around") ++ " " ++ wings_s:dir_axis(y)]); 308dir_help(radial_z, Ns) -> 309 dir_help_1(Ns, [around|?STR(dir_help,7,"around") ++ " " ++ wings_s:dir_axis(z)]); 310dir_help(normal, Ns) -> 311 dir_help_1(Ns, [normal|?STR(dir_help,10,"along its normal")]); 312dir_help(free, Ns) -> 313 dir_help_1(Ns, [free|?STR(dir_help,11,"freely in all directions")]); 314dir_help(uniform, [scale|_]) -> 315 ?STR(dir_help,12,"Scale equally in all directions"). 316 317%% Normal/Free. 318dir_help_1([move|_], [NF|Text]) when NF == normal; NF == free -> 319 ?STR(dir_help_1,1,"Move each element ") ++ Text; 320dir_help_1([rotate|_], [free|_Text]) -> 321 ?STR(dir_help_1,2,"Rotate freely"); 322dir_help_1([rotate|_], [normal|_Text]) -> 323 ?STR(dir_help_1,3,"Rotate around each element's normal"); 324dir_help_1([extrude|_], [NF|Text]) when NF == normal; NF == free -> 325 ?STR(dir_help_1,4,"Extrude each element, then move it ")++ Text; 326dir_help_1([extract|_], [NF|Text]) when NF == normal; NF == free -> 327 ?__(24,"Extract each element, then move it ")++ Text; 328dir_help_1([extrude_region|_], [normal|_]) -> 329 ?STR(dir_help_1,5,"Extrude faces as region, then move faces along the region's normal"); 330dir_help_1([extrude_region|_], [free|Text]) -> 331 ?STR(dir_help_1,6,"Extrude faces as region, then move faces ") ++ Text; 332dir_help_1([extract_region|_], [normal|_]) -> 333 ?STR(dir_help_1,7,"Extract faces, then move faces along the region's normal"); 334dir_help_1([extract_region|_], [free|Text]) -> 335 ?STR(dir_help_1,8,"Extract faces, then move faces ") ++ Text; 336dir_help_1([flatten|_], [normal|_Text]) -> 337 ?STR(dir_help_1,9,"Flatten elements to normal plane"); 338dir_help_1([lift|_], [normal|_]) -> 339 ?STR(dir_help_1,10,"Lift face along its normal"); 340dir_help_1([lift|_], [free|Text]) -> 341 ?STR(dir_help_1,11,"Lift face and move it ") ++ Text; 342dir_help_1([duplicate|_], [free|Text]) -> 343 ?STR(dir_help_1,12,"Duplicate and move freely ")++ Text; 344dir_help_1([shell_extrude|_], [normal|_]) -> 345 ?STR(dir_help_1,27,"Extract and Extrude faces as region, then move faces along the region's normal"); 346dir_help_1([shell_extrude|_], [free|Text]) -> 347 ?STR(dir_help_1,28,"Extract and Extrude faces as region, then move faces ") ++ Text; 348 349%% Axis 350dir_help_1([move|_], Text) -> 351 ?STR(dir_help_1,13,"Move each element along ") ++ Text; 352dir_help_1([extrude|_], Text) -> 353 ?STR(dir_help_1,14,"Extrude elements, then move along ") ++ Text; 354dir_help_1([extract|_], Text) -> 355 ?__(25,"Extract elements, then move along ") ++ Text; 356dir_help_1([extrude_region|_], Text) -> 357 ?STR(dir_help_1,15,"Extrude faces as region, then move along ") ++ Text; 358dir_help_1([extract_region|_], Text) -> 359 ?STR(dir_help_1,16,"Extract faces, then move along ") ++ Text; 360dir_help_1([rotate|_], Text) -> 361 ?STR(dir_help_1,17,"Rotate around ") ++ Text; 362dir_help_1([scale|_], [around|Text]) -> 363 ?STR(dir_help_1,18,"Scale ") ++ Text; 364dir_help_1([scale|_], Text) -> 365 ?STR(dir_help_1,19,"Scale along ")++ Text; 366dir_help_1([flatten|_], Text) -> 367 ?STR(dir_help_1,20,"Flatten to ")++ Text; 368dir_help_1([flatten_move|_], Text) -> 369 ?STR(dir_help_1,21,"Flatten and move to ") ++ Text; 370dir_help_1([lift|_], Text) -> 371 ?STR(dir_help_1,22,"Lift face along ")++ Text; 372dir_help_1([duplicate|_], Text) -> 373 ?STR(dir_help_1,23,"Duplicate, then move along ")++ Text; 374dir_help_1([shell_extrude|_], Text) -> 375 ?STR(dir_help_1,26,"Extract and Extrude faces as region, then move along ") ++ Text; 376dir_help_1(_, _) -> "". 377 378%% Menu checkmark 379crossmark(Key) -> 380 Val = case wings_pref:get_value(Key) of 381 undefined -> 382 case wings_wm:this() of 383 Client = {autouv, _} -> 384 wings_wm:get_prop(Client, Key); 385 {_,Client} -> 386 wings_wm:get_prop(Client, Key); 387 Client when is_atom(Client) -> % Client is 'geom' when updating from wings_pref_dlg 388 wings_wm:get_prop(Client, Key) 389 end; 390 Other -> Other 391 end, 392 [{crossmark, Val}]. 393