diff --git a/release/scripts/object_drop.py b/release/scripts/object_drop.py index f4803e62d98..19cc1f8d15a 100644 --- a/release/scripts/object_drop.py +++ b/release/scripts/object_drop.py @@ -1,13 +1,13 @@ #!BPY """ Name: 'Drop Onto Ground' -Blender: 245 +Blender: 249 Group: 'Object' Tooltip: 'Drop the selected objects onto "ground" objects' """ __author__= "Campbell Barton" __url__= ["blender.org", "blenderartists.org"] -__version__= "1.0" +__version__= "1.1" __bpydoc__= """ """ @@ -36,6 +36,7 @@ __bpydoc__= """ from Blender import Draw, Geometry, Mathutils, Window +from Blender.Mathutils import Vector, AngleBetweenVecs, RotationMatrix import bpy @@ -44,6 +45,8 @@ GLOBALS['GROUND_SOURCE'] = [Draw.Create(1), Draw.Create(0)] GLOBALS['GROUND_GROUP_NAME'] = Draw.Create('terrain') GLOBALS['DROP_AXIS'] = [Draw.Create(1), Draw.Create(0)] # on what axis will we drop? GLOBALS['DROP_OVERLAP_CHECK'] = Draw.Create(1) # is the terrain a single skin? +GLOBALS['DROP_ORIENT'] = Draw.Create(1) +GLOBALS['DROP_ORIENT_VALUE'] = Draw.Create(100.0) GLOBALS['EVENT'] = 2 GLOBALS['MOUSE'] = None @@ -52,19 +55,18 @@ def collect_terrain_triangles(obs_terrain): me = bpy.data.meshes.new() for ob in obs_terrain: - # this matrix takes the object and drop matrix into account - ob_mat = ob.matrixWorld # * drop_matrix - def blend_face_to_terrain_tris(f): - cos = [v.co*ob_mat for v in f] - if len(cos) == 4: return [(cos[0], cos[1], cos[2]), (cos[0], cos[2], cos[3])] - else: return [(cos[0], cos[1], cos[2]), ] + no = f.no + cos = [v.co for v in f] + if len(cos) == 4: return [(cos[0], cos[1], cos[2], no), (cos[0], cos[2], cos[3], no)] + else: return [(cos[0], cos[1], cos[2], no), ] # Clear me.verts = None try: me.getFromObject(ob) except: pass + me.transform(ob.matrixWorld) for f in me.faces: # may be [], thats ok terrain_tris.extend( blend_face_to_terrain_tris(f) ) @@ -72,30 +74,34 @@ def collect_terrain_triangles(obs_terrain): return terrain_tris def calc_drop_loc(ob, terrain_tris, axis): - pt = Mathutils.Vector(ob.loc) + pt = Vector(ob.loc) isect = None isect_best = None + isect_best_no = None isect_best_len = 0.0 - for t1,t2,t3 in terrain_tris: + for t1,t2,t3, no in terrain_tris: #if Geometry.PointInTriangle2D(pt, t1,t2,t3): isect = Mathutils.Intersect(t1, t2, t3, axis, pt, 1) # 1==clip if isect: if not GLOBALS['DROP_OVERLAP_CHECK'].val: # Find the first location - return isect + return isect, no else: if isect_best: isect_len = (pt-isect).length if isect_len < isect_best_len: isect_best_len = isect_len isect_best = isect + isect_best_no = no else: isect_best_len = (pt-isect).length isect_best = isect; - return isect_best + isect_best_no = no + + return isect_best, isect_best_no def error_nogroup(): @@ -135,13 +141,28 @@ def terrain_clamp(event, value): if GLOBALS['DROP_AXIS'][0].val: - axis = Mathutils.Vector(0,0,-1) + axis = Vector(0,0,-1) else: - axis = Mathutils.Vector(Window.GetViewVector()) + axis = Vector(Window.GetViewVector()) + + do_orient = GLOBALS['DROP_ORIENT'].val + do_orient_val = GLOBALS['DROP_ORIENT_VALUE'].val/100.0 + if not do_orient_val: do_orient = False for ob in obs_clamp: - loc = calc_drop_loc(ob, terrain_tris, axis) + loc, no = calc_drop_loc(ob, terrain_tris, axis) if loc: + if do_orient: + try: ang = AngleBetweenVecs(no, axis) + except:ang = 0.0 + if ang > 90.0: + no = -no + ang = 180.0-ang + + if ang > 0.0001: + ob_matrix = ob.matrixWorld * RotationMatrix(ang * do_orient_val, 4, 'r', axis.cross(no)) + ob.setMatrix(ob_matrix) + ob.loc = loc # to make the while loop exist @@ -175,7 +196,8 @@ def do_ground_group_name(e,v): if not g: error_nogroup() GLOBALS['EVENT'] = e - +def do_dummy(e,v): + GLOBALS['EVENT'] = e EVENT_NONE = 0 EVENT_EXIT = 1 @@ -185,7 +207,7 @@ def terain_clamp_ui(): # Only to center the UI x,y = GLOBALS['MOUSE'] x-=40 - y-=60 + y-=70 Draw.Label('Drop Axis', x-70,y+120, 60, 20) Draw.BeginAlign() @@ -204,7 +226,13 @@ def terain_clamp_ui(): GLOBALS['DROP_OVERLAP_CHECK'] = Draw.Toggle('Overlapping Terrain', EVENT_NONE, x-70, y+20, 190, 20, GLOBALS['DROP_OVERLAP_CHECK'].val, "Check all terrain triangles and use the top most (slow)") - Draw.PushButton('Drop Objects', EVENT_EXIT, x+20, y-10, 100, 20, 'Drop the selected objects', terrain_clamp) + Draw.BeginAlign() + GLOBALS['DROP_ORIENT'] = Draw.Toggle('Orient Normal', EVENT_REDRAW, x-70, y-10, 110, 20, GLOBALS['DROP_ORIENT'].val, "Rotate objects to the face normal", do_dummy) + if GLOBALS['DROP_ORIENT'].val: + GLOBALS['DROP_ORIENT_VALUE'] = Draw.Number('', EVENT_NONE, x+40, y-10, 80, 20, GLOBALS['DROP_ORIENT_VALUE'].val, 0.0, 100.0, "Percentage to orient 0.0 - 100.0") + Draw.EndAlign() + + Draw.PushButton('Drop Objects', EVENT_EXIT, x+20, y-40, 100, 20, 'Drop the selected objects', terrain_clamp) # So moving the mouse outside the popup exits the while loop GLOBALS['EVENT'] = EVENT_EXIT diff --git a/source/blender/src/buttons_logic.c b/source/blender/src/buttons_logic.c index 25bed178130..a1fddfefb9c 100644 --- a/source/blender/src/buttons_logic.c +++ b/source/blender/src/buttons_logic.c @@ -1603,12 +1603,12 @@ static short draw_controllerbuttons(bController *cont, uiBlock *block, short xco uiBlockBeginAlign(block); - uiDefButI(block, MENU, B_REDR, "Execution Method%t|Script%x0|Module%x1", xco+24,yco-24, 66, 19, &pc->mode, 0, 0, 0, 0, "Python script type (textblock or module - faster)"); + uiDefButI(block, MENU, B_REDR, "Execution Method%t|Script%x0|Module%x1", xco+4,yco-23, 66, 19, &pc->mode, 0, 0, 0, 0, "Python script type (textblock or module - faster)"); if(pc->mode==0) - uiDefIDPoinBut(block, test_scriptpoin_but, ID_SCRIPT, 1, "", xco+90,yco-24,width-90, 19, &pc->text, "Blender textblock to run as a script"); + uiDefIDPoinBut(block, test_scriptpoin_but, ID_SCRIPT, 1, "", xco+70,yco-23,width-74, 19, &pc->text, "Blender textblock to run as a script"); else { - uiDefBut(block, TEX, 1, "", xco+90,yco-24,(width-90)-25, 19, pc->module, 0, 63, 0, 0, "Module name and function to run e.g. \"someModule.main\". Internal texts and external python files can be used"); - uiDefButBitI(block, TOG, CONT_PY_DEBUG, B_REDR, "D", (xco+width)-25, yco-24, 19, 19, &pc->flag, 0, 0, 0, 0, "Continuously reload the module from disk for editing external modules without restarting"); + uiDefBut(block, TEX, 1, "", xco+70,yco-23,(width-70)-25, 19, pc->module, 0, 63, 0, 0, "Module name and function to run e.g. \"someModule.main\". Internal texts and external python files can be used"); + uiDefButBitI(block, TOG, CONT_PY_DEBUG, B_REDR, "D", (xco+width)-25, yco-23, 19, 19, &pc->flag, 0, 0, 0, 0, "Continuously reload the module from disk for editing external modules without restarting"); } uiBlockEndAlign(block); @@ -2748,19 +2748,19 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh if(parAct->type==ACT_PARENT_SET) { - ysize= 68; + ysize= 48; glRects(xco, yco-ysize, xco+width, yco); uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - uiDefIDPoinBut(block, test_obpoin_but, ID_OB, 1, "OB:", xco+40, yco-44, (width-80), 19, &(parAct->ob), "Set this object as parent"); + uiDefIDPoinBut(block, test_obpoin_but, ID_OB, 1, "OB:", xco+95, yco-24, (width-100), 19, &(parAct->ob), "Set this object as parent"); uiBlockBeginAlign(block); uiDefButBitS(block, TOGN, ACT_PARENT_COMPOUND, B_REDR, "Compound", - xco + 40, yco - 64, (width - 80)/2, 19, &parAct->flag, + xco + 5, yco - 44, (width - 10)/2, 19, &parAct->flag, 0.0, 0.0, 0, 0, "Add this object shape to the parent shape (only if the parent shape is already compound)"); uiDefButBitS(block, TOGN, ACT_PARENT_GHOST, B_REDR, "Ghost", - xco + 40 + ((width - 80)/2), yco - 64, (width - 80)/2, 19, &parAct->flag, + xco + 5 + ((width - 10)/2), yco - 44, (width - 10)/2, 19, &parAct->flag, 0.0, 0.0, 0, 0, "Make this object ghost while parented (only if not compound)"); uiBlockEndAlign(block); @@ -2773,7 +2773,7 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh } str= "Parent %t|Set Parent %x0|Remove Parent %x1"; - uiDefButI(block, MENU, B_REDR, str, xco+40, yco-24, (width-80), 19, &parAct->type, 0.0, 0.0, 0, 0, ""); + uiDefButI(block, MENU, B_REDR, str, xco+5, yco-24, parAct->type==1?(width-80):90, 19, &parAct->type, 0.0, 0.0, 0, 0, ""); yco-= ysize; break;