BProjection: code clean up (a littel), add short cut for clean plane rotation and...
[blender-addons-contrib.git] / space_view3d_paint_bprojection.py
1 bl_info = {
2     "name": "BProjection",
3     "description": "Help Clone tool",
4     "author": "kgeogeo",
5     "version": (1, 0),
6     "blender": (2, 6, 3),
7     "category": "Paint"}
8
9 import bpy
10 from bpy.types import Panel, Operator
11 from bpy.props import IntProperty, FloatProperty, BoolProperty, IntVectorProperty, StringProperty
12 from bpy_extras import view3d_utils
13 import math
14 from math import *
15 import mathutils
16 from mathutils import * 
17
18 # Main function for align the plan to view
19 def align_to_view(context):
20     ob = context.object        
21     rotation = ob.custom_rotation
22     scale = ob.custom_scale
23     z = ob.custom_z
24     posx = ob.custom_location[0]
25     posy = ob.custom_location[1]
26
27     reg = bpy.context.area.regions[4]        
28     width = reg.width
29     height = reg.height 
30         
31     r3d =  context.space_data.region_3d        
32     r3d.update()
33     vl = r3d.view_location
34     vr = r3d.view_rotation
35     quat = mathutils.Quaternion((0.0, 0.0, 1.0), math.radians(float(rotation)))
36         
37     v = Vector((1,0,z))
38     v.rotate(vr)
39
40     pos = (posx,posy) 
41
42     em = bpy.data.objects['Empty for BProjection']
43     img = bpy.data.textures['Texture for BProjection'].image
44     if img and img.size[1] != 0:
45         prop = img.size[0]/img.size[1]
46         em.scale[0] = prop
47     else: prop = 1    
48         
49     em.scale =  Vector((prop*scale, scale, scale))
50     em.location = view3d_utils.region_2d_to_location_3d(context.area.regions[4], r3d, pos, v)        
51     em.rotation_euler = Quaternion.to_euler(vr*quat)
52
53 # Function to update the properties
54 def update_props(self, context):          
55     v = Vector((0.5,0.5))
56     for i in range(4):
57         vres =  v - bpy.context.object.data.uv_loop_layers.active.data[len(bpy.context.object.data.uv_loop_layers.active.data)-1-i].uv 
58         vres /= vres.length
59         for j in range(2):
60             if abs(vres[j-1])>0:
61                 vres[j-1] /= abs(vres[j-1])
62         bpy.context.object.data.uv_loop_layers.active.data[len(bpy.context.object.data.uv_loop_layers.active.data)-1-i].uv = v - vres*bpy.context.object.custom_scaleuv/2
63     
64     align_to_view(context)
65
66 # Function to create custom properties
67 def createcustomprops():
68     Ob = bpy.types.Object    
69     Ob.custom_rotation = IntProperty(name="Rotation", description="Rotate the plane", min=-180, max=180, default=0,update = update_props)
70     Ob.custom_scale = FloatProperty(name="Scale", description="Scale the plane", min=0, max=10, default=1.0,update = update_props)
71     Ob.custom_z = FloatProperty(name="Z", description="Z axis for the plane", min=-10, max=10, default=-1.0,update = update_props)
72     Ob.custom_scaleuv = FloatProperty(name="ScaleUV", description="Scale the texture's UV", min=1.0, max=10, default=1.0,update = update_props)
73     Ob.custom_location = IntVectorProperty(name="Location", description="Location of the plan", default=(0, 0), subtype = 'XYZ', size=2, update = update_props)
74     Ob.custom_c3d = BoolProperty(name="c3d", default=True)
75     Ob.custom_rot = BoolProperty(name="rot", default=True)
76
77 # Draw Class to show the panel
78 class BProjection(Panel):
79     bl_space_type = 'VIEW_3D'
80     bl_region_type = 'UI'
81     bl_label = "BProjection"
82
83     @classmethod
84     def poll(cls, context):
85         return (context.image_paint_object)
86
87     def draw(self, context):        
88         layout = self.layout
89                 
90         try: 
91             bpy.data.objects['Empty for BProjection']
92
93             col = layout.column(align =True)
94             col.operator("object.removebprojectionplane", text="Remove BProjection plane")
95         
96             tex = bpy.data.textures['Texture for BProjection']
97
98             layout.template_ID_preview(tex, "image", open="image.open", rows=3, cols=3)
99         
100             col = layout.column(align =True)
101             col.operator('object.applyimage', text = "Apply image")
102             col = layout.column(align =True)
103             ob = context.object
104             col.prop(ob, "custom_c3d",text="Capture Cursor3d")
105             col.prop(ob, "custom_rot",text="Rotate around selection")
106             col = layout.column(align =True)
107             col.prop(ob,'custom_rotation')
108             col.prop(ob,'custom_scale') 
109             col.prop(ob,'custom_z') 
110             col.prop(ob,'custom_location')
111             col = layout.column(align =True)
112             col.prop(ob,'custom_scaleuv', slider = True)
113             col = layout.column(align =True)
114             col.prop(ob.material_slots['Material for BProjection'].material,'alpha', slider = True)
115
116         except:
117             col = layout.column(align =True)
118             col.operator("object.addbprojectionplane", text="Add BProjection plan")             
119
120 # Oprerator Class to apply the image to the plane             
121 class ApplyImage(Operator):
122     bl_idname = "object.applyimage"
123     bl_label = "Apply image"
124
125     def execute(self, context):        
126         img = bpy.data.textures['Texture for BProjection'].image
127         em = bpy.data.objects['Empty for BProjection']
128         uvdata = bpy.context.object.data.uv_textures.active.data        
129         uvdata[len(uvdata)-1].image = img
130         if img and img.size[1] != 0:        
131             prop = img.size[0]/img.size[1]                
132             em.scale[0] = prop
133             
134         context.object.data.update()
135         align_to_view(context)
136         
137         return {'FINISHED'}
138
139 # Oprerator Class to make the 4 point and scale the plan
140 class ScalePlane(Operator):
141     bl_idname = "object.scaleplane"
142     bl_label = "Draw lines"
143
144     def invoke(self, context, event):
145         
146         x = event.mouse_region_x
147         y = event.mouse_region_y                
148         if len(bpy.context.object.grease_pencil.layers.active.frames)==0: 
149             bpy.ops.gpencil.draw(mode='DRAW', stroke=[{"name":"", "pen_flip":False,
150                                                                 "is_start":True, "location":(0, 0, 0),
151                                                                 "mouse":(x,y), "pressure":1, "time":0}])
152         else:
153             if len(bpy.context.object.grease_pencil.layers.active.frames[0].strokes) < 4:
154                 bpy.ops.gpencil.draw(mode='DRAW', stroke=[{"name":"", "pen_flip":False,
155                                                                     "is_start":True, "location":(0, 0, 0),
156                                                                     "mouse":(x,y), "pressure":1, "time":0}])
157             if len(bpy.context.object.grease_pencil.layers.active.frames[0].strokes) == 4:
158                 s = bpy.context.object.grease_pencil.layers.active.frames[0]
159                 v1 = s.strokes[1].points[0].co - s.strokes[0].points[0].co
160                 v2 = s.strokes[3].points[0].co - s.strokes[2].points[0].co
161                 prop = v1.x/v2.x
162                 bpy.context.object.custom_scale *= abs(prop)
163                 bpy.ops.gpencil.active_frame_delete()
164         
165         return {'FINISHED'}
166
167 # Oprerator Class to configure all wath is needed
168 class AddBProjectionPlane(Operator):
169     bl_idname = "object.addbprojectionplane"
170     bl_label = "Configure"
171     
172     def creatematerial(self, context):        
173         try:
174             matBProjection = bpy.data.materials['Material for BProjection']
175         except:            
176             bpy.data.textures.new(name='Texture for BProjection',type='IMAGE')
177     
178             bpy.data.materials.new(name='Material for BProjection')
179             
180             matBProjection = bpy.data.materials['Material for BProjection']
181             matBProjection.texture_slots.add()
182             matBProjection.use_shadeless = True
183             matBProjection.use_transparency = True
184             matBProjection.active_texture = bpy.data.textures['Texture for BProjection']
185         
186             index = matBProjection.active_texture_index
187             matBProjection.texture_slots[index].texture_coords = 'UV'
188      
189         old_index = context.object.active_material_index
190         bpy.ops.object.material_slot_add()
191         index = context.object.active_material_index
192         bpy.context.object.material_slots[index].material = bpy.data.materials['Material for BProjection']
193         bpy.ops.object.material_slot_assign()
194         context.object.active_material_index = old_index
195             
196     def execute(self, context):    
197         try:
198             bpy.data.objects['Empty for BProjection']
199
200         except:            
201             bpy.ops.paint.texture_paint_toggle()
202             
203             bpy.context.space_data.show_relationship_lines = False
204             
205             ob = bpy.context.object
206         
207             bpy.ops.object.add()
208             em = bpy.context.object
209             em.name = "Empty for BProjection"
210                         
211             bpy.data.scenes['Scene'].objects.active = ob
212             ob.select = True
213     
214             bpy.ops.object.editmode_toggle()
215     
216             bpy.ops.mesh.primitive_plane_add()
217             bpy.ops.object.vertex_group_assign(new = True)
218             ob.vertex_groups.active.name = 'texture plane'   
219             bpy.ops.uv.unwrap()
220             
221             bpy.ops.object.editmode_toggle()
222             for i in range(4):
223                 ob.data.edges[len(ob.data.edges)-1-i].crease = 1
224             bpy.ops.object.editmode_toggle()
225     
226             em.select = True
227             bpy.ops.object.hook_add_selob()
228             
229             self.creatematerial(context)
230             
231             bpy.ops.gpencil.data_add()
232             bpy.context.object.grease_pencil.draw_mode = 'VIEW'
233             bpy.ops.gpencil.layer_add()
234             bpy.context.object.grease_pencil.layers.active.color = [1.0,0,0]
235
236             bpy.ops.mesh.hide()
237             
238             em.select = False
239             em.hide = True
240             
241             bpy.ops.object.editmode_toggle()
242                     
243             bpy.ops.object.applyimage()
244             km = bpy.data.window_managers['WinMan'].keyconfigs['Blender'].keymaps['3D View']
245             km.keymap_items[3-1].idname = 'view3d.rotate_view3d'
246             km.keymap_items[19-1].idname = 'view3d.zoom_view3d'
247             km.keymap_items[19-1].properties.delta = 1.0
248             km.keymap_items[20-1].idname = 'view3d.zoom_view3d'
249             km.keymap_items[20-1].properties.delta = -1.0
250             km.keymap_items[4-1].idname = 'view3d.pan_view3d'
251             km.keymap_items[26-1].idname = 'view3d.preset_view3d'
252             km.keymap_items[26-1].properties.view = 'FRONT'
253             km.keymap_items[28-1].idname = 'view3d.preset_view3d'
254             km.keymap_items[28-1].properties.view = 'RIGHT'            
255             km.keymap_items[32-1].idname = 'view3d.preset_view3d'
256             km.keymap_items[32-1].properties.view = 'TOP'
257             km.keymap_items[34-1].idname = 'view3d.preset_view3d'
258             km.keymap_items[34-1].properties.view = 'BACK'
259             km.keymap_items[35-1].idname = 'view3d.preset_view3d'
260             km.keymap_items[35-1].properties.view = 'LEFT'            
261             km.keymap_items[36-1].idname = 'view3d.preset_view3d'
262             km.keymap_items[36-1].properties.view = 'BOTTOM'                                   
263             km = bpy.context.window_manager.keyconfigs.default.keymaps['Image Paint']
264             kmi = km.keymap_items.new("object.scaleplane", 'LEFTMOUSE', 'PRESS', shift=True)
265                         
266             align_to_view(context)
267             
268             bpy.ops.paint.texture_paint_toggle()
269             
270         return {'FINISHED'}
271
272 # Oprerator Class to remove what is no more needed    
273 class RemoveBProjectionPlane(Operator):
274     bl_idname = "object.removebprojectionplane"
275     bl_label = "Configure"
276
277     def removematerial(self, context):
278         i = 0
279         for ms in context.object.material_slots:
280             if ms.name == 'Material for BProjection':
281                 index = i
282             i+=1
283                 
284         context.object.active_material_index = index
285         bpy.ops.object.material_slot_remove()
286     
287     def execute(self, context):
288         try:               
289             bpy.ops.paint.texture_paint_toggle()
290             
291             context.space_data.show_relationship_lines = True
292             
293             bpy.ops.object.modifier_remove(modifier="Hook-Empty for BProjection")
294             
295             self.removematerial(context)
296
297             ob = bpy.context.object
298     
299             bpy.ops.object.editmode_toggle()
300     
301             bpy.ops.mesh.reveal()
302                                    
303             bpy.ops.mesh.select_all()
304             bpy.ops.object.editmode_toggle() 
305             if ob.data.vertices[0].select:
306                 bpy.ops.object.editmode_toggle()
307                 bpy.ops.mesh.select_all()
308                 bpy.ops.object.editmode_toggle()
309             bpy.ops.object.editmode_toggle()                    
310             
311             ob.vertex_groups.active.name = 'texture plane'
312             bpy.ops.object.vertex_group_select()
313             bpy.ops.mesh.delete()
314             bpy.ops.object.vertex_group_remove()
315     
316             bpy.ops.object.editmode_toggle()
317    
318             ob.select = False
319                 
320             em = bpy.data.objects['Empty for BProjection']
321             bpy.data.scenes['Scene'].objects.active = em
322             em.hide = False
323             em.select = True
324             bpy.ops.object.delete()
325     
326             bpy.data.scenes['Scene'].objects.active = ob
327             ob.select = True
328             
329             km = bpy.data.window_managers['WinMan'].keyconfigs['Blender'].keymaps['3D View']
330             km.keymap_items[3-1].idname = 'view3d.rotate'
331             km.keymap_items[19-1].idname = 'view3d.zoom'
332             km.keymap_items[19-1].properties.delta = 1.0
333             km.keymap_items[20-1].idname = 'view3d.zoom'
334             km.keymap_items[20-1].properties.delta = -1.0
335             km.keymap_items[4-1].idname = 'view3d.move'
336             km.keymap_items[26-1].idname = 'view3d.viewnumpad'
337             km.keymap_items[26-1].properties.type = 'FRONT'
338             km.keymap_items[28-1].idname = 'view3d.viewnumpad'
339             km.keymap_items[28-1].properties.type = 'RIGHT'            
340             km.keymap_items[32-1].idname = 'view3d.viewnumpad'
341             km.keymap_items[32-1].properties.type = 'TOP'
342             km.keymap_items[34-1].idname = 'view3d.viewnumpad'
343             km.keymap_items[34-1].properties.type = 'BACK'
344             km.keymap_items[35-1].idname = 'view3d.viewnumpad'
345             km.keymap_items[35-1].properties.type = 'LEFT'            
346             km.keymap_items[36-1].idname = 'view3d.viewnumpad'
347             km.keymap_items[36-1].properties.type = 'BOTTOM'            
348             
349             km = bpy.context.window_manager.keyconfigs.default.keymaps['Image Paint']
350             for kmi in km.keymap_items:
351                 if kmi.idname in ["object.scaleplane"]:
352                     km.keymap_items.remove(kmi)
353             
354             bpy.ops.paint.texture_paint_toggle()
355                     
356         except:
357             nothing
358         
359         return {'FINISHED'}
360
361 # Oprerator Class to rotate the view3D
362 class RotateView3D(Operator):
363     bl_idname = "view3d.rotate_view3d"
364     bl_label = "Rotate the View3D"
365     
366     first_mouse_x = 0
367     first_mouse_y = 0 
368
369     panx = 0
370     pany = 0
371
372     rkey = False
373     skey = False
374     gkey = False
375     zkey = False
376     ukey = False
377     ckey = False
378     first_time = True
379     
380     def vect_sphere(self,mx,my):
381         width = bpy.context.area.regions[4].width
382         height = bpy.context.area.regions[4].height
383            
384         if width >= height:
385             ratio = height/width
386         
387             x = 2*mx/width
388             y = 2*ratio*my/height
389             
390             x = x - 1
391             y = y - ratio
392         else:
393             ratio = width/height
394         
395             x = 2*ratio*mx/width
396             y = 2*my/height
397  
398             x = x - ratio
399             y = y - 1
400         
401         z2 = 1 - x * x - y * y
402         if z2 > 0:
403             z= sqrt(z2)
404         else : z=0
405             
406         p = Vector((x, y, z))
407         p.normalize()
408         return p
409     
410     def tracball(self,mx,my,origine):
411         pos_init_cursor = view3d_utils.location_3d_to_region_2d(bpy.context.region, bpy.context.space_data.region_3d, bpy.context.space_data.cursor_location)        
412         if bpy.context.object.custom_rot:
413             pos_init = view3d_utils.location_3d_to_region_2d(bpy.context.region, bpy.context.space_data.region_3d, origine)
414             bpy.context.space_data.region_3d.view_location = origine
415         
416         v1 = self.vect_sphere(self.first_mouse_x,self.first_mouse_y)
417         v2 = self.vect_sphere(mx,my)
418                         
419         axis = Vector.cross(v1, v2);
420         angle = Vector.angle(v1, v2);
421             
422         q =  Quaternion(axis,-2*angle)
423                         
424         bpy.context.space_data.region_3d.view_rotation *=q
425         bpy.context.space_data.region_3d.update()
426         
427         if bpy.context.object.custom_rot:
428             pos_end = view3d_utils.region_2d_to_location_3d(bpy.context.region, bpy.context.space_data.region_3d, pos_init, Vector((0,0,0)))                
429             bpy.context.space_data.region_3d.view_location =  -1*pos_end
430
431         if bpy.context.object.custom_c3d:
432             bpy.context.space_data.region_3d.update()       
433             bpy.context.space_data.cursor_location = view3d_utils.region_2d_to_location_3d(bpy.context.region, bpy.context.space_data.region_3d, pos_init_cursor, Vector((0,0,0)))
434         
435         self.first_mouse_x = mx
436         self.first_mouse_y = my
437                 
438     def modal(self, context, event):                                
439         if event.value == 'PRESS':
440             self.panx = event.mouse_region_x
441             self.pany = event.mouse_region_y
442                     
443             if event.type == 'S':
444                 self.skey = True
445             
446             if event.type == 'R':
447                 self.rkey = True    
448
449             if event.type == 'G':
450                 self.gkey = True
451
452             if event.type == 'Z':
453                 self.zkey = True            
454
455             if event.type == 'U':
456                 self.ukey = True 
457
458             if event.type == 'C':
459                 self.ckey = True 
460                             
461         if event.value == 'RELEASE':
462             if event.type == 'S':
463                 self.skey = False
464             
465             if event.type == 'R':
466                 self.rkey = False
467             
468             if event.type == 'G':
469                 self.gkey = False            
470
471             if event.type == 'Z':
472                 self.zkey = False 
473
474             if event.type == 'U':
475                 self.ukey = False                 
476
477             if event.type == 'C':
478                 self.ckey = False             
479
480         if event.type == 'MOUSEMOVE':                        
481             
482             if self.rkey == False and self.skey == False and self.gkey == False and self.zkey == False and self.ukey == False:
483                 self.tracball(event.mouse_region_x,event.mouse_region_y,bpy.context.object.location)
484                 align_to_view(context)
485                 if self.first_time:
486                     rot_ang = bpy.context.user_preferences.view.rotation_angle            
487                     bpy.context.user_preferences.view.rotation_angle = 0
488                     bpy.ops.view3d.view_orbit(type='ORBITLEFT')
489                     bpy.context.user_preferences.view.rotation_angle = rot_ang   
490                     bpy.ops.view3d.view_persportho()         
491                     bpy.ops.view3d.view_persportho()
492                     self.first_time = False
493           
494             deltax = event.mouse_region_x - self.panx
495             deltay = event.mouse_region_y - self.pany           
496
497             if self.rkey == False and self.skey == False and self.gkey == True and self.zkey == False and self.ukey == False:       
498                 bpy.context.object.custom_location[0]+=deltax
499                 bpy.context.object.custom_location[1]+=deltay                
500                                    
501             if self.rkey == False and self.skey == True and self.gkey == False and self.zkey == False and self.ukey == False:                
502                 bpy.context.object.custom_scale+=deltax/10
503                                           
504             if self.rkey == False and self.skey == False and self.gkey == False and self.zkey == True and self.ukey == False:                
505                 bpy.context.object.custom_z+=deltax/10
506                       
507             if self.rkey == True and self.skey == False and self.gkey == False and self.zkey == False and self.ukey == False:
508                 bpy.context.object.custom_rotation+=deltax
509                     
510             if self.rkey == False and self.skey == False and self.gkey == False and self.zkey == False and self.ukey == True:
511                 bpy.context.object.custom_scaleuv+=deltax/10                
512
513             self.panx = event.mouse_region_x
514             self.pany = event.mouse_region_y
515             self.first_mouse_x = event.mouse_region_x
516             self.first_mouse_y = event.mouse_region_y
517             
518         elif event.type == 'MIDDLEMOUSE'and event.value == 'RELEASE':       
519             
520             return {'FINISHED'}
521         
522         if self.ckey:
523             if self.skey:
524                 bpy.context.object.custom_scale = 1
525             if self.rkey:
526                 bpy.context.object.custom_rotation = 0
527             return {'RUNNING_MODAL'}
528                     
529         return {'RUNNING_MODAL'}
530     
531     def execute(self, context):        
532         align_to_view(context)  
533         
534         return{'FINISHED'}
535
536     def invoke(self, context, event):
537         context.window_manager.modal_handler_add(self)
538         self.first_mouse_x = event.mouse_region_x
539         self.first_mouse_y = event.mouse_region_y
540         self.first_time = True
541         
542         return {'RUNNING_MODAL'}
543
544 # Oprerator Class to pan the view3D
545 class PanView3D(bpy.types.Operator):
546     bl_idname = "view3d.pan_view3d"
547     bl_label = "Pan View3D"
548
549     
550     first_mouse_x = 0
551     first_mouse_y = 0 
552
553     panx = 0
554     pany = 0
555
556     def modal(self, context, event):
557         width = bpy.context.area.regions[4].width
558         height = bpy.context.area.regions[4].height
559
560         deltax = event.mouse_region_x - self.first_mouse_x
561         deltay = event.mouse_region_y - self.first_mouse_y                
562                
563         l =  bpy.context.space_data.region_3d
564         vr = l.view_rotation
565         
566         v = Vector((deltax/max(width,height),deltay/max(width,height),0))
567         v.rotate(vr)
568         
569         pos = [0,0]
570         v1 = view3d_utils.region_2d_to_location_3d(bpy.context.region, l, pos, v)
571         pos = [width,height]
572         v2 = view3d_utils.region_2d_to_location_3d(bpy.context.region, l, pos, v)
573         
574         v3 = (v2 - v1)
575         
576         pos_init_cursor = view3d_utils.location_3d_to_region_2d(bpy.context.region, bpy.context.space_data.region_3d, bpy.context.space_data.cursor_location)
577         
578         bpy.context.space_data.region_3d.view_location -= v*v3.length
579         
580         bpy.context.space_data.region_3d.update()       
581         bpy.context.space_data.cursor_location = view3d_utils.region_2d_to_location_3d(bpy.context.region, bpy.context.space_data.region_3d, pos_init_cursor, Vector((0,0,0)))
582             
583         align_to_view(context)
584
585         self.first_mouse_x = event.mouse_region_x
586         self.first_mouse_y = event.mouse_region_y
587
588         if event.type == 'MIDDLEMOUSE'and event.value == 'RELEASE':
589             return {'FINISHED'}
590         
591         return {'RUNNING_MODAL'}
592                 
593     def invoke(self, context, event):
594         context.window_manager.modal_handler_add(self)
595         self.first_mouse_x = event.mouse_region_x
596         self.first_mouse_y = event.mouse_region_y   
597         
598         return {'RUNNING_MODAL'}
599
600     def execute(self, context):        
601         align_to_view(context)  
602         
603         return{'FINISHED'}
604
605 # Oprerator Class to zoom the view3D
606 class ZoomView3D(Operator):
607     bl_idname = "view3d.zoom_view3d"
608     bl_label = "Zoom View3D"
609
610     delta = FloatProperty(
611         name="delta",
612         description="Delta",
613         min=-1.0, max=1,
614         default=1.0,
615         )
616
617     def invoke(self, context, event):                   
618         bpy.ops.view3d.zoom(delta = self.delta)
619         
620         align_to_view(context)
621         
622         return {'FINISHED'}
623
624     def execute(self, context):        
625         align_to_view(context)
626         
627         return{'FINISHED'}
628
629 # Oprerator Class to use numpad shortcut
630 class PresetView3D(Operator):
631     bl_idname = "view3d.preset_view3d"
632     bl_label = "Preset View3D"
633
634     view = StringProperty(name="View", description="Select the view", default='TOP',)
635
636     def invoke(self, context, event):                   
637         origine = bpy.context.object.location
638         
639         pos_init_cursor = view3d_utils.location_3d_to_region_2d(bpy.context.region, bpy.context.space_data.region_3d, bpy.context.space_data.cursor_location)
640
641         if bpy.context.object.custom_rot:
642             pos_init = view3d_utils.location_3d_to_region_2d(bpy.context.region, bpy.context.space_data.region_3d, origine)
643             bpy.context.space_data.region_3d.view_location = origine
644
645         tmp = bpy.context.user_preferences.view.smooth_view
646         bpy.context.user_preferences.view.smooth_view = 0
647         bpy.ops.view3d.viewnumpad(type=self.view)        
648         align_to_view(context)
649         bpy.context.user_preferences.view.smooth_view = tmp
650
651         if bpy.context.object.custom_rot:
652             pos_end = view3d_utils.region_2d_to_location_3d(bpy.context.region, bpy.context.space_data.region_3d, pos_init, Vector((0,0,0)))                
653             bpy.context.space_data.region_3d.view_location =  -1*pos_end
654             align_to_view(context)
655
656         if bpy.context.object.custom_c3d:
657             bpy.context.space_data.region_3d.update()       
658             bpy.context.space_data.cursor_location = view3d_utils.region_2d_to_location_3d(bpy.context.region, bpy.context.space_data.region_3d, pos_init_cursor, Vector((0,0,0)))        
659                     
660         return {'FINISHED'}
661
662 def register():
663     bpy.utils.register_module(__name__)
664     createcustomprops()
665
666 def unregister():
667     bpy.utils.unregister_module(__name__)
668
669 if __name__ == "__main__":
670     register()
671    
672