Skip to content
Snippets Groups Projects
space_view3d_enhanced_3d_cursor.py 185 KiB
Newer Older
#  ***** BEGIN GPL LICENSE BLOCK *****
#
#  This program is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
#  ***** END GPL LICENSE BLOCK *****

# <pep8-80 compliant>

bl_info = {
    "name": "Enhanced 3D Cursor",
    "description": "Cursor history and bookmarks; drag/snap cursor.",
    "author": "dairin0d",
    "blender": (2, 77, 0),
    "location": "View3D > Action mouse; F10; Properties panel",
    "warning": "",
    "wiki_url": "https://wiki.blender.org/index.php/Extensions:2.6/Py/"
        "Scripts/3D_interaction/Enhanced_3D_Cursor",
dairin0d's avatar
dairin0d committed
    "tracker_url": "https://github.com/dairin0d/enhanced-3d-cursor/issues",
    "category": "3D View"}

"""
Breakdown:
    Addon registration
    Keymap utils
    Various utils (e.g. find_region)
    OpenGL; drawing utils
    Non-undoable data storage
    Cursor utils
    Stick-object
    Cursor monitor
    Addon's GUI
    Addon's properties
    Addon's operators
    ID Block emulator
    Mesh cache
    Snap utils
    View3D utils
    Transform orientation / coordinate system utils
    Generic transform utils
    Main operator
    ...
.

First step is to re-make the cursor addon (make something usable first).
CAD tools should be done without the hassle.

TODO:
    strip trailing space? (one of campbellbarton's commits did that)
    IDEAS:
        - implement 'GIMBAL' orientation (euler axes)
        - mini-Z-buffer in the vicinity of mouse coords (using raycasts)
        - an orientation that points towards cursor
          (from current selection to cursor)
        - user coordinate systems (using e.g. empties to store different
          systems; when user switches to such UCS, origin will be set to
          "cursor", cursor will be sticked to the empty, and a custom
          transform orientation will be aligned with the empty)
          - "Stick" transform orientation that is always aligned with the
            object cursor is "sticked" to?
        - make 'NORMAL' system also work for bones?
        - user preferences? (stored in a file)
        - create spline/edge_mesh from history?
        - API to access history/bookmarks/operators from other scripts?
        - Snap selection to bookmark?
        - Optimize
        - Clean up code, move to several files?
    LATER:
    ISSUES:
        Limitations:
            - I need to emulate in Python some things that Blender doesn't
              currently expose through API:
              - obtaining matrix of predefined transform orientation
              - obtaining position of pivot
              For some kinds of information (e.g. active vertex/edge,
              selected meta-elements), there is simply no workaround.
            - Snapping to vertices/edges works differently than in Blender.
              First of all, iteration over all vertices/edges of all
              objects along the ray is likely to be very slow.
              Second, it's more human-friendly to snap to visible
              elements (or at least with approximately known position).
            - In editmode I have to exit-and-enter it to get relevant
              information about current selection. Thus any operator
              would automatically get applied when you click on 3D View.
        Mites:
    QUESTIONS:
==============================================================================
Borrowed code/logic:
- space_view3d_panel_measure.py (Buerbaum Martin "Pontiac"):
  - OpenGL state storing/restoring; working with projection matrices.
"""

import bpy
import bgl
import blf

from mathutils import Vector, Matrix, Quaternion, Euler

from mathutils.geometry import (intersect_line_sphere,
                                intersect_ray_tri,
                                barycentric_transform,
                                intersect_line_line,
                                intersect_line_plane,
                                )

from bpy_extras.view3d_utils import (region_2d_to_location_3d,
                                     location_3d_to_region_2d,
                                     )

import math
import time

# ====== MODULE GLOBALS / CONSTANTS ====== #
tmp_name = chr(0x10ffff) # maximal Unicode value
epsilon = 0.000001

# ====== SET CURSOR OPERATOR ====== #
class EnhancedSetCursor(bpy.types.Operator):
    """Cursor history and bookmarks; drag/snap cursor."""
    bl_idname = "view3d.cursor3d_enhanced"
    bl_label = "Enhanced Set Cursor"
    key_char_map = {
        'PERIOD':".", 'NUMPAD_PERIOD':".",
        'MINUS':"-", 'NUMPAD_MINUS':"-",
        'EQUAL':"+", 'NUMPAD_PLUS':"+",
        #'E':"e", # such big/small numbers aren't useful
        'ONE':"1", 'NUMPAD_1':"1",
        'TWO':"2", 'NUMPAD_2':"2",
        'THREE':"3", 'NUMPAD_3':"3",
        'FOUR':"4", 'NUMPAD_4':"4",
        'FIVE':"5", 'NUMPAD_5':"5",
        'SIX':"6", 'NUMPAD_6':"6",
        'SEVEN':"7", 'NUMPAD_7':"7",
        'EIGHT':"8", 'NUMPAD_8':"8",
        'NINE':"9", 'NUMPAD_9':"9",
        'ZERO':"0", 'NUMPAD_0':"0",
        'SPACE':" ",
        'SLASH':"/", 'NUMPAD_SLASH':"/",
        'NUMPAD_ASTERIX':"*",
    }
    key_coordsys_map = {
        'LEFT_BRACKET':-1,
        'RIGHT_BRACKET':1,
        ':':-1, # Instead of [ for French keyboards
        '!':1, # Instead of ] for French keyboards
        'J':'VIEW',
        'K':"Surface",
        'L':'LOCAL',
        'B':'GLOBAL',
        'N':'NORMAL',
        'M':"Scaled",
    }
    key_pivot_map = {
        'H':'ACTIVE',
        'U':'CURSOR',
        'I':'INDIVIDUAL',
        'O':'CENTER',
        'P':'MEDIAN',
    }
    key_snap_map = {
        'C':'INCREMENT',
        'V':'VERTEX',
        'E':'EDGE',
        'F':'FACE',
    }
    key_tfm_mode_map = {
        'G':'MOVE',
        'R':'ROTATE',
        'S':'SCALE',
    }
    key_map = {
        "confirm":{'ACTIONMOUSE'}, # also 'RET' ?
        "cancel":{'SELECTMOUSE', 'ESC'},
        "free_mouse":{'F10'},
        "make_normal_snapshot":{'W'},
        "make_tangential_snapshot":{'Q'},
        "use_absolute_coords":{'A'},
        "snap_to_raw_mesh":{'D'},
        "use_object_centers":{'T'},
        "precision_up":{'PAGE_UP'},
Loading
Loading full blame...