1# ***** BEGIN GPL LICENSE BLOCK *****
2#
3#
4# This program is free software; you can redistribute it and/or
5# modify it under the terms of the GNU General Public License
6# as published by the Free Software Foundation; either version 2
7# of the License, or (at your option) any later version.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with this program; if not, write to the Free Software Foundation,
16# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17#
18# ***** END GPL LICENCE BLOCK *****
19#
20# -----------------------------------------------------------------------
21# Author: Alan Odom (Clockmender), Rune Morling (ermo) Copyright (c) 2019
22# -----------------------------------------------------------------------
23#
24import bpy
25from bpy.types import Panel
26from .pdt_msg_strings import (
27    PDT_LAB_ABS,
28    PDT_LAB_AD2D,
29    PDT_LAB_AD3D,
30    PDT_LAB_ALLACTIVE,
31    PDT_LAB_ANGLEVALUE,
32    PDT_LAB_ARCCENTRE,
33    PDT_LAB_BISECT,
34    PDT_LAB_CVALUE,
35    PDT_LAB_DEL,
36    PDT_LAB_DIR,
37    PDT_LAB_DISVALUE,
38    PDT_LAB_EDGETOEFACE,
39    PDT_LAB_FILLET,
40    PDT_LAB_FLIPANGLE,
41    PDT_LAB_FLIPPERCENT,
42    PDT_LAB_INTERSECT,
43    PDT_LAB_INTERSETALL,
44    PDT_LAB_JOIN2VERTS,
45    PDT_LAB_MODE,
46    PDT_LAB_NOR,
47    PDT_LAB_OPERATION,
48    PDT_LAB_ORDER,
49    PDT_LAB_ORIGINCURSOR,
50    PDT_LAB_PERCENT,
51    PDT_LAB_PERCENTS,
52    PDT_LAB_PIVOTALPHA,
53    PDT_LAB_PIVOTLOC,
54    PDT_LAB_PIVOTLOCH,
55    PDT_LAB_PIVOTSIZE,
56    PDT_LAB_PIVOTWIDTH,
57    PDT_LAB_PLANE,
58    PDT_LAB_PROFILE,
59    PDT_LAB_RADIUS,
60    PDT_LAB_SEGMENTS,
61    PDT_LAB_TAPER,
62    PDT_LAB_TAPERAXES,
63    PDT_LAB_TOOLS,
64    PDT_LAB_USEVERTS,
65    PDT_LAB_VARIABLES
66)
67
68def ui_width():
69    """Return the Width of the UI Panel.
70
71    Args:
72        None.
73
74    Returns:
75        UI Width.
76    """
77
78    area = bpy.context.area
79    resolution = bpy.context.preferences.system.ui_scale
80
81    for reg in area.regions:
82        if reg.type == "UI":
83            region_width = reg.width
84    return region_width
85
86# PDT Panel menus
87#
88class PDT_PT_PanelDesign(Panel):
89    bl_idname = "PDT_PT_PanelDesign"
90    bl_label = "PDT Design Operations"
91    bl_space_type = "VIEW_3D"
92    bl_region_type = "UI"
93    bl_category = "PDT"
94    bl_options = {'DEFAULT_CLOSED'}
95
96    def draw(self, context):
97        ui_cutoff = bpy.context.preferences.addons[__package__].preferences.pdt_ui_width
98        layout = self.layout
99        pdt_pg = context.scene.pdt_pg
100        #
101        # Working Plane
102        row = layout.row()
103        row.label(text=f"Working {PDT_LAB_PLANE}:")
104        row.prop(pdt_pg, "plane", text="")
105        #
106        # Move Mode
107        row = layout.row()
108        row.label(text=f"Move {PDT_LAB_MODE}:")
109        row.prop(pdt_pg, "select", text="")
110        #
111        # Active or All Selected
112        row = layout.row()
113        #row.label(text="")
114        row.prop(pdt_pg, "extend", text="All Selected Entities (Off: Active Only)")
115
116        # --------------------
117        # (1) Select Operation
118        row = layout.row()
119        box_1 = row.box()
120        row = box_1.row()
121        row.label(text=f"(1) Select {PDT_LAB_OPERATION}:")
122        row.prop(pdt_pg, "operation", text="")
123
124        # -----------------------
125        # (a) Set Coordinates box
126        row = box_1.row()
127        box_1a = row.box()
128        box_1a.label(text=f"(a) Either Set Coordinates + [Place »]")
129        # ^ was PDT_LAB_VARIABLES
130        #
131        # cartesian input coordinates in a box
132        row = box_1a.row()
133        box = row.box()
134        row = box.row()
135        split = row.split(factor=0.35, align=True)
136        split.label(text=PDT_LAB_CVALUE)
137        split.prop(pdt_pg, "cartesian_coords", text="")
138        row = box.row()
139        row.operator("pdt.absolute", icon="EMPTY_AXIS", text=f"{PDT_LAB_ABS} »")
140        row.operator("pdt.delta", icon="EMPTY_AXIS", text=f"{PDT_LAB_DEL} »")
141        #
142        # directional input coordinates in a box
143        row = box_1a.row()
144        box = row.box()
145        #box.label(text="Directional/Polar Coordinates:")
146        row = box.row()
147        row.prop(pdt_pg, "distance", text=PDT_LAB_DISVALUE)
148        row.prop(pdt_pg, "angle", text=PDT_LAB_ANGLEVALUE)
149        row = box.row()
150        row.operator("pdt.distance", icon="EMPTY_AXIS", text=f"{PDT_LAB_DIR} »")
151        row.prop(pdt_pg, "flip_angle", text=PDT_LAB_FLIPANGLE)
152
153        # ---------------------
154        # (b) Miscellaneous box
155        row = box_1.row()
156        box_1b = row.box()
157        box_1b.label(text="(b) Or Select |n| Entities + [Place »]")
158        #
159        # normal or arc centre
160        row = box_1b.row()
161        row.operator("pdt.normal", text=f"|3| {PDT_LAB_NOR} »")
162        row.operator("pdt.centre", text=f"|3| {PDT_LAB_ARCCENTRE} »")
163        #
164        # Intersect
165        box = box_1b.box()
166        row = box.row()
167        row.operator("pdt.intersect", text=f"|4| {PDT_LAB_INTERSECT} »")
168        if ui_width() < ui_cutoff:
169            row = box.row()
170        row.prop(pdt_pg, "object_order", text=PDT_LAB_ORDER)
171        #
172        # percentage row
173        row = box_1b.row()
174        box = row.box()
175        box.label(text=f"Do (1) at % between selected points")
176        row = box.row()
177        row.operator("pdt.percent", text=f"|2| % »")
178        row.prop(pdt_pg, "percent", text=PDT_LAB_PERCENTS)
179        if ui_width() < ui_cutoff:
180            row = box.row()
181        row.prop(pdt_pg, "flip_percent", text=PDT_LAB_FLIPPERCENT)
182
183class PDT_PT_PanelTools(Panel):
184    bl_idname = "PDT_PT_PanelTools"
185    bl_label = "PDT Design Tools"
186    bl_space_type = "VIEW_3D"
187    bl_region_type = "UI"
188    bl_category = "PDT"
189    bl_options = {'DEFAULT_CLOSED'}
190
191    def draw(self, context):
192        ui_cutoff = bpy.context.preferences.addons[__package__].preferences.pdt_ui_width
193        layout = self.layout
194        pdt_pg = context.scene.pdt_pg
195        # -----
196        # Tools
197        row = layout.row()
198        row.label(text=PDT_LAB_TOOLS)
199        row = layout.row()
200        row.operator("pdt.origin", text=PDT_LAB_ORIGINCURSOR)
201        row = layout.row()
202        row.operator("pdt.angle2", text=PDT_LAB_AD2D)
203        row.operator("pdt.angle3", text=PDT_LAB_AD3D)
204        row = layout.row()
205        row.operator("pdt.join", text=PDT_LAB_JOIN2VERTS)
206        row.operator("pdt.linetobisect", text=PDT_LAB_BISECT)
207        row = layout.row()
208        row.operator("pdt.edge_to_face", text=PDT_LAB_EDGETOEFACE)
209        row.operator("pdt.intersectall", text=PDT_LAB_INTERSETALL)
210        #
211        # Taper tool
212        box = layout.box()
213        row = box.row()
214        row.operator("pdt.taper", text=PDT_LAB_TAPER)
215        row.prop(pdt_pg, "taper", text=PDT_LAB_TAPERAXES)
216        #
217        # Fillet tool
218        box = layout.box()
219        row = box.row()
220        row.operator("pdt.fillet", text=f"{PDT_LAB_FILLET}")
221        row.prop(pdt_pg, "fillet_intersect", text="Intersect")
222        row = box.row()
223        row.prop(pdt_pg, "fillet_radius", text=PDT_LAB_RADIUS)
224        row.prop(pdt_pg, "fillet_profile", text=PDT_LAB_PROFILE)
225        row = box.row()
226        row.prop(pdt_pg, "fillet_segments", text=PDT_LAB_SEGMENTS)
227        row.prop(pdt_pg, "fillet_vertices_only", text=PDT_LAB_USEVERTS)
228
229
230class PDT_PT_PanelPivotPoint(Panel):
231    bl_idname = "PDT_PT_PanelPivotPoint"
232    bl_label = "PDT Pivot Point"
233    bl_space_type = "VIEW_3D"
234    bl_region_type = "UI"
235    bl_category = "PDT"
236    bl_options = {'DEFAULT_CLOSED'}
237
238    def draw(self, context):
239        ui_cutoff = bpy.context.preferences.addons[__package__].preferences.pdt_ui_width
240        pdt_pg = context.scene.pdt_pg
241        layout = self.layout
242        row = layout.row()
243        col = row.column()
244        if context.window_manager.pdt_run_opengl is False:
245            icon = "PLAY"
246            txt = "Show"
247        else:
248            icon = "PAUSE"
249            txt = "Hide"
250        col.operator("pdt.modaldraw", icon=icon, text=txt)
251        col = row.column()
252        col.prop(pdt_pg, "pivot_size", text=PDT_LAB_PIVOTSIZE)
253        if ui_width() < ui_cutoff:
254            row = layout.row()
255        col = row.column()
256        col.prop(pdt_pg, "pivot_width", text=PDT_LAB_PIVOTWIDTH)
257        col = row.column()
258        col.prop(pdt_pg, "pivot_alpha", text=PDT_LAB_PIVOTALPHA)
259        row = layout.row()
260        split = row.split(factor=0.35, align=True)
261        split.label(text=PDT_LAB_PIVOTLOCH)
262        split.prop(pdt_pg, "pivot_loc", text=PDT_LAB_PIVOTLOC)
263        row = layout.row()
264        col = row.column()
265        col.operator("pdt.pivotselected", icon="EMPTY_AXIS", text="Selection")
266        col = row.column()
267        col.operator("pdt.pivotcursor", icon="EMPTY_AXIS", text="Cursor")
268        col = row.column()
269        col.operator("pdt.pivotorigin", icon="EMPTY_AXIS", text="Origin")
270        row = layout.row()
271        col = row.column()
272        col.operator("pdt.viewplanerot", icon="EMPTY_AXIS", text="Rotate")
273        col = row.column()
274        col.prop(pdt_pg, "pivot_ang", text="Angle")
275        row = layout.row()
276        col = row.column()
277        col.operator("pdt.viewscale", icon="EMPTY_AXIS", text="Scale")
278        col = row.column()
279        col.operator("pdt.cursorpivot", icon="EMPTY_AXIS", text="Cursor To Pivot")
280        row = layout.row()
281        col = row.column()
282        col.prop(pdt_pg, "pivot_dis", text="Scale Distance")
283        col = row.column()
284        col.prop(pdt_pg, "distance", text="System Distance")
285        row = layout.row()
286        split = row.split(factor=0.35, align=True)
287        split.label(text="Scale")
288        split.prop(pdt_pg, "pivot_scale", text="")
289        row = layout.row()
290        col = row.column()
291        col.operator("pdt.pivotwrite", icon="FILE_TICK", text="PP Write")
292        col = row.column()
293        col.operator("pdt.pivotread", icon="FILE", text="PP Read")
294
295
296class PDT_PT_PanelPartsLibrary(Panel):
297    bl_idname = "PDT_PT_PanelPartsLibrary"
298    bl_label = "PDT Parts Library"
299    bl_space_type = "VIEW_3D"
300    bl_region_type = "UI"
301    bl_category = "PDT"
302    bl_options = {'DEFAULT_CLOSED'}
303
304    def draw(self, context):
305        ui_cutoff = context.preferences.addons[__package__].preferences.pdt_ui_width
306        layout = self.layout
307        pdt_pg = context.scene.pdt_pg
308        row = layout.row()
309        row.prop(pdt_pg, "pdt_library_path")
310        row = layout.row()
311        col = row.column()
312        col.operator("pdt.append", text="Append")
313        col = row.column()
314        col.operator("pdt.link", text="Link")
315        if ui_width() < ui_cutoff:
316            row = layout.row()
317        col = row.column()
318        col.prop(pdt_pg, "lib_mode", text="")
319        box = layout.box()
320        row = box.row()
321        col = row.column()
322        col.label(text="Objects")
323        col = row.column()
324        col.prop(pdt_pg, "object_search_string")
325        row = box.row()
326        row.prop(pdt_pg, "lib_objects", text="")
327        box = layout.box()
328        row = box.row()
329        col = row.column()
330        col.label(text="Collections")
331        col = row.column()
332        col.prop(pdt_pg, "collection_search_string")
333        row = box.row()
334        row.prop(pdt_pg, "lib_collections", text="")
335        box = layout.box()
336        row = box.row()
337        col = row.column()
338        col.label(text="Materials")
339        col = row.column()
340        col.prop(pdt_pg, "material_search_string")
341        row = box.row()
342        row.prop(pdt_pg, "lib_materials", text="")
343        row = box.row()
344        #row.operator("pdt.lib_show", text="Load Library File", icon='INFO')
345
346
347class PDT_PT_PanelViewControl(Panel):
348    bl_idname = "PDT_PT_PanelViewControl"
349    bl_label = "PDT View Control"
350    bl_space_type = "VIEW_3D"
351    bl_region_type = "UI"
352    bl_category = "PDT"
353    bl_options = {'DEFAULT_CLOSED'}
354
355    # Sub-layout highlight states
356    _ui_groups = [False, False]
357
358    def draw(self, context):
359        ui_cutoff = context.preferences.addons[__package__].preferences.pdt_ui_width
360        layout = self.layout
361        ui_groups = self._ui_groups
362        pdt_pg = context.scene.pdt_pg
363        box = layout.box()
364        row = box.row()
365        col = row.column()
366        col.label(text="View Rotation")
367        col = row.column()
368        col.operator("pdt.viewrot", text="Rotate Abs")
369        row = box.row()
370        split = row.split(factor=0.35, align=True)
371        split.label(text="Rotation")
372        split.prop(pdt_pg, "rotation_coords", text="")
373        row = box.row()
374        col = row.column()
375        col.prop(pdt_pg, "vrotangle", text="Angle")
376        if ui_width() < ui_cutoff:
377            row = box.row()
378        col = row.column()
379        col.operator("pdt.viewleft", text="", icon="TRIA_LEFT")
380        col = row.column()
381        col.operator("pdt.viewright", text="", icon="TRIA_RIGHT")
382        col = row.column()
383        col.operator("pdt.viewup", text="", icon="TRIA_UP")
384        col = row.column()
385        col.operator("pdt.viewdown", text="", icon="TRIA_DOWN")
386        col = row.column()
387        col.operator("pdt.viewroll", text="", icon="RECOVER_LAST")
388        row = box.row()
389        col = row.column()
390        col.operator("pdt.viewiso", text="Isometric")
391        col = row.column()
392        col.operator("pdt.reset_3d_view", text="Reset View")
393
394
395class PDT_PT_PanelCommandLine(Panel):
396    bl_idname = "PDT_PT_PanelCommandLine"
397    bl_label = "PDT Command Line (? for help)"
398    bl_space_type = "VIEW_3D"
399    bl_region_type = "UI"
400    bl_category = "PDT"
401    bl_options = {'DEFAULT_CLOSED'}
402
403    def draw(self, context):
404        layout = self.layout
405        pdt_pg = context.scene.pdt_pg
406        row = layout.row()
407        col = row.column()
408        col.prop(pdt_pg, "plane", text="Plane")
409        col = row.column()
410        col.prop(pdt_pg, "select", text="Mode")
411        row = layout.row()
412        row.label(text="Comand Line, uses Plane & Mode Options")
413        row = layout.row()
414        row.prop(pdt_pg, "command", text="")
415        # Try Re-run
416        row.operator("pdt.command_rerun", text="", icon="LOOP_BACK")
417        row = layout.row()
418        row.prop(pdt_pg, "maths_output", text="Maths Output")
419
420class PDT_PT_PanelTangent(Panel):
421    bl_idname = "PDT_PT_PanelTangent"
422    bl_label = "PDT Tangents"
423    bl_space_type = "VIEW_3D"
424    bl_region_type = "UI"
425    bl_category = "PDT"
426    bl_options = {'DEFAULT_CLOSED'}
427
428    def draw(self,context):
429        layout = self.layout
430        pdt_pg = context.scene.pdt_pg
431
432        if pdt_pg.menu_expand:
433            icon_e = "EVENT_C"
434        else:
435            icon_e = "EVENT_E"
436        row = layout.row()
437        row.label(text=f"Working {PDT_LAB_PLANE}:")
438        row.prop(pdt_pg, "plane", text="")
439        row = layout.row()
440        row.label(text="Tan Mode")
441        row.prop(pdt_pg, "tangent_mode", text="")
442        row = layout.row()
443        row.operator("pdt.tangentoperatesel", text="Tangents from Selection", icon="NONE")
444        row = layout.row()
445        row.label(text="Or Use Tangents From Inputs")
446        row.operator("pdt.tangentexpandmenu", text="", icon=icon_e)
447
448        box = layout.box()
449        row = box.row()
450        split = row.split(factor=0.35, align=True)
451        split.label(text="Tan Point")
452        split.prop(pdt_pg, "tangent_point2", text="")
453        row = box.row()
454        row.operator("pdt.tangentset3", text="from Cursor")
455        row.operator("pdt.tangentset4", text="from Vertex")
456
457        if pdt_pg.menu_expand:
458            box = layout.box()
459            row = box.row()
460            split = row.split(factor=0.35, align=True)
461            split.label(text="Centre 1")
462            split.prop(pdt_pg, "tangent_point0", text="")
463            row = box.row()
464            split = row.split(factor=0.45, align=False)
465            split.operator("pdt.tangentset1", text="Set From Arc")
466            split.prop(pdt_pg, "tangent_radius0", text="")
467
468            # Second Centre & Radius
469            row = box.row()
470            split = row.split(factor=0.35, align=True)
471            split.label(text="Centre 2")
472            split.prop(pdt_pg, "tangent_point1", text="")
473            row = box.row()
474            split = row.split(factor=0.45, align=False)
475            split.operator("pdt.tangentset2", text="Set From Arc")
476            split.prop(pdt_pg, "tangent_radius1", text="")
477            row = box.row()
478            row.operator("pdt.tangentoperate", text="Tangents From Inputs", icon="NONE")
479
480class PDT_PT_PanelTrig(Panel):
481    bl_idname = "PDT_PT_PanelTrig"
482    bl_label = "PDT Trigonometrical Waves"
483    bl_space_type = "VIEW_3D"
484    bl_region_type = "UI"
485    bl_category = "PDT"
486    bl_options = {'DEFAULT_CLOSED'}
487
488    def draw(self,context):
489        layout = self.layout
490        pdt_pg = context.scene.pdt_pg
491        row = layout.row()
492        row.label(text=f"Working {PDT_LAB_PLANE}:")
493        row.prop(pdt_pg, "plane", text="")
494
495        row = layout.row()
496        split = row.split(factor=0.5, align=True)
497        split.prop(pdt_pg, "trig_type")
498        split.prop(pdt_pg, "trig_cycles")
499        row = layout.row()
500        split = row.split(factor=0.5, align=True)
501        split.prop(pdt_pg, "trig_amp")
502        split.prop(pdt_pg, "trig_len")
503        row = layout.row()
504        split = row.split(factor=0.5, align=True)
505        split.prop(pdt_pg, "trig_obj", text="")
506        split.prop(pdt_pg, "trig_del")
507        row = layout.row()
508        split = row.split(factor=0.5, align=True)
509        split.prop(pdt_pg, "trig_res")
510        split.prop(pdt_pg, "trig_tanmax")
511        row = layout.row()
512        row.prop(pdt_pg, "trig_off")
513        row = layout.row()
514        row.operator("pdt.wave_generator", icon="SEQ_LUMA_WAVEFORM")
515        row.prop(pdt_pg, "trig_abs")
516