提供Verge3D教程和Web3D开发技术服务

【blender】显示快捷键脚本

  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. # <pep8 compliant>
  19. bl_info = {
  20.     “name”: “Screencast Keys”,
  21.     “author”: “Paulo Gomes, Bart Crouch, John E. Herrenyo, Gaia Clary, Pablo Vazquez”,
  22.     “version”: (1, 7),
  23.     “blender”: (2, 66, 0),
  24.     “location”: “3D View > Properties Panel > Screencast Keys”,
  25.     “warning”: “”,
  26.     “description”: “Display keys pressed in the 3D View, “
  27.                    “useful for screencasts.”,
  28.     “wiki_url”: “http://wiki.blender.org/index.php/Extensions:2.6/”
  29.                 “Py/Scripts/3D_interaction/Screencast_Key_Status_Tool”,
  30.     “tracker_url”: “http://projects.blender.org/tracker/index.php?”
  31.                    “func=detail&aid=21612”,
  32.     “category”: “3D View”}
  33. import bgl
  34. import blf
  35. import bpy
  36. import time
  37. import datetime
  38. MOUSE_RATIO = 0.535
  39. def getDisplayLocation(context):
  40.     scene   = context.scene
  41.     mouse_size = scene.screencast_keys_mouse_size
  42.     pos_x = int( (context.region.width  – mouse_size * MOUSE_RATIO) * \
  43.         scene.screencast_keys_pos_x / 100)
  44.     pos_y = int( (context.region.height – mouse_size) *
  45.         scene.screencast_keys_pos_y / 100)
  46.     return(pos_x, pos_y)
  47. def getBoundingBox(current_width, current_height, new_text):
  48.     w,h = blf.dimensions(0,new_text)
  49.     if w > current_width:
  50.         current_width = w
  51.     current_height += h
  52.     return(current_width, current_height)
  53. def draw_callback_px_text(self, context):
  54.     wm = context.window_manager
  55.     sc = context.scene
  56.     if not wm.screencast_keys_keys:
  57.         return
  58.     font_size  = sc.screencast_keys_font_size
  59.     mouse_size = sc.screencast_keys_mouse_size
  60.     box_draw   = sc.screencast_keys_box_draw
  61.     pos_x, pos_y = getDisplayLocation(context)
  62.     label_time_max = sc.screencast_keys_fade_time
  63.     # draw text in the 3D View
  64.     blf.size(0, sc.screencast_keys_font_size, 72)
  65.     blf.enable(0, blf.SHADOW)
  66.     blf.shadow_offset(0, 1, -1)
  67.     blf.shadow(0, 5, 0.0, 0.0, 0.0, 0.8)
  68.     font_color_r, font_color_g, font_color_b, font_color_alpha = sc.screencast_keys_text_color
  69.     final = 0
  70.     row_count = len(self.key)
  71.     keypos_x = pos_x
  72.     if sc.screencast_keys_mouse_position == ‘left’:
  73.         keypos_x += mouse_size * MOUSE_RATIO * 1.7
  74.     if sc.screencast_keys_mouse != ‘icon’:
  75.         keypos_x -= mouse_size * MOUSE_RATIO
  76.     if sc.screencast_keys_mouse_position == ‘right’ and sc.screencast_keys_mouse != ‘icon’:
  77.         keypos_x = pos_x
  78.     shift = 0
  79.     # we want to make sure we can shift vertically the text if the mouse is big,
  80.     # but don’t care if aligned to right 
  81.     if mouse_size > font_size*row_count and not sc.screencast_keys_mouse_position == ‘right’:
  82.         shift = (mouse_size – font_size*row_count) / 2
  83.     text_width, text_height = 0,0
  84.     row_count = 0
  85.     alpha = 1.0
  86.     for i in range(len(self.key)):
  87.         label_time = time.time() – self.time[i]
  88.         if label_time < label_time_max: # only display key-presses of last 2 seconds
  89.             if label_time > (label_time_max / 1.2):
  90.                 blf.blur(0, 1)
  91.             if label_time > (label_time_max / 1.1):
  92.                 blf.blur(0, 3)
  93.             keypos_y = pos_y + shift + font_size*(i+0.1)
  94.             blf.position(0, keypos_x, keypos_y , 0)
  95.             alpha = min(1.0, max(0.0, label_time_max * (label_time_max – label_time)))
  96.             bgl.glColor4f(font_color_r, font_color_g, font_color_b, font_color_alpha * alpha)
  97.             blf.draw(0, self.key[i])
  98.             text_width, text_height = getBoundingBox(text_width, text_height,
  99.                 self.key[i])
  100.             row_count += 1
  101.             final = i + 1
  102.         else:
  103.             break
  104.     # remove blurriness 
  105.     # disable shadows so they don’t appear all over blender
  106.     blf.blur(0,0)
  107.     blf.disable(0, blf.SHADOW)
  108.     # get rid of status texts that aren’t displayed anymore
  109.     self.key = self.key[:final]
  110.     self.time = self.time[:final]
  111.     # draw graphical representation of the mouse
  112.     if sc.screencast_keys_mouse == ‘icon’:
  113.         for shape in [“mouse”, “left_button”, “middle_button”, “right_button”]:
  114.             draw_mouse(context, shape, “outline”, font_color_alpha * 0.4)
  115.         final = 0
  116.         for i in range(len(self.mouse)):
  117.             click_time = time.time() – self.mouse_time[i]
  118.             if click_time < 2:
  119.                 shape = map_mouse_event(self.mouse[i])
  120.                 if shape:
  121.                     alpha = min(1.0, max(0.0, 2 * (2 – click_time)))
  122.                     draw_mouse(context, shape, “filled”, alpha)
  123.                 final = i + 1
  124.             else:
  125.                 break
  126.     # get rid of mouse clicks that aren’t displayed anymore
  127.     self.mouse = self.mouse[:final]
  128.     self.mouse_time = self.mouse_time[:final]
  129. def draw_callback_px_box(self, context):
  130.     wm = context.window_manager
  131.     sc = context.scene
  132.     if not wm.screencast_keys_keys:
  133.         return
  134.     font_size  = sc.screencast_keys_font_size
  135.     mouse_size = sc.screencast_keys_mouse_size
  136.     if sc.screencast_keys_mouse_position == ‘right’:
  137.         mouse_size = 25
  138.     box_draw   = sc.screencast_keys_box_draw
  139.     pos_x, pos_y = getDisplayLocation(context)
  140.     # get text-width/height to resize the box
  141.     blf.size(0, sc.screencast_keys_font_size, 72)
  142.     box_width, box_height = sc.screencast_keys_box_width,0
  143.     final = 0
  144.     row_count = 0
  145.     box_hide = sc.screencast_keys_box_hide
  146.     label_time_max = sc.screencast_keys_fade_time
  147.     for i in range(len(self.key)):
  148.         label_time = time.time() – self.time[i]
  149.         if label_time < label_time_max: # only display key-presses of last 4 seconds
  150.             box_width, box_height = getBoundingBox(box_width, box_height, self.key[i])
  151.             row_count += 1
  152.             final = i + 1
  153.             box_hide = False
  154.         else:
  155.             break
  156.     # Got the size right, now draw box using proper colors
  157.     box_color_r, box_color_g, box_color_b, box_color_alpha = sc.screencast_keys_box_color
  158.     if box_draw and not box_hide:
  159.         padding_x = 16
  160.         padding_y = 12
  161.         x0 = max(0, pos_x – padding_x)
  162.         y0 = max(0, pos_y – padding_y)
  163.         x1 = pos_x + box_width + mouse_size * MOUSE_RATIO * 1.3 + padding_x
  164.         y1 = pos_y + max(mouse_size, font_size * row_count) + padding_y
  165.         positions = [[x0, y0], [x0, y1], [x1, y1], [x1, y0]]
  166.         settings = [[bgl.GL_QUADS, min(0.0, box_color_alpha)], [bgl.GL_LINE_LOOP, min(0.0, box_color_alpha)]]
  167.         for mode, box_alpha in settings:
  168.             bgl.glEnable(bgl.GL_BLEND)
  169.             bgl.glBegin(mode)
  170.             bgl.glColor4f(box_color_r, box_color_g, box_color_b, box_color_alpha)
  171.             for v1, v2 in positions:
  172.                 bgl.glVertex2f(v1, v2)
  173.             bgl.glEnd()
  174.     if sc.screencast_keys_show_operator:
  175.         draw_last_operator(context, pos_x, pos_y)
  176.     if sc.screencast_keys_timer_show:
  177.         draw_timer(context, pos_x, pos_y)
  178.     # get rid of status texts that aren’t displayed anymore
  179.     self.key = self.key[:final]
  180.     self.time = self.time[:final]
  181. def draw_callback_px(self, context):
  182.     draw_callback_px_text(self, context)
  183.     draw_callback_px_box(self, context)
  184. def draw_last_operator(context, pos_x, pos_y):
  185.     wm = context.window_manager
  186.     sc = context.scene
  187.     font_color_r, font_color_g, font_color_b, font_color_alpha = sc.screencast_keys_text_color
  188.     pos_x, pos_y = getDisplayLocation(context)
  189.     if wm.operators:
  190.         last_operator = wm.operators[-1].bl_label
  191.         blf.enable(0, blf.SHADOW)
  192.         blf.shadow_offset(0, 1, -1)
  193.         blf.shadow(0, 5, 0.0, 0.0, 0.0, 0.8)
  194.         blf.size(0, sc.screencast_keys_font_size, 36)
  195.         blf.position(0, pos_x – 14, pos_y – 30, 0)
  196.         bgl.glColor4f(font_color_r, font_color_g, font_color_b, font_color_alpha * 0.8)
  197.         blf.draw(0, “Last: %s” % (last_operator))
  198.         blf.disable(0, blf.SHADOW)
  199. def draw_timer(context, pos_x, pos_y):
  200.     sc = context.scene
  201.     #calculate overall time
  202.     overall_time = datetime.timedelta(seconds=int(time.time() – ScreencastKeysStatus.overall_time[0]))
  203.     timer_color_r, timer_color_g, timer_color_b, timer_color_alpha = sc.screencast_keys_timer_color
  204.     pos_x = context.region.width – (sc.screencast_keys_timer_size * 12) + 12
  205.     pos_y = 10
  206.     #draw time
  207.     blf.size(0, sc.screencast_keys_timer_size, 72)
  208.     blf.position(0, pos_x, pos_y, 0)
  209.     bgl.glColor4f(timer_color_r, timer_color_g, timer_color_b, timer_color_alpha)
  210.     blf.draw(0, “Elapsed Time: %s” % (overall_time))
  211. def draw_mouse(context, shape, style, alpha):
  212.     # shape and position
  213.     sc   = context.scene
  214.     mouse_size = sc.screencast_keys_mouse_size
  215.     font_size  = sc.screencast_keys_font_size
  216.     box_draw = sc.screencast_keys_box_draw
  217.     pos_x, pos_y = getDisplayLocation(context)
  218.     if sc.screencast_keys_mouse_position == ‘left’:
  219.         offset_x = pos_x
  220.     if sc.screencast_keys_mouse_position == ‘right’:
  221.         offset_x = context.region.width – pos_x – (mouse_size * MOUSE_RATIO)
  222.     offset_y = pos_y
  223.     if font_size > mouse_size:
  224.         offset_y += (font_size – mouse_size) / 2
  225.     shape_data = get_shape_data(shape)
  226.     bgl.glTranslatef(offset_x, offset_y, 0)
  227.     # color
  228.     r, g, b, a = sc.screencast_keys_text_color
  229.     bgl.glEnable(bgl.GL_BLEND)
  230.     bgl.glColor4f(r, g, b, alpha)
  231.     # inner shape for filled style
  232.     if style == “filled”:
  233.         inner_shape = []
  234.         for i in shape_data:
  235.             inner_shape.append(i[0])
  236.     # outer shape
  237.     for i in shape_data:
  238.         shape_segment = i
  239.         shape_segment[0] = [mouse_size * k for k in shape_segment[0]]
  240.         shape_segment[1] = [mouse_size * k for k in shape_segment[1]]
  241.         shape_segment[2] = [mouse_size * k for k in shape_segment[2]]
  242.         shape_segment[3] = [mouse_size * k for k in shape_segment[3]]
  243.         # create the buffer
  244.         shape_buffer = bgl.Buffer(bgl.GL_FLOAT, [4, 3], shape_segment)
  245.         # create the map and draw the triangle fan
  246.         bgl.glMap1f(bgl.GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, shape_buffer)
  247.         bgl.glEnable(bgl.GL_MAP1_VERTEX_3)
  248.         if style == “outline”:
  249.             bgl.glBegin(bgl.GL_LINE_STRIP)
  250.         else# style == “filled”
  251.             bgl.glBegin(bgl.GL_TRIANGLE_FAN)
  252.         for j in range(10):
  253.             bgl.glEvalCoord1f(j / 10.0)
  254.         x, y, z = shape_segment[3]
  255.         # make sure the last vertex is indeed the last one, to avoid gaps
  256.         bgl.glVertex3f(x, y, z)
  257.         bgl.glEnd()
  258.         bgl.glDisable(bgl.GL_MAP1_VERTEX_3)
  259.     # draw interior
  260.     if style == “filled”:
  261.         bgl.glBegin(bgl.GL_TRIANGLE_FAN)
  262.         for i in inner_shape:
  263.             j = [mouse_size * k for k in i]
  264.             x, y, z = j
  265.             bgl.glVertex3f(x, y, z)
  266.         bgl.glEnd()
  267.     bgl.glTranslatef(-offset_x, -offset_y, 0)
  268. # hardcoded data to draw the graphical represenation of the mouse
  269. def get_shape_data(shape):
  270.     data = []
  271.     if shape == “mouse”:
  272.         data = [[[0.404, 0.032, 0.0],
  273.             [0.096, 0.002, 0.0],
  274.             [0.059, 0.126, 0.0],
  275.             [0.04, 0.213, 0.0]],
  276.             [[0.04, 0.213, 0.0],
  277.             [-0.015, 0.465, 0.0],
  278.             [-0.005, 0.564, 0.0],
  279.             [0.032, 0.87, 0.0]],
  280.             [[0.032, 0.87, 0.0],
  281.             [0.05, 0.973, 0.0],
  282.             [0.16, 1.002, 0.0],
  283.             [0.264, 1.002, 0.0]],
  284.             [[0.264, 1.002, 0.0],
  285.             [0.369, 1.002, 0.0],
  286.             [0.478, 0.973, 0.0],
  287.             [0.497, 0.87, 0.0]],
  288.             [[0.497, 0.87, 0.0],
  289.             [0.533, 0.564, 0.0],
  290.             [0.554, 0.465, 0.0],
  291.             [0.499, 0.213, 0.0]],
  292.             [[0.499, 0.213, 0.0],
  293.             [0.490, 0.126, 0.0],
  294.             [0.432, 0.002, 0.0],
  295.             [0.404, 0.032, 0.0]]]
  296.     elif shape == “left_button”:
  297.         data = [[[0.154, 0.763, 0.0],
  298.             [0.126, 0.755, 0.0],
  299.             [0.12, 0.754, 0.0],
  300.             [0.066, 0.751, 0.0]],
  301.             [[0.066, 0.751, 0.0],
  302.             [0.043, 0.75, 0.0],
  303.             [0.039, 0.757, 0.0],
  304.             [0.039, 0.767, 0.0]],
  305.             [[0.039, 0.767, 0.0],
  306.             [0.047, 0.908, 0.0],
  307.             [0.078, 0.943, 0.0],
  308.             [0.155, 0.97, 0.0]],
  309.             [[0.155, 0.97, 0.0],
  310.             [0.174, 0.977, 0.0],
  311.             [0.187, 0.975, 0.0],
  312.             [0.191, 0.972, 0.0]],
  313.             [[0.191, 0.972, 0.0],
  314.             [0.203, 0.958, 0.0],
  315.             [0.205, 0.949, 0.0],
  316.             [0.199, 0.852, 0.0]],
  317.             [[0.199, 0.852, 0.0],
  318.             [0.195, 0.77, 0.0],
  319.             [0.18, 0.771, 0.0],
  320.             [0.154, 0.763, 0.0]]]
  321.     elif shape == “middle_button”:
  322.         data = [[[0.301, 0.8, 0.0],
  323.             [0.298, 0.768, 0.0],
  324.             [0.231, 0.768, 0.0],
  325.             [0.228, 0.8, 0.0]],
  326.             [[0.228, 0.8, 0.0],
  327.             [0.226, 0.817, 0.0],
  328.             [0.225, 0.833, 0.0],
  329.             [0.224, 0.85, 0.0]],
  330.             [[0.224, 0.85, 0.0],
  331.             [0.222, 0.873, 0.0],
  332.             [0.222, 0.877, 0.0],
  333.             [0.224, 0.9, 0.0]],
  334.             [[0.224, 0.9, 0.0],
  335.             [0.225, 0.917, 0.0],
  336.             [0.226, 0.933, 0.0],
  337.             [0.228, 0.95, 0.0]],
  338.             [[0.228, 0.95, 0.0],
  339.             [0.231, 0.982, 0.0],
  340.             [0.298, 0.982, 0.0],
  341.             [0.301, 0.95, 0.0]],
  342.             [[0.301, 0.95, 0.0],
  343.             [0.302, 0.933, 0.0],
  344.             [0.303, 0.917, 0.0],
  345.             [0.305, 0.9, 0.0]],
  346.             [[0.305, 0.9, 0.0],
  347.             [0.307, 0.877, 0.0],
  348.             [0.307, 0.873, 0.0],
  349.             [0.305, 0.85, 0.0]],
  350.             [[0.305, 0.85, 0.0],
  351.             [0.303, 0.833, 0.0],
  352.             [0.302, 0.817, 0.0],
  353.             [0.301, 0.8, 0.0]]]
  354.     elif shape == “middle_down_button”:
  355.         data = [[[0.301, 0.8, 0.0],
  356.             [0.298, 0.768, 0.0],
  357.             [0.231, 0.768, 0.0],
  358.             [0.228, 0.8, 0.0]],
  359.             [[0.228, 0.8, 0.0],
  360.             [0.226, 0.817, 0.0],
  361.             [0.225, 0.833, 0.0],
  362.             [0.224, 0.85, 0.0]],
  363.             [[0.224, 0.85, 0.0],
  364.             [0.264, 0.873, 0.0],
  365.             [0.284, 0.873, 0.0],
  366.             [0.305, 0.85, 0.0]],
  367.             [[0.305, 0.85, 0.0],
  368.             [0.303, 0.833, 0.0],
  369.             [0.302, 0.817, 0.0],
  370.             [0.301, 0.8, 0.0]]]
  371.     elif shape == “middle_up_button”:
  372.         data = [[[0.270, 0.873, 0.0],
  373.             [0.264, 0.873, 0.0],
  374.             [0.222, 0.877, 0.0],
  375.             [0.224, 0.9, 0.0]],
  376.             [[0.224, 0.9, 0.0],
  377.             [0.225, 0.917, 0.0],
  378.             [0.226, 0.933, 0.0],
  379.             [0.228, 0.95, 0.0]],
  380.             [[0.228, 0.95, 0.0],
  381.             [0.231, 0.982, 0.0],
  382.             [0.298, 0.982, 0.0],
  383.             [0.301, 0.95, 0.0]],
  384.             [[0.301, 0.95, 0.0],
  385.             [0.302, 0.933, 0.0],
  386.             [0.303, 0.917, 0.0],
  387.             [0.305, 0.9, 0.0]],
  388.             [[0.305, 0.9, 0.0],
  389.             [0.307, 0.877, 0.0],
  390.             [0.284, 0.873, 0.0],
  391.             [0.270, 0.873, 0.0]]]
  392.     elif shape == “right_button”:
  393.         data = [[[0.375, 0.763, 0.0],
  394.             [0.402, 0.755, 0.0],
  395.             [0.408, 0.754, 0.0],
  396.             [0.462, 0.751, 0.0]],
  397.             [[0.462, 0.751, 0.0],
  398.             [0.486, 0.75, 0.0],
  399.             [0.49, 0.757, 0.0],
  400.             [0.489, 0.767, 0.0]],
  401.             [[0.489, 0.767, 0.0],
  402.             [0.481, 0.908, 0.0],
  403.             [0.451, 0.943, 0.0],
  404.             [0.374, 0.97, 0.0]],
  405.             [[0.374, 0.97, 0.0],
  406.             [0.354, 0.977, 0.0],
  407.             [0.341, 0.975, 0.0],
  408.             [0.338, 0.972, 0.0]],
  409.             [[0.338, 0.972, 0.0],
  410.             [0.325, 0.958, 0.0],
  411.             [0.324, 0.949, 0.0],
  412.             [0.329, 0.852, 0.0]],
  413.             [[0.329, 0.852, 0.0],
  414.             [0.334, 0.77, 0.0],
  415.             [0.348, 0.771, 0.0],
  416.             [0.375, 0.763, 0.0]]]
  417.     return(data)
  418. # return the shape that belongs to the given event
  419. def map_mouse_event(event):
  420.     shape = False
  421.     if event == ‘LEFTMOUSE’:
  422.         shape = “left_button”
  423.     elif event == ‘MIDDLEMOUSE’:
  424.         shape = “middle_button”
  425.     elif event == ‘RIGHTMOUSE’:
  426.         shape = “right_button”
  427.     elif event == ‘WHEELDOWNMOUSE’:
  428.         shape = “middle_down_button”
  429.     elif event == ‘WHEELUPMOUSE’:
  430.         shape = “middle_up_button”
  431.     return(shape)
  432. class ScreencastKeysStatus(bpy.types.Operator):
  433.     bl_idname = “view3d.screencast_keys”
  434.     bl_label = “Screencast Keys”
  435.     bl_description = “Display keys pressed in the 3D View”
  436.     last_activity = ‘NONE’
  437.     _handle = None
  438.     _timer = None
  439.     @staticmethod
  440.     def handle_add(self, context):
  441.         ScreencastKeysStatus._handle = bpy.types.SpaceView3D.draw_handler_add(draw_callback_px, (self, context), ‘WINDOW’, ‘POST_PIXEL’)
  442.         ScreencastKeysStatus._timer = context.window_manager.event_timer_add(0.075, context.window)
  443.     @staticmethod
  444.     def handle_remove(context):
  445.         if ScreencastKeysStatus._handle is not None:
  446.             context.window_manager.event_timer_remove(ScreencastKeysStatus._timer)
  447.             bpy.types.SpaceView3D.draw_handler_remove(ScreencastKeysStatus._handle, ‘WINDOW’)
  448.         ScreencastKeysStatus._handle = None
  449.         ScreencastKeysStatus._timer = None
  450.     def modal(self, context, event):
  451.         if context.area:
  452.             context.area.tag_redraw()
  453.         if event.type == ‘TIMER’:
  454.             # no input, so no need to change the display
  455.             return {‘PASS_THROUGH’}
  456.         scene = context.scene
  457.         # keys that shouldn’t show up in the 3D View
  458.         mouse_keys = [‘MOUSEMOVE’,’MIDDLEMOUSE’,’LEFTMOUSE’,
  459.          ‘RIGHTMOUSE’, ‘WHEELDOWNMOUSE’,’WHEELUPMOUSE’]
  460.         ignore_keys = [‘LEFT_SHIFT’, ‘RIGHT_SHIFT’, ‘LEFT_ALT’,
  461.          ‘RIGHT_ALT’, ‘LEFT_CTRL’, ‘RIGHT_CTRL’, ‘TIMER’,
  462.          ‘MOUSEMOVE’, ‘INBETWEEN_MOUSEMOVE’]
  463.         if scene.screencast_keys_mouse != ‘text’:
  464.             ignore_keys.extend(mouse_keys)
  465.         if event.value == ‘PRESS’ or (event.value == ‘RELEASE’ and \
  466.         self.last_activity == ‘KEYBOARD’ and event.type in mouse_keys):
  467.             # add key-press to display-list
  468.             sc_keys = []
  469.             if event.ctrl:
  470.                 sc_keys.append(“Ctrl “)
  471.             if event.alt:
  472.                 sc_keys.append(“Alt “)
  473.             if event.shift:
  474.                 sc_keys.append(“Shift “)
  475.             sc_amount = “”
  476.             if self.key:
  477.                 #print(“Is a key”)
  478.                 if event.type not in ignore_keys and event.type in self.key[0]:
  479.                     mods = “+ “.join(sc_keys)
  480.                     old_mods = “+ “.join(self.key[0].split(“+ “)[:-1])
  481.                     if mods == old_mods:
  482.                         amount = self.key[0].split(” x”)
  483.                         if len(amount) >= 2:
  484.                             sc_amount = ” x” + str(int(amount[-1]) + 1)
  485.                         else:
  486.                             sc_amount = ” x2″
  487.                         del self.key[0]
  488.                         del self.time[0]
  489.             if event.type not in ignore_keys:
  490.                 #print(“Recorded as key”)
  491.                 sc_keys.append(event.type)
  492.                 self.key.insert(0, “+ “.join(sc_keys) + sc_amount)
  493.                 self.time.insert(0, time.time())
  494.             elif event.type in mouse_keys and \
  495.             scene.screencast_keys_mouse == ‘icon’:
  496.                 #print(“Recorded as mouse press”)
  497.                 self.mouse.insert(0, event.type)
  498.                 self.mouse_time.insert(0, time.time())
  499.             if event.type in mouse_keys:
  500.                 self.last_activity = ‘MOUSE’
  501.             else:
  502.                 self.last_activity = ‘KEYBOARD’
  503.             #print(“Last activity set to:”, self.last_activity)
  504.         if not context.window_manager.screencast_keys_keys:
  505.             # stop script
  506.             ScreencastKeysStatus.handle_remove(context)
  507.             return {‘CANCELLED’}
  508.         return {‘PASS_THROUGH’}
  509.     def cancel(self, context):
  510.         if context.window_manager.screencast_keys_keys:
  511.             ScreencastKeysStatus.handle_remove(context)
  512.             context.window_manager.screencast_keys_keys = False
  513.     def invoke(self, context, event):
  514.         if context.area.type == ‘VIEW_3D’:
  515.             if context.window_manager.screencast_keys_keys is False:
  516.                 # operator is called for the first time, start everything
  517.                 context.window_manager.screencast_keys_keys = True
  518.                 self.key = []
  519.                 self.time = []
  520.                 self.mouse = []
  521.                 self.mouse_time = []
  522.                 ScreencastKeysStatus.overall_time = []
  523.                 ScreencastKeysStatus.handle_add(self, context)
  524.                 ScreencastKeysStatus.overall_time.insert(0, time.time())
  525.                 context.window_manager.modal_handler_add(self)
  526.                 return {‘RUNNING_MODAL’}
  527.             else:
  528.                 # operator is called again, stop displaying
  529.                 context.window_manager.screencast_keys_keys = False
  530.                 self.key = []
  531.                 self.time = []
  532.                 self.mouse = []
  533.                 self.mouse_time = []
  534.                 ScreencastKeysStatus.overall_time = []
  535.                 return {‘CANCELLED’}
  536.         else:
  537.             self.report({‘WARNING’}, “3D View not found, can’t run Screencast Keys”)
  538.             return {‘CANCELLED’}
  539. class ScreencastKeysTimerReset(bpy.types.Operator):
  540.     “””Reset Timer”””
  541.     bl_idname = “view3d.screencast_keys_timer_reset”
  542.     bl_label = “Reset Timer”
  543.     bl_description = “Set the timer back to zero”
  544.     def execute(self, context):
  545.         ScreencastKeysStatus.overall_time = [time.time()]
  546.         return {‘FINISHED’}
  547. # properties used by the script
  548. def init_properties():
  549.     scene = bpy.types.Scene
  550.     wm = bpy.types.WindowManager
  551.     scene.screencast_keys_pos_x = bpy.props.IntProperty(
  552.         name=”Position X”,
  553.         description=”Margin on the X axis”,
  554.         default=3,
  555.         min=0,
  556.         max=100)
  557.     scene.screencast_keys_pos_y = bpy.props.IntProperty(
  558.         name=”Position Y”,
  559.         description=”Margin on the Y axis”,
  560.         default=10,
  561.         min=0,
  562.         max=100)
  563.     scene.screencast_keys_font_size = bpy.props.IntProperty(
  564.         name=”Text Size”,
  565.         description=”Text size displayed on 3D View”,
  566.         default=24, min=10, max=150)
  567.     scene.screencast_keys_mouse_size = bpy.props.IntProperty(
  568.         name=”Mouse Size”,
  569.         description=”Mouse size displayed on 3D View”,
  570.         default=33, min=10, max=150)
  571.     scene.screencast_keys_text_color = bpy.props.FloatVectorProperty(
  572.         name=”Text / Icon Color”,
  573.         description=”Color for the text and mouse icon”,
  574.         default=(1.0, 1.0, 1.0, 1.0),
  575.         min=0.1,
  576.         max=1,
  577.         subtype=’COLOR’,
  578.         size=4)
  579.     scene.screencast_keys_box_color = bpy.props.FloatVectorProperty(
  580.         name=”Box Color”,
  581.         description=”Box color”,
  582.         default=(0.0, 0.0, 0.0, 0.3),
  583.         min=0,
  584.         max=1,
  585.         subtype=’COLOR’,
  586.         size=4)
  587.     scene.screencast_keys_box_width = bpy.props.IntProperty(
  588.         name=”Box Width”,
  589.         description=”Box default width (resizes with text if needed)”,
  590.         default = 0,
  591.         min = 0,
  592.         max = 2048,
  593.         soft_max = 1024)
  594.     scene.screencast_keys_mouse = bpy.props.EnumProperty(
  595.         items=((“none”, “No Mouse”, “Don’t display mouse events”),
  596.               (“icon”, “Icon”, “Display graphical representation of “\
  597.                “the mouse”),
  598.               (“text”, “Text”, “Display mouse events as text lines”)),
  599.         name=”Mouse Display”,
  600.         description=”Display mouse events”,
  601.         default=’icon’)
  602.     scene.screencast_keys_mouse_position = bpy.props.EnumProperty(
  603.         items=((“left”, “Left”, “Align to the left”),
  604.               (“right”, “Right”, “Align to the right”)),
  605.         name=”Icon Position”,
  606.         description=”Align the mouse icon on the 3D View”,
  607.         default=’left’)
  608.     scene.screencast_keys_box_draw = bpy.props.BoolProperty(
  609.         name=”Display Box”,
  610.         description = “Display a bounding box behind the text”,
  611.         default = True)
  612.     scene.screencast_keys_box_hide = bpy.props.BoolProperty(
  613.         name=”Hide Box”,
  614.         description = “Hide the box when no key is pressed”,
  615.         default = False)
  616.     scene.screencast_keys_fade_time = bpy.props.FloatProperty(
  617.         name=”Fade Out Time”,
  618.         description = “Time in seconds for keys to last on screen”,
  619.         default = 3.5,
  620.         min = 0.5,
  621.         max = 10.0,
  622.         soft_max = 5.0,
  623.         step = 10,
  624.         subtype = ‘TIME’)
  625.     scene.screencast_keys_show_operator = bpy.props.BoolProperty(
  626.         name=”Display Last Operator”,
  627.         description = “Display the last operator used”,
  628.         default = True)
  629.     scene.screencast_keys_timer_show = bpy.props.BoolProperty(
  630.         name=”Display Timer”,
  631.         description = “Counter of the elapsed time in H:MM:SS since the script started”,
  632.         default = False)
  633.     scene.screencast_keys_timer_size = bpy.props.IntProperty(
  634.         name=”Time Size”,
  635.         description=”Time size displayed on 3D View”,
  636.         default=12, min=8, max=100)
  637.     scene.screencast_keys_timer_color = bpy.props.FloatVectorProperty(
  638.         name=”Time Color”,
  639.         description=”Color for the time display”,
  640.         default=(1.0, 1.0, 1.0, 0.3),
  641.         min=0,
  642.         max=1,
  643.         subtype=’COLOR’,
  644.         size=4)
  645.     # Runstate initially always set to False
  646.     # note: it is not stored in the Scene, but in window manager:
  647.     wm.screencast_keys_keys = bpy.props.BoolProperty(default=False)
  648. # removal of properties when script is disabled
  649. def clear_properties():
  650.     props = (
  651.         “screencast_keys_keys”,
  652.         “screencast_keys_mouse”,
  653.         “screencast_keys_font_size”,
  654.         “screencast_keys_mouse_size”,
  655.         “screencast_keys_mouse_position”,
  656.         “screencast_keys_fade_time”,
  657.         “screencast_keys_pos_x”,
  658.         “screencast_keys_pos_y”,
  659.         “screencast_keys_box_draw”,
  660.         “screencast_keys_text_color”,
  661.         “screencast_keys_box_color”,
  662.         “screencast_keys_box_hide”,
  663.         “screencast_keys_box_width”,
  664.         “screencast_keys_show_operator”,
  665.         “screencast_keys_timer_show”,
  666.         “screencast_keys_timer_color”,
  667.         “screencast_keys_timer_size”,
  668.     )
  669.     wm = bpy.context.window_manager
  670.     for p in props:
  671.         if p in wm:
  672.             del wm[p]
  673. # defining the panel
  674. class OBJECT_PT_keys_status(bpy.types.Panel):
  675.     bl_label = “Screencast Keys”
  676.     bl_space_type = “VIEW_3D”
  677.     bl_region_type = “UI”
  678.     def draw(self, context):
  679.         sc = context.scene
  680.         wm = context.window_manager
  681.         layout = self.layout
  682.         if not wm.screencast_keys_keys:
  683.             layout.operator(“view3d.screencast_keys”, text=”Start Display”,
  684.                 icon = “PLAY”)
  685.         else:
  686.             layout.operator(“view3d.screencast_keys”, text=”Stop Display”,
  687.                 icon = “PAUSE”)
  688.             split = layout.split()
  689.             col = split.column()
  690.             sub = col.column(align=True)
  691.             sub.label(text=”Size:”)
  692.             sub.prop(sc, “screencast_keys_font_size”, text=”Text”)
  693.             sub.prop(sc, “screencast_keys_mouse_size”, text=”Mouse”)
  694.             col = split.column()
  695.             sub = col.column(align=True)
  696.             sub.label(text=”Position:”)
  697.             sub.prop(sc, “screencast_keys_pos_x”, text=”X”)
  698.             sub.prop(sc, “screencast_keys_pos_y”, text=”Y”)
  699.             row = layout.row(align=True)
  700.             row.prop(sc, “screencast_keys_text_color”)
  701.             row = layout.row(align=True)
  702.             row.prop(sc, “screencast_keys_fade_time”)
  703.             layout.separator()
  704.             row = layout.row(align=True)
  705.             row.prop(sc, “screencast_keys_mouse”, text=”Mouse”)
  706.             row = layout.row(align=True)
  707.             row.enabled = sc.screencast_keys_mouse == ‘icon’
  708.             row.prop(sc, “screencast_keys_mouse_position”, expand=True)
  709.             layout.label(text=”Display:”)
  710.             row = layout.row(align=True)
  711.             row.prop(sc, “screencast_keys_box_draw”, text=”Box”)
  712.             row = layout.row(align=True)
  713.             row.active = sc.screencast_keys_box_draw
  714.             row.prop(sc, “screencast_keys_box_color”, text=””)
  715.             row.prop(sc, “screencast_keys_box_hide”, text=”Hide”)
  716.             row = layout.row(align=True)
  717.             row.active = sc.screencast_keys_box_draw
  718.             row.prop(sc, “screencast_keys_box_width”)
  719.             row = layout.row(align=True)
  720.             row.prop(sc, “screencast_keys_show_operator”, text=”Last Operator”)
  721.             split = layout.split()
  722.             col = split.column()
  723.             sub = col.column(align=True)
  724.             sub.prop(sc, “screencast_keys_timer_show”, text=”Time”)
  725.             col = split.column()
  726.             sub = col.column(align=True)
  727.             sub.active = sc.screencast_keys_timer_show
  728.             sub.prop(sc, “screencast_keys_timer_color”, text=””)
  729.             row = layout.row(align=True)
  730.             row.enabled = sc.screencast_keys_timer_show
  731.             row.prop(sc, “screencast_keys_timer_size”)
  732.             row = layout.row(align=True)
  733.             row.enabled = sc.screencast_keys_timer_show
  734.             row.operator(“view3d.screencast_keys_timer_reset”, text=”Reset”)
  735. classes = (ScreencastKeysStatus,
  736.            ScreencastKeysTimerReset,
  737.            OBJECT_PT_keys_status)
  738. # store keymaps here to access after registration
  739. addon_keymaps = []
  740. def register():
  741.     init_properties()
  742.     for c in classes:
  743.         bpy.utils.register_class(c)
  744.     wm = bpy.context.window_manager
  745.     kc = wm.keyconfigs.addon
  746.     if kc:
  747.         km = kc.keymaps.new(name=’3D View’, space_type=’VIEW_3D’)
  748.         kmi = km.keymap_items.new(‘view3d.screencast_keys’, ‘C’, ‘PRESS’, shift=True, alt=True)
  749.         addon_keymaps.append((km, kmi))
  750. def unregister():
  751.     # incase its enabled
  752.     ScreencastKeysStatus.handle_remove(bpy.context)
  753.     for c in classes:
  754.         bpy.utils.unregister_class(c)
  755.     # handle the keymap
  756.     for km, kmi in addon_keymaps:
  757.         km.keymap_items.remove(kmi)
  758.     addon_keymaps.clear()
  759.     clear_properties()
  760. if __name__ == “__main__“:
  761.     register()

zjbcool

zjbcool
关闭菜单