Skip to content

Commit e44366d

Browse files
authored
Version 2.2.1
Version 2.2.1
2 parents 2b2e633 + f93df95 commit e44366d

File tree

4 files changed

+145
-34
lines changed

4 files changed

+145
-34
lines changed

__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"name": "Script To Button",
77
"author": "RivinHD",
88
"blender": (3, 3, 10),
9-
"version": (2, 2, 0),
9+
"version": (2, 2, 1),
1010
"location": "View3D",
1111
"category": "System",
1212
"doc_url": "https://github.com/RivinHD/ScriptToButton/wiki",

functions.py

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import os
22
import bpy
33
import zipfile
4+
import uuid
45
from bpy.props import StringProperty, PointerProperty
56
from bpy.types import PropertyGroup, Context, UILayout, Text, AddonPreferences, Scene
67
from typing import TYPE_CHECKING, Union
@@ -90,7 +91,7 @@ def load(context: Context) -> tuple[list, list]:
9091
return btnFails
9192

9293

93-
def get_all_button_names(context: Context) -> list:
94+
def get_all_button_names(context: Context) -> set:
9495
return set(button.name for button in context.scene.stb)
9596

9697

@@ -132,6 +133,7 @@ def get_areas(text: str) -> list:
132133
"Image_Editor": "VIEW",
133134
"Compositor": "CompositorNodeTree",
134135
"Texture_Node_Editor": "TextureNodeTree",
136+
"Geomerty_Node_Editor": "GeometryNodeTree",
135137
"Shader_Editor": "ShaderNodeTree",
136138
"Video_Sequencer": "SEQUENCE_EDITOR",
137139
"Movie_Clip_Editor": "CLIP_EDITOR",
@@ -152,8 +154,8 @@ def get_props(text: str) -> list:
152154
lines = text.splitlines()
153155
props = []
154156
for i in range(len(lines)):
155-
current_line = lines[i]
156-
if not current_line.strip().startswith("#STB-"):
157+
current_line = lines[i].strip()
158+
if not current_line.startswith("#STB-") or current_line.startswith("#STB-Area"):
157159
continue
158160
next_line = lines[i + 1]
159161
if next_line.startswith("#"):
@@ -392,7 +394,7 @@ def remove_button(context: Context, delete_file: bool, delete_text: bool):
392394
"%s.py" % name
393395
))
394396
if delete_text:
395-
if index := bpy.data.texts.find(name) != -1:
397+
if (index := bpy.data.texts.find(name)) != -1:
396398
bpy.data.texts.remove(bpy.data.texts[index])
397399
delete_vector_props(button)
398400
delete_list_prop(button)
@@ -527,18 +529,19 @@ def update_vector_property(self, context):
527529

528530
def create_vector_prop(size: int, name: str, type: str, back_address: str):
529531
property_func = getattr(bpy.props, "%sProperty" % type)
532+
vec_id = uuid.uuid5(uuid.NAMESPACE_OID, name).hex
530533

531534
class VectorProp(PropertyGroup):
532535
prop: property_func(size=size, update=update_vector_property)
533536
address: StringProperty(default=back_address)
534-
VectorProp.__name__ = "VectorProp_%s_%s" % (type, name)
537+
VectorProp.__name__ = "VectorProp_%s_%s" % (type, vec_id)
535538
bpy.utils.register_class(VectorProp)
536539
setattr(
537540
bpy.types.Scene,
538-
"stb_%sproperty_%s" % (type.lower(), name),
541+
"stb_%sproperty_%s" % (type.lower(), vec_id),
539542
PointerProperty(type=VectorProp)
540543
)
541-
return "bpy.context.scene.stb_%sproperty_%s" % (type.lower(), name)
544+
return "bpy.context.scene.stb_%sproperty_%s" % (type.lower(), vec_id)
542545

543546

544547
def unregister_vector():
@@ -631,7 +634,6 @@ def export(mode, selections: list, export_path: str) -> None:
631634

632635

