Internal support for rotating duplis according to the ground slope normal.
[blender-addons-contrib.git] / space_view3d_game_props_visualiser.py
1 # ##### BEGIN GPL LICENSE BLOCK #####
2 #
3 #  This program is free software; you can redistribute it and/or
4 #  modify it under the terms of the GNU General Public License
5 #  as published by the Free Software Foundation; either version 2
6 #  of the License, or (at your option) any later version.
7 #
8 #  This program is distributed in the hope that it will be useful,
9 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 #  GNU General Public License for more details.
12 #
13 #  You should have received a copy of the GNU General Public License
14 #  along with this program; if not, write to the Free Software Foundation,
15 #  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 #
17 # ##### END GPL LICENSE BLOCK #####
18
19 # <pep8 compliant>
20
21
22 bl_info = {
23     "name": "Game Property Visualizer",
24     "author": "Bartius Crouch/Vilem Novak",
25     "version": (2, 6),
26     "blender": (2, 65, 4),
27     "location": "View3D > Properties panel > Display tab",
28     "description": "Display the game properties next to selected objects "
29                    "in the 3d-view",
30     "warning": "Script is returning errors",
31     "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.6/Py/"
32         "Scripts/3D_interaction/Game_Property_Visualiser",
33     "tracker_url": "https://developer.blender.org/T22607",
34     "category": "3D View"}
35
36 """
37 Displays game properties next to selected objects(under name)
38
39 How to use:
40     just toggle the button 'Visualize game props' in the right side panel
41 """
42
43 import bgl
44 import blf
45 import bpy
46 import mathutils
47
48
49 # calculate locations and store them as ID property in the mesh
50 def calc_callback(self, context):
51     # polling
52     if context.mode == 'EDIT_MESH':
53         return
54
55     # get screen information
56     mid_x = context.region.width / 2.0
57     mid_y = context.region.height / 2.0
58     width = context.region.width
59     height = context.region.height
60
61     # get matrices
62     view_mat = context.space_data.region_3d.perspective_matrix
63
64     ob_mat = context.active_object.matrix_world
65     total_mat = view_mat * ob_mat
66
67     # calculate location info
68     texts = []
69
70     # uncomment 2 lines below, to enable live updating of the selection
71     #ob=context.active_object
72     for ob in context.selected_objects:
73         locs = []
74         ob_mat = ob.matrix_world
75         total_mat = view_mat*ob_mat
76
77         for p in ob.game.properties:
78             # d = {'data':p.name+':'+str(p.value)}
79             # print (d)
80             locs.append(mathutils.Vector((0, 0, 0, 1)))
81
82         for loc in locs:
83             vec = total_mat * loc # order is important
84             # dehomogenise
85             vec = mathutils.Vector((vec[0]/vec[3], vec[1]/vec[3], vec[2]/vec[3]))
86             x = int(mid_x + vec[0]*width / 2.0)
87             y = int(mid_y + vec[1]*height / 2.0)
88             texts += [x, y]
89
90     # store as ID property in mesh
91     context.scene['GamePropsVisualizer'] = texts
92
93
94 # draw in 3d-view
95 def draw_callback(self, context):
96     # polling
97     if context.mode == 'EDIT_MESH':
98         return
99
100     """
101     # retrieving ID property data
102     try:
103         texts = context.scene['GamePropsVisualizer']
104     except:
105         return
106
107     if not texts:
108         return
109     """
110
111     texts = context.scene['GamePropsVisualizer']
112
113     # draw
114     i = 0
115
116     blf.size(0, 12, 72)
117
118
119     bgl.glColor3f(1.0, 1.0, 1.0)
120     for ob in bpy.context.selected_objects:
121         for pi,p in enumerate(ob.game.properties):
122             blf.position(0, texts[i], texts[i+1] - (pi+1) * 14, 0)
123             if p.type=='FLOAT':
124                 t=p.name+':  '+ str('%g' % p.value)
125             else:
126                 t=p.name+':  '+ str(p.value)
127             blf.draw(0, t)
128             i += 2
129
130
131 # operator
132 class GamePropertyVisualizer(bpy.types.Operator):
133     bl_idname = "view3d.game_props_visualizer"
134     bl_label = "Game Properties Visualizer"
135     bl_description = "Toggle the visualization of game properties"
136
137     _handle_calc = None
138     _handle_draw = None
139
140     @staticmethod
141     def handle_add(self, context):
142         GamePropertyVisualizer._handle_calc = bpy.types.SpaceView3D.draw_handler_add(
143             calc_callback, (self, context), 'WINDOW', 'POST_VIEW')
144         GamePropertyVisualizer._handle_draw = bpy.types.SpaceView3D.draw_handler_add(
145             draw_callback, (self, context), 'WINDOW', 'POST_PIXEL')
146
147     @staticmethod
148     def handle_remove():
149         if GamePropertyVisualizer._handle_calc is not None:
150             bpy.types.SpaceView3D.draw_handler_remove(GamePropertyVisualizer._handle_calc, 'WINDOW')
151         if GamePropertyVisualizer._handle_draw is not None:
152             bpy.types.SpaceView3D.draw_handler_remove(GamePropertyVisualizer._handle_draw, 'WINDOW')
153         GamePropertyVisualizer._handle_calc = None
154         GamePropertyVisualizer._handle_draw = None
155
156     @classmethod
157     def poll(cls, context):
158         return context.mode != 'EDIT_MESH'
159
160     def modal(self, context, event):
161         if not context.scene.display_game_properties:
162             return self.cancel(context)
163         context.area.tag_redraw()
164         return {'PASS_THROUGH'}
165
166     def invoke(self, context, event):
167         if context.area.type == 'VIEW_3D':
168             if not context.scene.display_game_properties:
169                 # operator is called and not running
170                 GamePropertyVisualizer.handle_add(self, context)
171                 context.scene.display_game_properties = True
172                 context.window_manager.modal_handler_add(self)
173                 return {'RUNNING_MODAL'}
174             else:
175                 # operator is called again, stop displaying
176                 return self.cancel(context)
177         else:
178             self.report({'WARNING'}, "View3D not found, can't run operator")
179             return {'CANCELLED'}
180
181     def cancel(self, context):
182         GamePropertyVisualizer.handle_remove()
183         context.scene.display_game_properties = False
184         context.area.tag_redraw()
185         return {'FINISHED'}
186
187
188 # defining the panel
189 def menu_func(self, context):
190     layout = self.layout
191     col = layout.column()
192     if not context.scene.display_game_properties:
193         text = "Visualize game props"
194     else:
195         text = "Hide game props"
196     col.operator(GamePropertyVisualizer.bl_idname, text=text)
197     layout.separator()
198
199
200 def register():
201     bpy.utils.register_class(GamePropertyVisualizer)
202     bpy.types.Scene.display_game_properties = bpy.props.BoolProperty(name='Visualize Game Poperties')
203     bpy.types.VIEW3D_PT_view3d_display.prepend(menu_func)
204
205 def unregister():
206     GamePropertyVisualizer.handle_remove()
207     bpy.utils.unregister_class(GamePropertyVisualizer)
208     bpy.types.VIEW3D_PT_view3d_display.remove(menu_func)
209     del bpy.types.Scene.display_game_properties
210
211 if __name__ == "__main__":
212     register()