[Edit Linked Library] Fixes based on code review from Campbell
[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/Scripts/3D_interaction/Game_Property_Visualiser",
32     "tracker_url": "http://projects.blender.org/tracker/?func=detail&aid=22607&group_id=153&atid=468",
33     "category": "3D View"}
34
35 """
36 Displays game properties next to selected objects(under name)
37
38 How to use:
39     just toggle the button 'Visualize game props' in the right side panel
40 """
41
42 import bgl
43 import blf
44 import bpy
45 import mathutils
46
47
48 # calculate locations and store them as ID property in the mesh
49 def calc_callback(self, context):
50     # polling
51     if context.mode == 'EDIT_MESH':
52         return
53
54     # get screen information
55     mid_x = context.region.width/2.0
56     mid_y = context.region.height/2.0
57     width = context.region.width
58     height = context.region.height
59
60     # get matrices
61     view_mat = context.space_data.region_3d.perspective_matrix
62
63     ob_mat = context.active_object.matrix_world
64     total_mat = view_mat*ob_mat
65
66     # calculate location info
67     texts = []
68
69     # uncomment 2 lines below, to enable live updating of the selection
70     #ob=context.active_object
71     for ob in context.selected_objects:
72         locs = []
73         ob_mat = ob.matrix_world
74         total_mat = view_mat*ob_mat
75
76         for p in ob.game.properties:
77             # d = {'data':p.name+':'+str(p.value)}
78             # print (d)
79             locs.append(mathutils.Vector((0,0,0,1)))
80
81         for loc in locs:
82             vec = total_mat * loc # order is important
83             # dehomogenise
84             vec = mathutils.Vector((vec[0]/vec[3],vec[1]/vec[3],vec[2]/vec[3]))
85             x = int(mid_x + vec[0]*width/2.0)
86             y = int(mid_y + vec[1]*height/2.0)
87             texts+=[x, y]
88
89     # store as ID property in mesh
90     context.scene['GamePropsVisualizer'] = texts
91
92
93 # draw in 3d-view
94 def draw_callback(self, context):
95     # polling
96     if context.mode == 'EDIT_MESH':
97         return
98
99     """
100     # retrieving ID property data
101     try:
102         texts = context.scene['GamePropsVisualizer']
103     except:
104         return
105
106     if not texts:
107         return
108     """
109
110     texts = context.scene['GamePropsVisualizer']
111
112     # draw
113     i=0
114
115     blf.size(0, 12, 72)
116
117
118     bgl.glColor3f(1.0,1.0,1.0)
119     for ob in bpy.context.selected_objects:
120         for pi,p in enumerate(ob.game.properties):
121             blf.position(0, texts[i], texts[i+1]-(pi+1)*14, 0)
122             if p.type=='FLOAT':
123                 t=p.name+':  '+ str('%g'% p.value)
124             else:
125                 t=p.name+':  '+ str(p.value)
126             blf.draw(0, t)
127             i+=2
128
129
130 # operator
131 class GamePropertyVisualizer(bpy.types.Operator):
132     bl_idname = "view3d.game_props_visualizer"
133     bl_label = "Game Properties Visualizer"
134     bl_description = "Toggle the visualization of game properties"
135
136     _handle_calc = None
137     _handle_draw = None
138
139     @staticmethod
140     def handle_add(self, context):
141         GamePropertyVisualizer._handle_calc = bpy.types.SpaceView3D.draw_handler_add(
142             calc_callback, (self, context), 'WINDOW', 'POST_VIEW')
143         GamePropertyVisualizer._handle_draw = bpy.types.SpaceView3D.draw_handler_add(
144             draw_callback, (self, context), 'WINDOW', 'POST_PIXEL')
145
146     @staticmethod
147     def handle_remove():
148         if GamePropertyVisualizer._handle_calc is not None:
149             bpy.types.SpaceView3D.draw_handler_remove(GamePropertyVisualizer._handle_calc, 'WINDOW')
150         if GamePropertyVisualizer._handle_draw is not None:
151             bpy.types.SpaceView3D.draw_handler_remove(GamePropertyVisualizer._handle_draw, 'WINDOW')
152         GamePropertyVisualizer._handle_calc = None
153         GamePropertyVisualizer._handle_draw = None
154
155     @classmethod
156     def poll(cls, context):
157         return context.mode != 'EDIT_MESH'
158
159     def execute(self, context):
160         if context.area.type == 'VIEW_3D':
161             if not context.scene.display_game_properties:
162                 # operator is called and not running
163                 GamePropertyVisualizer.handle_add(self, context)
164                 context.scene.display_game_properties = True
165             else:
166                 # operator is called again, stop displaying
167                 GamePropertyVisualizer.handle_remove()
168                 context.scene.display_game_properties = False
169             context.area.tag_redraw()
170             return {'FINISHED'}
171         else:
172             self.report({'WARNING'}, "View3D not found, can't run operator")
173             return {'CANCELLED'}
174
175
176 # defining the panel
177 def menu_func(self, context):
178     layout = self.layout
179     col = layout.column()
180     if not context.scene.display_game_properties:
181         text = "Visualize game props"
182     else:
183         text = "Hide game props"
184     col.operator(GamePropertyVisualizer.bl_idname, text=text)
185     layout.separator()
186
187
188 def register():
189     bpy.utils.register_class(GamePropertyVisualizer)
190     bpy.types.Scene.display_game_properties = bpy.props.BoolProperty(name='Visualize Game Poperties')
191     bpy.types.VIEW3D_PT_view3d_display.prepend(menu_func)
192
193 def unregister():
194     GamePropertyVisualizer.handle_remove()
195     bpy.utils.unregister_class(GamePropertyVisualizer)
196     bpy.types.VIEW3D_PT_view3d_display.remove(menu_func)
197     del bpy.types.Scene.display_game_properties
198
199 if __name__ == "__main__":
200     register()