633636
def import_zip(filepath: str, context: Context) -> tuple[list, list]:
634-
STB_pref = get_preferences(context)
635637
btnFails = ([], [])
636638
with zipfile.ZipFile(filepath, 'r') as zip_out:
637639
filepaths = []
@@ -640,31 +642,31 @@ def import_zip(filepath: str, context: Context) -> tuple[list, list]:
640642
filepaths.append(i)
641643
for filepath in filepaths:
642644
txt = zip_out.read(filepath).decode("utf-8").replace("\r", "")
643-
Fail = import_button(filepath, context, STB_pref, txt)
645+
Fail = import_button(filepath, context, txt)
644646
btnFails[0].extend(Fail[0])
645647
btnFails[1].append(Fail[1])
646648
return btnFails
647649

648650

649651
def import_py(filepath: str, context: Context) -> tuple[list[str], tuple[list, list]]:
650-
STB_pref = get_preferences(context)
651652
with open(filepath, 'r', encoding='utf8') as file:
652653
txt = file.read()
653-
return import_button(filepath, context, STB_pref, txt)
654+
return import_button(filepath, context, txt)
654655

655656

656657
def import_button(
657658
filepath: str,
658659
context: Context,
659660
txt: str) -> tuple[list[str], tuple[list, list]]:
660661
STB_pref = get_preferences(context)
662+
stb = context.scene.stb
661663
name = check_for_duplicates(
662-
[i.name for i in bpy.data.texts],
664+
get_all_button_names(context),
663665
os.path.splitext(os.path.basename(filepath))[0]
664666
)
665667
bpy.data.texts.new(name)
666668
bpy.data.texts[name].write(txt)
667-
button: STB_button_properties = context.scene.stb.add()
669+
button: STB_button_properties = stb.add()
668670
button.name = name
669671
button.selected = True
670672

@@ -708,7 +710,7 @@ def rename(context: Context, name: str):
708710
old_path = os.path.join(directory, "Storage", "%s.py" %
709711
STB_pref.selected_button)
710712
if name != button.name:
711-
name = check_for_duplicates(get_all_button_names(context), name)
713+
name = check_for_duplicates(get_all_button_names(context).difference([button.name]), name)
712714
button.name = name
713715
button.selected = True
714716
text.name = name

operators.py

Lines changed: 110 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import typing
22
import bpy
3-
from bpy.types import Operator, Context, Event, PropertyGroup
3+
from bpy.types import Operator, Context, Event, PropertyGroup, UILayout
44
from bpy.props import StringProperty, EnumProperty, BoolProperty, CollectionProperty
55
from bpy_extras.io_utils import ImportHelper, ExportHelper
66
from . functions import get_preferences
@@ -423,7 +423,7 @@ def execute(self, context: Context):
423423
return {'CANCELLED'}
424424
functions.export(
425425
self.mode,
426-
map(lambda x: x.use, self.export_buttons),
426+
filter(lambda x: x.use, self.export_buttons),
427427
self.filepath
428428
)
429429
return {"FINISHED"}
@@ -493,27 +493,108 @@ class STB_OT_Edit(Operator):
493493
bl_description = "Edit the selected Button"
494494
bl_options = {"UNDO"}
495495

496+
area_items = [ # (identifier, name, description, icon, value)
497+
('', 'General', '', ''),
498+
('3D_Viewport', '3D Viewport', '', 'VIEW3D'),
499+
('Image_Editor', 'Image Editor', '', 'IMAGE'),
500+
('UV_Editor', 'UV Editor', '', 'UV'),
501+
('Compositor', 'Compositor', '', 'NODE_COMPOSITING'),
502+
('Texture_Node_Editor', 'Texture Node Editor', '', 'NODE_TEXTURE'),
503+
('Geomerty_Node_Editor', 'Geomerty Node Editor', '', 'NODETREE'),
504+
('Shader_Editor', 'Shader Editor', '', 'NODE_MATERIAL'),
505+
('Video_Sequencer', 'Video Sequencer', '', 'SEQUENCE'),
506+
('Movie_Clip_Editor', 'Movie Clip Editor', '', 'TRACKER'),
507+
508+
('', 'Animation', '', ''),
509+
('Dope_Sheet', 'Dope Sheet', '', 'ACTION'),
510+
('Timeline', 'Timeline', '', 'TIME'),
511+
('Graph_Editor', 'Graph Editor', '', 'GRAPH'),
512+
('Drivers', 'Drivers', '', 'DRIVER'),
513+
('Nonlinear_Animation', 'Nonlinear Animation', '', 'NLA'),
514+
515+
('', 'Scripting', '', ''),
516+
('Text_Editor', 'Text Editor', '', 'TEXT')
517+
]
518+
496519
name: StringProperty(name="Name")
497520
stb_properties: CollectionProperty(type=properties.STB_edit_property_item)
498521

