Welcome to mirror list, hosted at ThFree Co, Russian Federation.

widgets.py « mesh_snap_utilities_line - git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 6f8639e0cdc7cd4d88329ba84da3e70b482f41cb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
### 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 #####

import bpy

from .common_classes import SnapUtilities
from .common_utilities import snap_utilities
from .drawing_utilities import SnapDrawn


#def mesh_runtime_batchcache_isdirty(me):
#    import ctypes
#    batch_cache = ctypes.c_void_p.from_address(me.as_pointer() + 1440)
#    if batch_cache:
#        return ctypes.c_bool.from_address(batch_cache.value + 549).value
#    return False


class SnapWidgetCommon(SnapUtilities):
    snap_to_update = False

    def handler(self, scene):
        cls = SnapWidgetCommon
        if cls.snap_to_update is False:
            last_operator = self.wm_operators[-1] if self.wm_operators else None
            if (not last_operator or
                last_operator.name not in {'Select', 'Loop Select', '(De)select All'}):
                    cls.snap_to_update = self.depsgraph.id_type_updated('MESH') or\
                                         self.depsgraph.id_type_updated('OBJECT')

    def draw_point_and_elem(self):
        if self.bm:
            if self.bm.is_valid and self.geom.is_valid:
                self.draw_cache.draw_elem(self.snap_obj, self.bm, self.geom)
            else:
                self.bm = None
                self.geom = None
                self.sctx.update_all()

        self.draw_cache.draw(self.type, self.location, None, None, None)

    def init_snapwidget(self, context, snap_edge_and_vert = True):
        self.snap_context_init(context, snap_edge_and_vert)
        self.snap_context_update(context)
        self.mode = context.mode
        self.last_mval = None

        self.wm_operators = context.window_manager.operators
        self.depsgraph = context.depsgraph
        bpy.app.handlers.depsgraph_update_post.append(self.handler)
        SnapWidgetCommon.snap_to_update = False

        SnapUtilities.snapwidgets.append(self)

    def end_snapwidget(self):
        SnapUtilities.snapwidgets.remove(self)

        #from .snap_context_l import global_snap_context_get
        #sctx = global_snap_context_get(None, None, None)

        sctx = object.__getattribute__(self, 'sctx')
        if sctx and not SnapUtilities.snapwidgets:
            sctx.clear_snap_objects()

        handler = object.__getattribute__(self, 'handler')
        bpy.app.handlers.depsgraph_update_post.remove(handler)

    def update_snap(self, context, mval):
        if self.last_mval == mval:
            return -1
        else:
            self.last_mval = mval

        if (SnapWidgetCommon.snap_to_update):
            ## Something has changed since the last time.
            # Has the mesh been changed?
            # In the doubt lets clear the snap context.
            self.snap_context_update(context)
            SnapWidgetCommon.snap_to_update = False

        #print('test_select', mval)
        space = context.space_data
        self.sctx.update_viewport_context(context.depsgraph, context.region, space, True)

        shading = space.shading
        snap_face = not ((self.snap_vert or self.snap_edge) and
                        (shading.show_xray or shading.type == 'WIREFRAME'))

        if snap_face != self.snap_face:
            self.snap_face = snap_face
            self.sctx.set_snap_mode(
                     self.snap_vert, self.snap_edge, self.snap_face)

        snap_utilities.edge_cache.snp_obj = None # hack for snap edge elemens update
        self.snap_obj, prev_loc, self.location, self.type, self.bm, self.geom, len = snap_utilities(
                self.sctx,
                None,
                mval,
                increment=self.incremental
        )


class SnapPointWidget(SnapWidgetCommon, bpy.types.Gizmo):
    bl_idname = "VIEW3D_GT_snap_point"

    def test_select(self, context, mval):
        self.update_snap(context, mval)
        self.snap_to_grid()

        context.area.tag_redraw()
        return -1

    def draw(self, context):
        self.draw_point_and_elem()

    def setup(self):
        self.init_snapwidget(bpy.context)


class SnapFaceWidget(SnapWidgetCommon, bpy.types.Gizmo):
    bl_idname = "VIEW3D_GT_snap_face_point"

    def test_select(self, context, mval):
        self.update_snap(context, mval)
        self.snap_to_grid()

        context.area.tag_redraw()
        return -1

    def draw(self, context):
        self.draw_point_and_elem()

    def setup(self):
        self.init_snapwidget(bpy.context, False)


class SnapCircleWidget(SnapWidgetCommon, bpy.types.Gizmo):
    bl_idname = "VIEW3D_GT_snap_circle"

    from mathutils import Vector
    zero_vector = Vector()
    default_normal = Vector((0.0, 0.0, 1.0))

    def get_normal(self, context):
        if self.constrain:
            return

        view_vector, orig = self.sctx.last_ray
        if not self.rv3d.is_perspective:
            #temporary hack
            orig -= view_vector * 100

        normal_face = context.scene.ray_cast(context.view_layer, orig, view_vector)[2]
        if normal_face and normal_face != self.zero_vector:
            self.normal = normal_face
        else:
            self.normal = self.default_normal

    def test_select(self, context, mval):
        self.update_snap(context, mval)
        self.snap_to_grid()
        self.get_normal(context)

        context.area.tag_redraw()
        return -1

    def draw(self, context):
        self.draw_point_and_elem()
        self.draw_cache.draw_rot_tool(
                self.rv3d.view_distance / 15,
                self.location, self.normal, None)

    def setup(self):
        context = bpy.context
        self.init_snapwidget(context)
        self.rv3d = context.region_data
        self.normal = self.default_normal


def context_mode_check(context, widget_group):
    workspace = context.workspace
    mode = workspace.tools_mode
    for tool in workspace.tools:
        if (tool.widget == widget_group) and (tool.mode == mode):
            break
    else:
        context.window_manager.gizmo_group_type_unlink_delayed(widget_group)
        return False
    return True


class SnapWidgetGroupCommon:
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'WINDOW'
    bl_options = {'3D'}

    @classmethod
    def poll(cls, context):
        return context_mode_check(context, cls.bl_idname)

    def init_tool(self, context, gizmo_name):
        self.widget = self.gizmos.new(gizmo_name)

    def __del__(self):
        if hasattr(self, "widget"):
            object.__getattribute__(self.widget, 'end_snapwidget')()


class SnapPointWidgetGroup(SnapWidgetGroupCommon, bpy.types.GizmoGroup):
    bl_idname = "MESH_GGT_snap_point"
    bl_label = "Draw Snap Point"

    def setup(self, context):
        self.init_tool(context, SnapPointWidget.bl_idname)


class SnapCircleWidgetGroup(SnapWidgetGroupCommon, bpy.types.GizmoGroup):
    bl_idname = "MESH_GGT_snap_circle"
    bl_label = "Draw Snap Circle"

    def setup(self, context):
        self.init_tool(context, SnapCircleWidget.bl_idname)


class SnapFaceWidgetGroup(SnapWidgetGroupCommon, bpy.types.GizmoGroup):
    bl_idname = "MESH_GGT_face_snap_point"
    bl_label = "Draw Face and Snap Point"

    def setup(self, context):
        self.init_tool(context, SnapFaceWidget.bl_idname)