From 2e66c1817595fcdcf76e0a6850ca897b84cb3720 Mon Sep 17 00:00:00 2001 From: dupoxy Date: Sat, 20 Jan 2024 07:12:21 +0100 Subject: [PATCH 1/6] Update README.md --- README.md | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6e35798..40a4ab5 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,41 @@ -# 3d_cursors_briefcase +# 🌟 Welcome to 3D Cursors Briefcase 💼. +Take control of your 3D cursor in Blender like never before! +With 3D Cursors Briefcase, you can save, load, and manage multiple 3D cursors. +Try it today and launch your 3D Cursors experience! 🚀 + + +# ⚙️ Installation: +- [Download](3D-Cursor-Briefcase.py) the Python script for the add-on. +- Open Blender and go to `Edit > Preferences`. +- In the Preferences window, click on the `Add-ons` tab. +- Click on `Install...` and navigate to the downloaded Python script. +- Click on `Install Add-on` and make sure to enable the add-on by checking the box next to it. + +# 📖 User guide: + + +- **Go to** `View3D > Sidebar > View Tab`. + - In the `3D Cursors 💼` panel. + +![user interface](3d-cursor-case-guide.png "user interface") +1. **Saving a 3D Cursor:** + - Position your 3D cursor in the desired location and rotation. + - Click on the `+` button. This will save the current position and rotation of the 3D cursor. + +2. **Deleting a 3D Cursor:** + - Select the saved 3D cursor from the list. + - Click on the `-` button. This will remove the selected 3D cursor from the list. + +3. **Moving a 3D Cursor Up/Down in the List:** + - Select the saved 3D cursor from the list. + - Click on the `🞁` or `🞃` button to change the order of the selected 3D cursor in the list. + +4. **Loading a 3D Cursor:** + - Select the saved 3D cursor from the list. + - Click on the `Load` button. This will move the 3D cursor to the saved location and rotation. + +5. **Going to a 3D Cursor:** + - Click on the `Centre View` button. Centers the view on the 3D Cursor. + +[LICENSE](LICENSE) -- 2.30.2 From e33ef17732140097177472926ef5ea3c88fda768 Mon Sep 17 00:00:00 2001 From: dupoxy Date: Sat, 20 Jan 2024 07:18:03 +0100 Subject: [PATCH 2/6] Upload files to "/" --- 3D-Cursors-Briefcase.py | 135 ++++++++++++++++++++++++++++++++++++++ 3d-cursors-case-guide.png | Bin 0 -> 11809 bytes 2 files changed, 135 insertions(+) create mode 100644 3D-Cursors-Briefcase.py create mode 100644 3d-cursors-case-guide.png diff --git a/3D-Cursors-Briefcase.py b/3D-Cursors-Briefcase.py new file mode 100644 index 0000000..e323e1c --- /dev/null +++ b/3D-Cursors-Briefcase.py @@ -0,0 +1,135 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +bl_info = { + "name": "3D Cursors Briefcase", + "author": "twist-lab", + "version": (0, 0, 1), + "blender": (2, 80, 0), + "location": "View3D > Sidebar > View Tab", + "description": "A place to store 3D Cursors", + "warning": "", + "doc_url": "TODO", #"{BLENDER_MANUAL_URL}/addons/3d_view/3d_navigation.html" + "category": "3D View", +} + +import bpy + + +class Cursor3dProperties(bpy.types.PropertyGroup): + location: bpy.props.FloatVectorProperty(name="Location") + rotation: bpy.props.FloatVectorProperty(name="Rotation") + + +class SCENE_OT_save_cursor(bpy.types.Operator): + bl_idname = "scene.save_cursor" + bl_label = "Save" + bl_description = "Save 3D Cursor location and rotation" + + def execute(self, context): + item = context.scene.cursors3d_collection.add() + item.name = "3D Cursor" + item.location = context.scene.cursor.location + item.rotation = context.scene.cursor.rotation_euler + return {'FINISHED'} + + +class SCENE_OT_restore_cursor(bpy.types.Operator): + bl_idname = "scene.restore_cursor" + bl_label = "Load" + bl_description = "Restore selected 3D Cursor" + + @classmethod + def poll(cls, context): + return bool(context.scene.cursors3d_collection) and context.scene.cursors3d_index < len(context.scene.cursors3d_collection) + + def execute(self, context): + if context.scene.cursors3d_collection: + item = context.scene.cursors3d_collection[context.scene.cursors3d_index] + context.scene.cursor.location = item.location + context.scene.cursor.rotation_euler = item.rotation + return {'FINISHED'} + + +class SCENE_OT_remove_cursor_from_list(bpy.types.Operator): + bl_idname = "scene.remove_cursor_from_list" + bl_label = "Delete" + bl_description = "Delete selected 3D Cursor from the list" + + @classmethod + def poll(cls, context): + return bool(context.scene.cursors3d_collection) and context.scene.cursors3d_index < len(context.scene.cursors3d_collection) + + def execute(self, context): + context.scene.cursors3d_collection.remove(context.scene.cursors3d_index) + return {'FINISHED'} + + +class SCENE_OT_move_cursor_in_list(bpy.types.Operator): + bl_idname = "scene.move_cursor_in_list" + bl_label = "Move" + bl_description = "Move the active Cursor up/down in the list" + direction: bpy.props.EnumProperty(items=[('UP', 'Up', ''), ('DOWN', 'Down', '')]) + + @classmethod + def poll(cls, context): + return bool(context.scene.cursors3d_collection) and context.scene.cursors3d_index < len(context.scene.cursors3d_collection) + + def execute(self, context): + index = context.scene.cursors3d_index + collection = context.scene.cursors3d_collection + if self.direction == 'UP' and index > 0: + collection.move(index, index - 1) + context.scene.cursors3d_index -= 1 + elif self.direction == 'DOWN' and index < len(collection) - 1: + collection.move(index, index + 1) + context.scene.cursors3d_index += 1 + + return {'FINISHED'} + + +class SCENE_UL_cursors3d_list(bpy.types.UIList): + def draw_item(self, context, layout, data, item, icon, active_data, active_propname): + layout.prop(item, "name", text="", emboss=False) + + +class OBJECT_PT_cursors3d_panel(bpy.types.Panel): + bl_label = "3D Cursors 💼" + bl_idname = "OBJECT_PT_cursors3d_panel" + bl_space_type = 'VIEW_3D' + bl_region_type = 'UI' + bl_category = "View" + + def draw(self, context): + layout = self.layout + row = layout.row() + col = row.column() + col.template_list("SCENE_UL_cursors3d_list", "", context.scene, "cursors3d_collection", context.scene, "cursors3d_index", rows=3) + col = row.column(align=True) + col.operator("scene.save_cursor", icon='ADD', text="") + col.operator("scene.remove_cursor_from_list", icon='REMOVE', text="") + col.separator() + col.operator("scene.move_cursor_in_list", icon='TRIA_UP', text="").direction = 'UP' + col.operator("scene.move_cursor_in_list", icon='TRIA_DOWN', text="").direction = 'DOWN' + row = layout.row() + row.operator("scene.restore_cursor") + row.operator("view3d.view_center_cursor", text="Center View") + + +classes = (Cursor3dProperties, SCENE_OT_save_cursor, SCENE_OT_restore_cursor, SCENE_OT_remove_cursor_from_list, SCENE_UL_cursors3d_list, OBJECT_PT_cursors3d_panel, SCENE_OT_move_cursor_in_list) + + +def register(): + for cls in classes: + bpy.utils.register_class(cls) + bpy.types.Scene.cursors3d_collection = bpy.props.CollectionProperty(type=Cursor3dProperties) + bpy.types.Scene.cursors3d_index = bpy.props.IntProperty() + + +def unregister(): + for cls in classes: + bpy.utils.unregister_class(cls) + del bpy.types.Scene.cursors3d_collection + del bpy.types.Scene.cursors3d_index + + +if __name__ == "__main__": + register() diff --git a/3d-cursors-case-guide.png b/3d-cursors-case-guide.png new file mode 100644 index 0000000000000000000000000000000000000000..c1f751cf48eb994f2fe298c4cfc7347a227a2b1f GIT binary patch literal 11809 zcmZ{KbyU=0_a`DDB_Rk(44nc3A|Nqzr=X-XNQdN5BhuZVq%=q)(t;q}-60K4qgq2)QZpMmW|X7Tu3L0(P%0R|3ZB3kxSQc{V0 zMGa~7;s|OoQg@mBqFwssoUELjh(<1s^6FD&>d4dR*ZEKKf=MJliA#E^wLmYneLNiJ zR6ZmuFm53ccrNdkVDC45hh2tTmcGEcSC+gF%Pc?T=H>?AOp@Zt-1hL&v9MrQ3nCx` z#fCo{Ya=902)?Doe))nE;m}ESnH!a(PKu+ds#;f{o2rt{N<)P?M}#Ybkc`d6f&}GU z(#fZZXRF_`lJ-G@B$2u5TEv3Zk7j}>ua`AO_V(=TA8o|6vrm-iUz|-F5#rz=PEVB; z6<@jU&D2;tv(gW}5g7e|+S3)P^nW_V;x5eby-N58G+K{U6hp$lrv} z&nX&8Wko0nJ>%8Se)nGPudlCfZYDS3Lm_Y!LL*mpMc0C$w#ED6U}wCryR);(ZF?kp z7<$)iLSI~5tf8UN9Ro3{wbPZBmiBWGxDh=W;Jc57|7#8(?;3oVt>LV@wHW9e6qfph zHZ_W`JB&)qM^H>`sk1Z4QV4czUZ(fs>U^K$#qYv&G2g59AUyWJdqk6z{5D!ejh+V$ zTj?1Y3=9k>dy+5D{!W&tWr@xBdU-V>nPx;dis&-<#-7m%nrF)h;(^vpN>ZZ@t-f48S62bln-7 zHiF*_3M`lE*F|rrrRG$RQ zvp+SNQ-Adg2VKw`y*Qm>D^lXOGFM=wI6*Kr+iOuQE767Sj<83w=EOx&*u*Z%&o9th zT3QlV)Cv~YP07d;L47ahI(A&7bJcK<~s;O}W-^D)n7*c5=%^o#h{VhT5kL5=s^)pdJf4R0?9|#9_ z-&`yYtC3Jl{Tam}joktlo2#+bbU3C6rCwS(#)m%*`YecA#K&i zM(?YgLj4*mi62xw=}_~BML+o75B<3u+*jBRu~yXi?Ng<}P!J~JLaXa{KKp)a;EPnp zFK*P$Av|PQ@UpV<`2=&r_1W$;&lHO??TGK$q&6EH+tK={97IK4UYsYKyt05M{7b8T zr&{~k&x<9co zL)4Sg*qZqT3?{44;Jlenn0U9>%Xh~KUnM$pz`1V=z%C{l4N^7pzrx|};giHA{v5xp zAk92V_zFj+tT^QCv3Y1%*ppYTtSA$Y0Cqu4>C|T~ZU!yRGM@K_Ff9MFrW2e%ZgZSV z4QdB3`Nb&cpbvFK0!)XQ*rKJSQVV#Fd8IYR3T8R4;=dbU^n@t!DM zX2YmFBM)yvJma_%O;aFae99x8=SFs^I^n)9q>Q?tF~Rt2n{=+Fdbs&JN+JLY6C3-H zNoi@f>GJ>=OHo8PhT~|C3>ZEs{nDlFMA1PWUk9)uKD63$o_FI}x6%x2wXR2BB{!ju zH6D;h#4_YRp0y-^Rc2?wZ=WCo;|4QDDVrq7IgMISb<2MJj^v4yo2ERTXyxyku%d2I zD8&zhGaR@?Z;2p+eZq&$d>_{3U%bu|^R1_fOe+nh=x1IfTp;2-5fBs0#4KXcC?D|> zyFh%OYR)nkztH3vL32kVR*9zy~7!7^f)Z< z($hGB;NiwSI-IW~{9-}?i{x=A^&jykmzxg^4E(dm6OF=xbs9*o>rg-%AFw@W<1%cv zqO;CJdv8IvAK9d~Nuoi2AI@!1|J-3g@LNum{4kNy5ytp?0$Dph^bWOA?Jj4$@(^>o zzC^YLDI&Uv661u*IP+rb@q!Ftj{@gVXh&6N1i75FG$RvJFWIQqRcfy9CbV;h%vIaf zwI*rZ8Fl~jQ_^tTs-Wz>MkKKO{^V?2U9`$ilgiZ^H z7mPM}I1Z3s%bLHmnUJ3{i{sR<9pLnfs_zR)x3jpTP09R9xrb6W(<&|I>v%xSA3kyteoAFIPxl=59qD zgLT4V+Wydxg_icC&8+mBj)Y>(!qIq{Do5?>PH_UghHlK@;Og%wmH$KJzdEtd>r+U76$x*VUdvrmBwu- zm7NQcV{et<-YAI~`Z6vgQ?abab>j0gJx(NWiuQb*%J6sHPxOO$^!bbW!FB zJ!cZ-UZ1arJkl)7sq*y}8KDlDEOTmKgNb>q|+O7M{#F?(&wBN(MzP^4WUW8m|a3RuB ztw`O0i74i*>PU4B)9DO9jkfX?-Rz|x7dGpP1S5WvX8Pr)$Ux>3yuuGfq2@nAyTTQR zAWs~IUPwgdHa_WqQ>G2LWJ?yhnj3xjrHT=sNZ#{~R@vYKp)Q+R#{(tZ;ZM$oNm=dK zX6yd4>~;U5e|J6|tju1kiss%pHlz zwoQg7>BFR@A~)U|bZL|ln_*5c+>2s#8u-iukWpm89LP=T!|9(TP@DV*1}ro+wbiE1Myhlq_`U~ zlG!MY|BL$m&r|;e1phxz1qp?p-@1Ewc_}J}4{a2(iuNS-AMY3BNQ!yr?lrV;^gHNy z79X*&vGrcztdWJU-aAZBPme4N#*vw;vK&lhN?*oXg?W27H8gD89?2=3QBLQsYa~A5 z<>TXQk$GpeUNyPy87Q{91^bZDjHSJ>pgL4 z0*=Ykqx`q5?Ci;0@16pL3;H$)k9_kYOdk|7PN3!P_WA=9dm|=iEJw3YH2|B?-QB%b zhZ~ao(rJJ0$Hg+d)l3|;lbhIa8iZt_f3EsH?wRKECd7u$jMXI*Uf#u z$;Uzd%@+VJPSUc$+O!3$#LB8jNMG?-zGe{-!tq4F!9ZPoBws0|y1IIxm9Mh^i{Poq z?d94(6slPmosck|BNOq`VWB8ErzZybtGyA7$QF~|!HOlz==bjj1O#XUWNX}pE*a(1 zvsCYCWVBqMk|rx7vsmw(tCIHe%a<>+v$M6n?o!#647c@7O~3sE12IU+C%RYR$PIF2 zDvJmp0nHyaaD8IY{;sS@*qP9Aag{qPHg-TrQ(^XU(Ns_PZAg~e9>CDYt z;SHd97)z$0+uw;4Bflrq)QeSSa)Rd*nrbRpV$_4~fFo>W!TkU{2`oN6b(JKrENpe8swkWk&e$Fp99(YrQ}4lZaN(Jm8L+7G z^YX+4+;*psNaPt{AmG!D^e!)F@gfk2_rsYMB@#42Ir8E=J?O>Ni1Vk0^RTB4#1-)~{wPmxF8)~}zOu41M(nC5ou)K#J8$Z1kvMD9o@Ach>(?Z!WdIi4 zyLZoAqVs{^V+(V@g{#Pt(xJg+6#(v?ZjV|`jf{+(YzxgMZWmP_?kp!otF=S8nVa9C%-_pWxPW z^j(EO{B+D|`l(;J7Fj-JGO98Sik@KWqj~tQ(Y30;0AZ-n*VFT>Z+vVFR3~yFn16>E z0~`AqiHswb0kD9PQT^BK>=)_S<4I+;(9ISF_8+|i#*#|Cr89MVThZ!?FH7Mia$U=I zp(WZC$xwJl2Qnf|Uj!%B;*%Zvv2;uaWJ;TFk!4UbzSpp!o8>et@Y_IEU-9xfmg>R0 zAdysN8*v6RDetnDc*dlP`uyt|DHPjqdRzKSTp5|br9axNiBR02W4Y`ioe^*5a9sT3 zEzm{)TY%EAzI=HOHVt5)fK=x=)i^Huf%y%nmcSICuzO%}ZVr5@_3f2AOUoh20oC1H zk8_&%>3spZ^iAI7+K%q;`NHJfr34L9;@MeUgmaZb7^1V>WVyu`kDN=y_sTWnm0K_& zgp0fLR|zKGV=esKiSrW=mkV`Gby7K$;M(r>;C*~Zhl*C zz=lGcow+$XvyE**`sG?-o>S__tcni=1PIl*4^8*1l;;^~F?!pH=zb>m=vRQ0&;~yXJS4w^scLvT8 z9UWbe7^gz>-1qlt4N(wQ(v8r!WqLoa51NiqR?5l)-iJTQDJeP9{!Ujce}6wLX=K;n zgZz-c8k3f0yWB#EHC3UeZdh-npmqA@r0}~0&=meopTvYk5fHY}Ai=*elqPp|Xm zyqz6+9Y1WP$e$UMl79PSwNPIb8?s~s;0_qLeM|Uz(a`!a5~4Q*70t)t(wP-4 zS2nv-Ww7M7NiP`8gfm~dY;1#&Wq)U9Wp!0Cd~;`I^qX6M=|HIz6vF&XP)O*9!{jI1 zCQmkc-s3(2^d6EW+>mn(hSH+51jkmT0P;kD7JIa2vh= z>*tkkon6EC?=7wGf z^T=QVN>8@CL5Ff0@fD^9|oN@9f+tHMqNR%AJX(G4-d$zc_7VJiD4D< zo=s^$z1X_1Rd3c^zL##tU(AmAVU0m9ngYs+HEWI=ML_uy(3h{yV2|t3Arq2rt}nKt{Oj8w^2~^sm@GaIKQ}qwt8$x_fiHYkd~5GBPax?)bJ$2RD#u^L7Ixorb#rlX z+sINkjtPORZ_w+VKZ6Xspd^6_=Q(;wW6u1DIvkdFBhHPX5#Z{ zoq+A+F%v_0i`V4%xRQ#Z#yM*)at-I1A-}^0r{9m8^l#dZ6O}6?bO8i5>+4z(;o(C( zNvZBa*2Vt1krQHX+%YwCiqC8RAl_yuZrru%b;q9P)rfxNpp=N3sp0}a+v z1o7UVhK@I5+G77sl5^>a>^Q=2wtru=>esHGe)$d*xVE;zgO-w;^}CZy{P$ZS0|Nty zHADOPmjH_8^84DhoQ}z}u&`{Wq^CEV<}X3Z#^jZiPZ5YJ6Z^+TSZo5fv;*ePHN;D2 z8f=HJHKA0`(7M#Z?jj5fzh`F^He-feL{d%9{$6W-1{&>9#3I_*yFAZg# zlc>V}2kJRd;B z%vMojQ&jGM=4_o}t~PqQ>vmcGU5xyT89=M)F}lK1Iq=;k?PCH!7M#?1Z?#v+DkSmP}i-{O*(N3fy zn~qiN$Xd_qNL**!_mfeG4JTk?(wfLC3B2xJsQ(-HcVk~uX=_!3RO+s~yOUX4=Xk~v z^^vs$`U6XbEN}=?p$-T~IPSM)Qe0tw&;ltb+I|&LWVmZcY5=SIvH^D}N4D-eCQ-P! zo}Qn(ySVUKK7VslP{bZr7`V>!XLVK5z7HZp_6fYOVWI$~p@l^%yv1f>fByN7DD;1W z?!&#kW^kPnZO*M2LR{Q$Z%W?U*w_GhIFp;1jnv|P)0 >JXp{#ytRDKQlBl)dV6b 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 X_iWg5RDv92zR?t9RHe%$jX(V_u~f6* literal 0 HcmV?d00001 -- 2.30.2 From b0df3e8d2d87718ccc4e16401cfb404afe7aeb86 Mon Sep 17 00:00:00 2001 From: dupoxy Date: Sat, 20 Jan 2024 07:19:16 +0100 Subject: [PATCH 3/6] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 40a4ab5..8bd067c 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Try it today and launch your 3D Cursors experience! 🚀 # ⚙️ Installation: -- [Download](3D-Cursor-Briefcase.py) the Python script for the add-on. +- [Download](3D-Cursors-Briefcase.py) the Python script for the add-on. - Open Blender and go to `Edit > Preferences`. - In the Preferences window, click on the `Add-ons` tab. - Click on `Install...` and navigate to the downloaded Python script. @@ -18,7 +18,7 @@ Try it today and launch your 3D Cursors experience! 🚀 - **Go to** `View3D > Sidebar > View Tab`. - In the `3D Cursors 💼` panel. -![user interface](3d-cursor-case-guide.png "user interface") +![user interface](3d-cursors-case-guide.png "user interface") 1. **Saving a 3D Cursor:** - Position your 3D cursor in the desired location and rotation. - Click on the `+` button. This will save the current position and rotation of the 3D cursor. -- 2.30.2 From 32ec7cc68cef3dfee29e4a76e7c7e73ec6328aa8 Mon Sep 17 00:00:00 2001 From: dupoxy Date: Sat, 20 Jan 2024 07:25:32 +0100 Subject: [PATCH 4/6] Update README.md --- README.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 8bd067c..4854adc 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,17 @@ -# 🌟 Welcome to 3D Cursors Briefcase 💼. +# 🌟 Welcome to 3D Cursors Briefcase 💼 Take control of your 3D cursor in Blender like never before! With 3D Cursors Briefcase, you can save, load, and manage multiple 3D cursors. Try it today and launch your 3D Cursors experience! 🚀 - -# ⚙️ Installation: -- [Download](3D-Cursors-Briefcase.py) the Python script for the add-on. +# ⚙️ Installation +- [Download](https://projects.blender.org/dupoxy/3d_cursors_briefcase/raw/branch/dupoxy-init/3D-Cursors-Briefcase.py) the Python script for the add-on. - Open Blender and go to `Edit > Preferences`. - In the Preferences window, click on the `Add-ons` tab. - Click on `Install...` and navigate to the downloaded Python script. - Click on `Install Add-on` and make sure to enable the add-on by checking the box next to it. -# 📖 User guide: - +# 📖 User guide - **Go to** `View3D > Sidebar > View Tab`. - In the `3D Cursors 💼` panel. -- 2.30.2 From f43a5a8c87f5ccf95f6f6067836fa3feefdfcda7 Mon Sep 17 00:00:00 2001 From: dupoxy Date: Sat, 20 Jan 2024 07:27:24 +0100 Subject: [PATCH 5/6] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4854adc..be1bba2 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ With 3D Cursors Briefcase, you can save, load, and manage multiple 3D cursors. Try it today and launch your 3D Cursors experience! 🚀 # ⚙️ Installation -- [Download](https://projects.blender.org/dupoxy/3d_cursors_briefcase/raw/branch/dupoxy-init/3D-Cursors-Briefcase.py) the Python script for the add-on. +- [Download](https://projects.blender.org/dupoxy/3d_cursors_briefcase/raw/branch/main/3D-Cursors-Briefcase.py) the Python script for the add-on. - Open Blender and go to `Edit > Preferences`. - In the Preferences window, click on the `Add-ons` tab. - Click on `Install...` and navigate to the downloaded Python script. -- 2.30.2 From 1fa5a0af06159cf856a33c8a280059ed1b302553 Mon Sep 17 00:00:00 2001 From: dupoxy Date: Sat, 20 Jan 2024 07:30:05 +0100 Subject: [PATCH 6/6] Update 3D-Cursors-Briefcase.py --- 3D-Cursors-Briefcase.py | 270 ++++++++++++++++++++-------------------- 1 file changed, 135 insertions(+), 135 deletions(-) diff --git a/3D-Cursors-Briefcase.py b/3D-Cursors-Briefcase.py index e323e1c..b53871f 100644 --- a/3D-Cursors-Briefcase.py +++ b/3D-Cursors-Briefcase.py @@ -1,135 +1,135 @@ -# SPDX-License-Identifier: GPL-2.0-or-later -bl_info = { - "name": "3D Cursors Briefcase", - "author": "twist-lab", - "version": (0, 0, 1), - "blender": (2, 80, 0), - "location": "View3D > Sidebar > View Tab", - "description": "A place to store 3D Cursors", - "warning": "", - "doc_url": "TODO", #"{BLENDER_MANUAL_URL}/addons/3d_view/3d_navigation.html" - "category": "3D View", -} - -import bpy - - -class Cursor3dProperties(bpy.types.PropertyGroup): - location: bpy.props.FloatVectorProperty(name="Location") - rotation: bpy.props.FloatVectorProperty(name="Rotation") - - -class SCENE_OT_save_cursor(bpy.types.Operator): - bl_idname = "scene.save_cursor" - bl_label = "Save" - bl_description = "Save 3D Cursor location and rotation" - - def execute(self, context): - item = context.scene.cursors3d_collection.add() - item.name = "3D Cursor" - item.location = context.scene.cursor.location - item.rotation = context.scene.cursor.rotation_euler - return {'FINISHED'} - - -class SCENE_OT_restore_cursor(bpy.types.Operator): - bl_idname = "scene.restore_cursor" - bl_label = "Load" - bl_description = "Restore selected 3D Cursor" - - @classmethod - def poll(cls, context): - return bool(context.scene.cursors3d_collection) and context.scene.cursors3d_index < len(context.scene.cursors3d_collection) - - def execute(self, context): - if context.scene.cursors3d_collection: - item = context.scene.cursors3d_collection[context.scene.cursors3d_index] - context.scene.cursor.location = item.location - context.scene.cursor.rotation_euler = item.rotation - return {'FINISHED'} - - -class SCENE_OT_remove_cursor_from_list(bpy.types.Operator): - bl_idname = "scene.remove_cursor_from_list" - bl_label = "Delete" - bl_description = "Delete selected 3D Cursor from the list" - - @classmethod - def poll(cls, context): - return bool(context.scene.cursors3d_collection) and context.scene.cursors3d_index < len(context.scene.cursors3d_collection) - - def execute(self, context): - context.scene.cursors3d_collection.remove(context.scene.cursors3d_index) - return {'FINISHED'} - - -class SCENE_OT_move_cursor_in_list(bpy.types.Operator): - bl_idname = "scene.move_cursor_in_list" - bl_label = "Move" - bl_description = "Move the active Cursor up/down in the list" - direction: bpy.props.EnumProperty(items=[('UP', 'Up', ''), ('DOWN', 'Down', '')]) - - @classmethod - def poll(cls, context): - return bool(context.scene.cursors3d_collection) and context.scene.cursors3d_index < len(context.scene.cursors3d_collection) - - def execute(self, context): - index = context.scene.cursors3d_index - collection = context.scene.cursors3d_collection - if self.direction == 'UP' and index > 0: - collection.move(index, index - 1) - context.scene.cursors3d_index -= 1 - elif self.direction == 'DOWN' and index < len(collection) - 1: - collection.move(index, index + 1) - context.scene.cursors3d_index += 1 - - return {'FINISHED'} - - -class SCENE_UL_cursors3d_list(bpy.types.UIList): - def draw_item(self, context, layout, data, item, icon, active_data, active_propname): - layout.prop(item, "name", text="", emboss=False) - - -class OBJECT_PT_cursors3d_panel(bpy.types.Panel): - bl_label = "3D Cursors 💼" - bl_idname = "OBJECT_PT_cursors3d_panel" - bl_space_type = 'VIEW_3D' - bl_region_type = 'UI' - bl_category = "View" - - def draw(self, context): - layout = self.layout - row = layout.row() - col = row.column() - col.template_list("SCENE_UL_cursors3d_list", "", context.scene, "cursors3d_collection", context.scene, "cursors3d_index", rows=3) - col = row.column(align=True) - col.operator("scene.save_cursor", icon='ADD', text="") - col.operator("scene.remove_cursor_from_list", icon='REMOVE', text="") - col.separator() - col.operator("scene.move_cursor_in_list", icon='TRIA_UP', text="").direction = 'UP' - col.operator("scene.move_cursor_in_list", icon='TRIA_DOWN', text="").direction = 'DOWN' - row = layout.row() - row.operator("scene.restore_cursor") - row.operator("view3d.view_center_cursor", text="Center View") - - -classes = (Cursor3dProperties, SCENE_OT_save_cursor, SCENE_OT_restore_cursor, SCENE_OT_remove_cursor_from_list, SCENE_UL_cursors3d_list, OBJECT_PT_cursors3d_panel, SCENE_OT_move_cursor_in_list) - - -def register(): - for cls in classes: - bpy.utils.register_class(cls) - bpy.types.Scene.cursors3d_collection = bpy.props.CollectionProperty(type=Cursor3dProperties) - bpy.types.Scene.cursors3d_index = bpy.props.IntProperty() - - -def unregister(): - for cls in classes: - bpy.utils.unregister_class(cls) - del bpy.types.Scene.cursors3d_collection - del bpy.types.Scene.cursors3d_index - - -if __name__ == "__main__": - register() +# SPDX-License-Identifier: GPL-2.0-or-later +bl_info = { + "name": "3D Cursors Briefcase", + "author": "dupoxy", + "version": (0, 0, 1), + "blender": (2, 80, 0), + "location": "View3D > Sidebar > View Tab", + "description": "A place to store 3D Cursors", + "warning": "", + "doc_url": "https://projects.blender.org/dupoxy/3d_cursors_briefcase/src/branch/main/README.md", + "category": "3D View", +} + +import bpy + + +class Cursor3dProperties(bpy.types.PropertyGroup): + location: bpy.props.FloatVectorProperty(name="Location") + rotation: bpy.props.FloatVectorProperty(name="Rotation") + + +class SCENE_OT_save_cursor(bpy.types.Operator): + bl_idname = "scene.save_cursor" + bl_label = "Save" + bl_description = "Save 3D Cursor location and rotation" + + def execute(self, context): + item = context.scene.cursors3d_collection.add() + item.name = "3D Cursor" + item.location = context.scene.cursor.location + item.rotation = context.scene.cursor.rotation_euler + return {'FINISHED'} + + +class SCENE_OT_restore_cursor(bpy.types.Operator): + bl_idname = "scene.restore_cursor" + bl_label = "Load" + bl_description = "Restore selected 3D Cursor" + + @classmethod + def poll(cls, context): + return bool(context.scene.cursors3d_collection) and context.scene.cursors3d_index < len(context.scene.cursors3d_collection) + + def execute(self, context): + if context.scene.cursors3d_collection: + item = context.scene.cursors3d_collection[context.scene.cursors3d_index] + context.scene.cursor.location = item.location + context.scene.cursor.rotation_euler = item.rotation + return {'FINISHED'} + + +class SCENE_OT_remove_cursor_from_list(bpy.types.Operator): + bl_idname = "scene.remove_cursor_from_list" + bl_label = "Delete" + bl_description = "Delete selected 3D Cursor from the list" + + @classmethod + def poll(cls, context): + return bool(context.scene.cursors3d_collection) and context.scene.cursors3d_index < len(context.scene.cursors3d_collection) + + def execute(self, context): + context.scene.cursors3d_collection.remove(context.scene.cursors3d_index) + return {'FINISHED'} + + +class SCENE_OT_move_cursor_in_list(bpy.types.Operator): + bl_idname = "scene.move_cursor_in_list" + bl_label = "Move" + bl_description = "Move the active Cursor up/down in the list" + direction: bpy.props.EnumProperty(items=[('UP', 'Up', ''), ('DOWN', 'Down', '')]) + + @classmethod + def poll(cls, context): + return bool(context.scene.cursors3d_collection) and context.scene.cursors3d_index < len(context.scene.cursors3d_collection) + + def execute(self, context): + index = context.scene.cursors3d_index + collection = context.scene.cursors3d_collection + if self.direction == 'UP' and index > 0: + collection.move(index, index - 1) + context.scene.cursors3d_index -= 1 + elif self.direction == 'DOWN' and index < len(collection) - 1: + collection.move(index, index + 1) + context.scene.cursors3d_index += 1 + + return {'FINISHED'} + + +class SCENE_UL_cursors3d_list(bpy.types.UIList): + def draw_item(self, context, layout, data, item, icon, active_data, active_propname): + layout.prop(item, "name", text="", emboss=False) + + +class OBJECT_PT_cursors3d_panel(bpy.types.Panel): + bl_label = "3D Cursors 💼" + bl_idname = "OBJECT_PT_cursors3d_panel" + bl_space_type = 'VIEW_3D' + bl_region_type = 'UI' + bl_category = "View" + + def draw(self, context): + layout = self.layout + row = layout.row() + col = row.column() + col.template_list("SCENE_UL_cursors3d_list", "", context.scene, "cursors3d_collection", context.scene, "cursors3d_index", rows=3) + col = row.column(align=True) + col.operator("scene.save_cursor", icon='ADD', text="") + col.operator("scene.remove_cursor_from_list", icon='REMOVE', text="") + col.separator() + col.operator("scene.move_cursor_in_list", icon='TRIA_UP', text="").direction = 'UP' + col.operator("scene.move_cursor_in_list", icon='TRIA_DOWN', text="").direction = 'DOWN' + row = layout.row() + row.operator("scene.restore_cursor") + row.operator("view3d.view_center_cursor", text="Center View") + + +classes = (Cursor3dProperties, SCENE_OT_save_cursor, SCENE_OT_restore_cursor, SCENE_OT_remove_cursor_from_list, SCENE_UL_cursors3d_list, OBJECT_PT_cursors3d_panel, SCENE_OT_move_cursor_in_list) + + +def register(): + for cls in classes: + bpy.utils.register_class(cls) + bpy.types.Scene.cursors3d_collection = bpy.props.CollectionProperty(type=Cursor3dProperties) + bpy.types.Scene.cursors3d_index = bpy.props.IntProperty() + + +def unregister(): + for cls in classes: + bpy.utils.unregister_class(cls) + del bpy.types.Scene.cursors3d_collection + del bpy.types.Scene.cursors3d_index + + +if __name__ == "__main__": + register() -- 2.30.2