522+
def items_stb_select_area(self, context: Context):
523+
for item in self.stb_areas:
524+
if item.delete:
525+
self.stb_areas.remove(self.stb_areas.find(item.name))
526+
used_areas = set(area.name for area in self.stb_areas)
527+
areas = []
528+
for i, (identifier, name, description, icon) in enumerate(STB_OT_Edit.area_items):
529+
if identifier in used_areas:
530+
continue
531+
areas.append((
532+
identifier,
533+
name,
534+
description,
535+
icon,
536+
i * (identifier != '') - 1
537+
))
538+
return areas
539+
stb_select_area: EnumProperty(items=items_stb_select_area, default=0)
540+
stb_areas: CollectionProperty(type=properties.STB_edit_area_item)
541+
542+
def get_add_area(self):
543+
return False
544+
545+
def set_add_area(self, value):
546+
identifier = self.stb_select_area
547+
icon = UILayout.enum_item_icon(self, 'stb_select_area', identifier)
548+
label = UILayout.enum_item_name(self, 'stb_select_area', identifier)
549+
if identifier == '':
550+
return
551+
new = self.stb_areas.add()
552+
new.name = identifier
553+
new.label = label
554+
new.icon = icon
555+
items = STB_OT_Edit.items_stb_select_area(self, bpy.context)
556+
for item in items:
557+
if item[0] == '':
558+
continue
559+
self.stb_select_area = item[0]
560+
break
561+
add_area: BoolProperty(default=False, get=get_add_area, set=set_add_area)
562+
499563
def draw(self, context: Context):
500564
layout = self.layout
501565
layout.prop(self, 'name')
502566

503567
layout.separator(factor=0.5)
504-
layout.label(text="Properties")
568+
layout.label(text="Areas")
569+
row = layout.row(align=True)
570+
row.prop(self, 'stb_select_area')
571+
row.prop(self, 'add_area', icon="ADD", icon_only=True)
505572
box = layout.box()
506-
for prop in filter(lambda x: not x.use_delete, self.stb_properties):
507-
row = box.row()
508-
row.label(text=f"{prop.name} [Ln {prop.line}]")
509-
row.prop(prop, 'use_delete', icon='X', icon_only=True, emboss=False)
573+
if len(self.stb_areas):
574+
for area in filter(lambda x: not x.delete, self.stb_areas):
575+
row = box.row()
576+
row.label(text=area.label, icon_value=area.icon)
577+
row.prop(area, 'delete', icon='X', icon_only=True, emboss=False)
578+
else:
579+
box.label(text="All Areas", icon='RESTRICT_COLOR_ON')
580+
581+
properties = list(filter(lambda x: not x.use_delete, self.stb_properties))
582+
if len(properties):
583+
layout.separator(factor=0.5)
584+
layout.label(text="Properties")
585+
box = layout.box()
586+
for prop in properties:
587+
row = box.row()
588+
row.label(text=f"{prop.name} [Ln {prop.line}]")
589+
row.prop(prop, 'use_delete', icon='X', icon_only=True, emboss=False)
510590

511591
def invoke(self, context, event):
512592
STB_pref = get_preferences(context)
513593
stb = context.scene.stb
514594
button = stb[STB_pref.selected_button]
515595
self.name = button.name
516596
self.stb_properties.clear()
597+
self.stb_areas.clear()
517598
for prop in functions.get_all_properties(button):
518599
new = self.stb_properties.add()
519600
new.name = prop.name
@@ -525,9 +606,7 @@ def execute(self, context):
525606
functions.rename(context, self.name)
526607

527608
STB_pref = get_preferences(context)
528-
stb = context.scene.stb
529609
property_changed = False
530-
button = stb[STB_pref.selected_button]
531610

532611
text_index = bpy.data.texts.find(STB_pref.selected_button)
533612
if text_index == -1:
@@ -537,22 +616,35 @@ def execute(self, context):
537616
text = bpy.data.texts[text_index]
538617
lines = [line.body for line in text.lines]
539618

619+
if len(self.stb_areas):
620+
property_changed = True
621+
if lines[0].strip().startswith("#STB"):
622+
line = lines[0]
623+
line += " /// "
624+
else:
625+
line = ""
626+
lines.insert(0, line)
627+
line += " /// ".join(map(lambda x: "#STB-Area-%s" % x.name, self.stb_areas))
628+
lines[0] = line
629+
630+
edited_lines = []
540631
for prop in filter(lambda x: x.use_delete, self.stb_properties):
541632
property_changed = True
542633
line: str = lines[prop.line - 1]
543634
line_start = line.find("#STB")
544635
if line_start == -1:
545636
continue
546-
637+
547638
if (init_start_position := line.find("#STB-InitValue-")) != -1:
548639
init_start_position += len("#STB-InitValue-")
549640
init_end_position = line.find("-END", init_start_position)
550641
init_value = line[init_start_position: init_end_position]
551-
lines[prop.line] = "%s= %s" %(prop.linename, init_value)
552-
642+
lines[prop.line] = "%s= %s" % (prop.linename, init_value)
643+
553644
and_position = line.find("///", line_start)
554645
end_position = line.find("#STB", and_position)
555-
while (and_next := line.find("///", end_position)) != -1 and (end_next := line.find("#STB", and_next)) != -1:
646+
while ((and_next := line.find("///", end_position)) != -1
647+
and (end_next := line.find("#STB", and_next)) != -1):
556648
and_position = and_next
557649
end_position = end_next
558650

@@ -567,8 +659,12 @@ def execute(self, context):
567659
line = line[:line_start] + line[line_end:]
568660

569661
lines[prop.line - 1] = line
662+
edited_lines.append(prop.line - 1)
663+
664+
for i in sorted(edited_lines, reverse=True):
665+
line = lines[i]
570666
if line.strip() == "":
571-
lines.pop(prop.line - 1)
667+
lines.pop(i)
572668

573669
if property_changed:
574670
text.clear()

properties.py

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
)
77
from .functions import update_text
88
from . import functions
9+
from contextlib import suppress
910

1011
classes = []
1112

@@ -248,14 +249,22 @@ class STB_add_property_item(PropertyGroup):
248249
line: StringProperty()
249250
value: StringProperty()
250251
type: StringProperty()
251-
252+
253+
252254
class STB_edit_property_item(PropertyGroup):
253255
name: StringProperty()
254256
line: IntProperty()
255257
linename: StringProperty()
256258
use_delete: BoolProperty(default=False)
257259

258260

261+
class STB_edit_area_item(PropertyGroup):
262+
name: StringProperty()
263+
label: StringProperty()
264+
icon: IntProperty()
265+
delete: BoolProperty(default=False)
266+
267+
259268
classes = [
260269
STB_property_string,
261270
STB_property_int,
@@ -273,7 +282,8 @@ class STB_edit_property_item(PropertyGroup):
273282
STB_text_property,
274283
STB_export_button,
275284
STB_add_property_item,
276-
STB_edit_property_item
285+
STB_edit_property_item,
286+
STB_edit_area_item
277287
]
278288

279289

@@ -286,11 +296,14 @@ def register():
286296
def unregister():
287297
for ele in bpy.context.scene.stb:
288298
for intvec in ele.IntVectorProps:
289-
exec("del bpy.types.Scene.%s" % intvec.address.split(".")[-1])
299+
with suppress(AttributeError):
300+
exec("del bpy.types.Scene.%s" % intvec.address.split(".")[-1])
290301
for floatvec in ele.FloatVectorProps:
291-
exec("del bpy.types.Scene.%s" % floatvec.address.split(".")[-1])
302+
with suppress(AttributeError):
303+
exec("del bpy.types.Scene.%s" % floatvec.address.split(".")[-1])
292304
for boolvec in ele.BoolVectorProps:
293-
exec("del bpy.types.Scene.%s" % boolvec.address.split(".")[-1])
305+
with suppress(AttributeError):
306+
exec("del bpy.types.Scene.%s" % boolvec.address.split(".")[-1])
294307
for cls in classes:
295308
bpy.utils.unregister_class(cls)
296309
del bpy.types.Scene.stb

0 commit comments

Comments
 (0)