Last active
December 9, 2023 22:09
-
-
Save mwganson/aea3c51981c0b994cfd961cf4db56b50 to your computer and use it in GitHub Desktop.
Easy texture reflections for FreeCAD
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
__version__ = "0.2023.12.09" | |
__icon__ = "https://github.com/mwganson/EasyReflector/raw/main/EasyReflectorIcon.svg" | |
#__version__ = "0.2023.12.09" | |
##EasyReflector macro by TheMarkster | |
##based on work by Athanaze at https://github.com/Athanaze/Freecad-easy-reflections | |
## | |
##do not run this file directly. Instead run the EasyReflector.FCMacro file. | |
## | |
#from pivy import coin | |
#import FreeCAD, FreeCADGui | |
#import os, requests, concurrent.futures | |
#from PySide import QtGui, QtCore | |
# | |
#PATH = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macro").GetString("MacroPath")+"/easy_reflections/" | |
#DEFAULT_FILES = ["other image file","none","interior.jpg","industrial.jpg","mesh2.jpg","outside.jpg","studio.jpg","workshop.jpg"] | |
#GITHUB_BASE_URL = "https://github.com/mwganson/EasyReflector/blob/main/easy_reflections/" | |
#GITHUB_RAW_EXTRA = "?raw=true" | |
#EXPANDED_FILES = DEFAULT_FILES #will add any additional files user has added to Environment property | |
# | |
## Get a list of all image files in the local directory | |
#local_files = [f for f in os.listdir(PATH)] if os.path.exists(PATH) else DEFAULT_FILES | |
# | |
## Iterate through local files and add their base names to EXPANDED_FILES if not already present | |
#for local_file in local_files: | |
# base_name, extension = os.path.splitext(local_file) | |
# fullname = base_name + extension | |
# if fullname not in EXPANDED_FILES and fullname != "white.jpg": #aliased to "none" | |
# EXPANDED_FILES.append(fullname) | |
# | |
#class EasyReflector: | |
# def __init__(self, obj): | |
# obj.addProperty("App::PropertyString","Version","EasyReflector","Version used to create this object").Version = __version__ | |
# obj.addProperty("App::PropertyEnumeration", "Environment","EasyReflector","Select Environment (white = None)") | |
# obj.Environment = EXPANDED_FILES | |
# obj.Environment = "studio.jpg" | |
# obj.addProperty("App::PropertyLinkList","LinkedObjects","EasyReflector","Objects to apply textures to") | |
# obj.addProperty("App::PropertyFileIncluded","ImageFile","EasyReflector","Image file to use for environment") | |
# obj.setEditorMode("ImageFile", 2) #hide by default | |
# obj.addProperty("App::PropertyBool","Enabled","EasyReflector","Whether texturing is enabled or not").Enabled=True | |
# obj.Proxy = self | |
# | |
# def execute(self,fp): | |
# if not fp.LinkedObjects: | |
# return | |
# self.setEnvironment(fp, fp.Environment) | |
# | |
# def onChanged(self,fp,prop): | |
# if not fp: | |
# return | |
# elif prop == "Environment": | |
# if fp.Environment == "other image file": | |
# fp.setEditorMode("ImageFile", 0) #normal mode | |
# else: | |
# fp.setEditorMode("ImageFile", 2) #hide | |
# elif prop == "LinkedObjects": | |
# self.verifyLinkedObjects(fp) | |
# | |
# def verifyLinkedObjects(self,fp): | |
# links = fp.LinkedObjects | |
# incompatibles = ["App::Plane","App::Line"] | |
# links_to_keep = [obj for obj in links if not obj.TypeId in incompatibles] | |
# links_removed = [obj for obj in links if obj.TypeId in incompatibles] | |
# for lr in links_removed: | |
# FreeCAD.Console.PrintWarning(f"EasyReflector: {lr.Label} is incompatible \ | |
#and has been removed from Linked Objects property.\n") | |
# fp.LinkedObjects = links_to_keep | |
# | |
# def onDocumentRestored(self, fp): | |
# self.setEnvironment(fp, fp.Environment) | |
# | |
# def checkImagesExist(self, fp): | |
# paths = [PATH + (fn if fn != "none" else "white.jpg") for fn in DEFAULT_FILES[1:]] | |
# for path in paths: | |
# if not os.path.exists(path): | |
# return False | |
# return True | |
# | |
# def getPermissionFromUser(self,fp): | |
# msgBox = QtGui.QMessageBox() | |
# msgBox.setWindowTitle("EasyReflector") | |
# msgBox.setIcon(QtGui.QMessageBox.Warning) | |
# msgBox.setText("EasyReflector needs to download the texture image files.") | |
# info = "These are jpg image files to be used as textures for the reflections. " | |
# info += "They will be downloaded from a github repository and placed in " | |
# info += "your macros folder in a subfolder named easy_reflections. " | |
# info += "You must manually remove these files if you uninstall EasyReflector. " | |
# info += "Proceed with download (Yes/No)?" | |
# msgBox.setInformativeText(info) | |
# msgBox.setStandardButtons(QtGui.QMessageBox.Yes | QtGui.QMessageBox.No) | |
# msgBox.setDefaultButton(QtGui.QMessageBox.No) | |
# ret = msgBox.exec(); | |
# return ret == QtGui.QMessageBox.Yes | |
# | |
# | |
# def downloadImages(self, fp): | |
# if not self.getPermissionFromUser(fp): | |
# return | |
# FreeCAD.Console.PrintMessage("Downloading files...\n") | |
# os.makedirs(PATH, exist_ok=True) | |
# QtGui.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor) | |
# | |
# def download_file(fn): | |
# if fn == "none": | |
# # For "none", download the white.jpg file | |
# url = GITHUB_BASE_URL + "white.jpg" + GITHUB_RAW_EXTRA | |
# else: | |
# # For other files, download them using their respective names | |
# url = GITHUB_BASE_URL + fn + GITHUB_RAW_EXTRA | |
# | |
# try: | |
# response = requests.get(url) | |
# response.raise_for_status() | |
# content = response.content | |
# | |
# # Construct the local file path | |
# local_file_path = os.path.join(PATH, fn if fn != "none" else "white.jpg") | |
# | |
# # Save the content to the local file | |
# with open(local_file_path, "wb") as file: | |
# file.write(content) | |
# | |
# print(f"Downloaded '{fn}' from GitHub and saved it as '{local_file_path}'") | |
# except Exception as e: | |
# print(f"Failed to download '{fn}' from GitHub: {str(e)}") | |
# | |
# with concurrent.futures.ThreadPoolExecutor() as executor: | |
# executor.map(download_file, DEFAULT_FILES[1:]) | |
# QtGui.QApplication.restoreOverrideCursor() | |
# | |
# def setEnvironment(self, fp, env): | |
# if not self.checkImagesExist(fp): | |
# self.downloadImages(fp) | |
# tex = coin.SoTexture2() | |
# if env == "other image file": | |
# tex.filename = fp.ImageFile | |
# else: | |
# if fp.Environment == "none": | |
# tex.filename = PATH + "white.jpg" | |
# else: | |
# tex.filename = PATH + fp.Environment | |
# if not fp.Enabled: | |
# tex.filename = PATH + "white.jpg" | |
# tc = coin.SoTextureCoordinateEnvironment() | |
# linked = fp.LinkedObjects | |
# if not linked: | |
# return | |
# for link in linked: | |
# rootnode = link.ViewObject.RootNode | |
# child1 = rootnode.getChild(1) | |
# child2 = rootnode.getChild(2) | |
# already_done = "SoTexture2" in str(type(child1)) and "SoTextureCoordinateEnvironment" in str(type(child2)) | |
# if already_done: | |
# rootnode.replaceChild(1, tex) | |
# rootnode.replaceChild(2, tc) | |
# else: | |
# rootnode.insertChild(tex,1) | |
# rootnode.insertChild(tc,2) | |
# | |
#__XPM__ = """ | |
#/* XPM */ | |
#static char *_693848802616[] = { | |
#/* columns rows colors chars-per-pixel */ | |
#"64 64 116 2 ", | |
#" c #0B650BB10DE1", | |
#". c #0DBE0E0B1115", | |
#"X c #10200F3813BC", | |
#"o c #0F1110011307", | |
#"O c #119B125615DD", | |
#"+ c #143415321A30", | |
#"@ c #16DB18631CF3", | |
#"# c #18E719ED1E46", | |
#"$ c #141816BF200E", | |
#"% c #1650190121ED", | |
#"& c #1AD71C552268", | |
#"* c #1C2C1EEC286B", | |
#"= c #1EAA209824F5", | |
#"- c #1E3E212C2A47", | |
#"; c #211C226F2652", | |
#": c #22FA25302AC4", | |
#"> c #266E28E82D80", | |
#", c #29202AC92E23", | |
#"< c #238A27013143", | |
#"1 c #25EA2A833376", | |
#"2 c #2AFC2D5832DB", | |
#"3 c #28FE2DD8392C", | |
#"4 c #2DBA30FC35C9", | |
#"5 c #2C2C318A3BD9", | |
#"6 c #319D332E3610", | |
#"7 c #329E35AD3AA8", | |
#"8 c #360F39893E28", | |
#"9 c #3A4A3B303DFF", | |
#"0 c #2E87359C4292", | |
#"q c #305236804275", | |
#"w c #329D3954441F", | |
#"e c #39C83D7542B6", | |
#"r c #359C3D0149AC", | |
#"t c #383A3F404BC4", | |
#"y c #3D5840CE4552", | |
#"u c #3B94420A4CCF", | |
#"i c #3DFE44B85143", | |
#"p c #4394443145FD", | |
#"a c #41C5455C4A4D", | |
#"s c #457D49764E74", | |
#"d c #4A8E4B894DEA", | |
#"f c #409047185373", | |
#"g c #45364AC95396", | |
#"h c #49CF4E13539E", | |
#"j c #46634D2C5AFF", | |
#"k c #498B4E115CE4", | |
#"l c #4C5050EC55EC", | |
#"z c #4E1B53A75A3E", | |
#"x c #532953EE55DA", | |
#"c c #516955E75A8F", | |
#"v c #54EF592D5DCD", | |
#"b c #5CE15CE85DE7", | |
#"n c #4CE5541362C2", | |
#"m c #516355E36259", | |
#"M c #55735AE06229", | |
#"N c #59DB5E276391", | |
#"B c #55875C586A13", | |
#"V c #5BDF60CA6600", | |
#"C c #5D41629A6980", | |
#"Z c #5DA6646471AD", | |
#"A c #6278629763D6", | |
#"S c #622F66926C3A", | |
#"D c #63C169026E62", | |
#"F c #6A646B386CE6", | |
#"G c #61E0672E71F2", | |
#"H c #64C56B4C7396", | |
#"J c #69F66E6A73DA", | |
#"K c #67006DBD7A69", | |
#"L c #68376F227AA8", | |
#"P c #6C7471817689", | |
#"I c #6DFD73857A79", | |
#"U c #72EA7485765A", | |
#"Y c #71EF76AD7BFA", | |
#"T c #7435794E7EAC", | |
#"R c #7B1A7D027F95", | |
#"E c #6C5473C880B9", | |
#"W c #714177B881DE", | |
#"Q c #76367B8C81CE", | |
#"! c #797A7E8E844E", | |
#"~ c #76607DA5882D", | |
#"^ c #7BCE814A8691", | |
#"/ c #7E2284438A18", | |
#"( c #7FA0880B8BE5", | |
#") c #8345841C85C8", | |
#"_ c #821B86C08BA5", | |
#"` c #847189E68E50", | |
#"' c #8AFC8C168D68", | |
#"] c #85338C479212", | |
#"[ c #89068ED4935A", | |
#"{ c #87859080937B", | |
#"} c #8A45922294B2", | |
#"| c #8EC095939BCA", | |
#" . c #91BB928693B4", | |
#".. c #97DD99EA9BD1", | |
#"X. c #9B909CBB9E2E", | |
#"o. c #A441A473A55A", | |
#"O. c #A4D9A778A8FB", | |
#"+. c #AC79AD21AE40", | |
#"@. c #B33EB400B547", | |
#"#. c #B67CB78AB89C", | |
#"$. c #B6ECB898BA4A", | |
#"%. c #BC61BCF0BDC0", | |
#"&. c #C02CC15AC322", | |
#"*. c #C274C424C54E", | |
#"=. c #C83FC83FC855", | |
#"-. c #CC1ACC3CCC9E", | |
#";. c #D017D0B5D270", | |
#":. c #D43CD482D4F3", | |
#">. c #DBAEDBDEDC46", | |
#",. c #E02EE054E096", | |
#"<. c #E444E465E4B3", | |
#"1. c #EBF8EC3AEC69", | |
#"2. c #F02DF0F6F11C", | |
#"3. c #F5E1F5F3F61B", | |
#"4. c #F840F862F891", | |
#"5. c none", | |
#/* pixels */ | |
#"5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.", | |
#"5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.", | |
#"5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.", | |
#"5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.4.4.5.4.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.", | |
#"5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.4.<.%. .` ) ) ) o.=.2.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.", | |
#"5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.4.;.` c a g c v l a 9 7 6 8 F =.4.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.", | |
#"5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.4.&.S 7 7 w r u l c z h 9 2 > ; # , U :.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.", | |
#"5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.:.F 6 3 3 0 0 0 e f l c z h e 2 , ; @ # 6 @.4.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.", | |
#"5.5.5.5.5.5.5.5.5.5.5.5.5.5.3...e - < 3 0 0 0 0 w r f h x c h e 2 , & + o > X.4.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.", | |
#"5.5.5.5.5.5.5.5.5.5.5.5.5.>.F 2 % * * 1 3 3 0 0 w w r t j z c h e 2 , = O o ; ' 4.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.", | |
#"5.5.5.5.5.5.5.5.5.5.5.5.-.x : & * * * < < 3 0 0 w w w r u h c c h e 2 > = O . & U 3.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.", | |
#"5.5.5.5.5.5.5.5.5.5.5.%.d & % * * % * * - < 3 0 0 w r r r t h k z h e 4 , & O . # A 1.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.", | |
#"5.5.5.5.5.5.5.5.5.4.%.p & + $ % * * * % * * < 3 0 0 0 r r r t g z c h y 2 > & O . + x <.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.", | |
#"5.5.5.5.5.5.5.5.5.;.s % O + + + $ % % * % * * - 3 0 0 r r t t t f l c h y 4 > = O O d :.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.", | |
#"5.5.5.5.5.5.5.5.>.v & + O X + O $ $ % * * $ * * < 1 0 0 r t t t u u l c g e 4 - # O X p -.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.", | |
#"5.5.5.5.5.5.5.2.U , * $ $ + X O + + $ $ $ * % % * * < 0 q r t t u u i l c h y 4 , # X 9 #.4.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.", | |
#"5.5.5.5.5.5.4.X.7 8 2 = % @ O o O + + $ $ $ % % % * * 3 0 0 t t i t u i l z l e 6 1 # X 6 o.4.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.", | |
#"5.5.5.5.5.5.-.a e y y 5 - = = @ + O O O + $ % % $ % % * - 0 q t u u u r i l c l e 2 > # X , .4.5.5.5.5.5.5.5.5.5.5.5.5.5.5.", | |
#"5.5.5.5.5.3.F > 7 e 8 8 7 1 - = = $ + + X $ $ % % $ $ % * < 3 q r i i i u i g c h e 4 > @ X : ) 3.5.5.5.5.5.5.5.5.5.5.5.5.5.", | |
#"5.5.5.5.5.#.7 : : > , , 3 4 4 - - = = % $ O $ $ $ % $ $ % * < 3 0 r i i i u i g v l e 6 > @ o & U 3.5.5.5.5.5.5.5.5.5.5.5.5.", | |
#"5.5.5.5.1.V , : = & # # # = > > : : : : * $ + O + $ $ $ $ $ % < 3 0 r i f f u i g c l e , & o o . @ F <.5.5.5.5.5.5.5.5.5.5.5.", | |
#"5.5.5.5.#.6 4 , = # @ O O O + = - : - : : : & $ + + + $ $ $ $ % < 3 0 u f f f i g h 8 > = , 6 7 6 ; @ # b >.5.5.5.5.5.5.5.5.5.5.", | |
#"5.5.5.4.F 4 4 4 : = & @ + O o O + % & - : > , : % + X $ $ $ $ $ & - 3 0 t j g e 7 > : 2 s D P P U A g 7 : b ;.5.5.5.5.5.5.5.5.5.", | |
#"5.5.5.,.a 7 7 4 , : = & # @ @ O X X + + & - , 2 > * $ + $ $ + $ $ $ - 3 g w 1 : : > w j Z T ^ Q ! T J N p , b -.5.5.5.5.5.5.5.5.", | |
#"5.5.4.O.6 7 8 8 4 , ; = # & # @ + O X X + + & > 2 2 : # + $ $ $ + $ 5 j 7 & & : w z C H I Y I I Y T W Y H c 7 v -.5.5.5.5.5.5.5.", | |
#"5.5.3.A , 6 7 6 7 4 > ; = & & # # @ + X o . O + & 2 2 > & + + $ % g D y & , 8 h M L I T T Q T T W Q Q ! Q J c 4 x <.5.5.5.5.5.5.", | |
#"5.5.1.7 > 4 6 4 , , > = = % = % # # @ + O O . X + # : 2 2 = $ * B ~ h , 4 u z C H I T Q Q Q Q Q ! Q ! Q Q U S h 2 .4.5.5.5.5.5.", | |
#"5.5.:., ; 2 4 , = = = = = # = = & & # # + + O X X X @ = > 2 2 S _ l 1 8 h m C Z P D v d s a d v F T Q Q W I S v h e :.5.5.5.5.5.", | |
#"5.4.@.> # , 6 , = # # = # = = # & & # & # # + + X X . + + 3 U ] h 4 y h v C Z v y 6 , = @ + @ ; 6 h J R T P S c v e _ 4.5.5.5.5.", | |
#"5.4. .; = ; , 6 = # # # # @ # = & & & & & # # # + + + X # S ` g 4 u l v V z y > @ O O O O O o . X # 9 J T P S c v v l 3.5.5.5.5.", | |
#"5.4.) + + = ; , - # # # @ # % % & # & # % & # & + + + + h [ g 2 u z v V u , @ o O @ @ O + O O o . o O p Y T D v c N d ,.5.5.5.5.", | |
#"5.4.' ; . # = ; , # @ @ @ @ # # # & & & & # & # % # # e [ N 6 g z V v e & O + O @ O + + + O O O o . . # v ! P N v v v +.4.5.5.5.", | |
#"5.4.} y # o # # ; # @ # + @ # # # % # & & & & & % @ > ( P 7 i z v c 8 & + + + + + + + + + + + O O X X X 8 Y T A v M C .5.5.5.5.", | |
#"5.4.X.y 6 @ O # # = # @ @ @ @ @ # # # % # # & # # = V ( 8 u v V C h = % + + + + + + X + + X + O + O X . & P ^ J v N D X.4.5.5.5.", | |
#"5.4.%.6 9 6 @ o # = # # @ @ @ @ # @ @ % # & & & = 7 ( l y c V V z N y - & # + + + + + + + + + O + O X X + D ] I V V D O.4.5.5.5.", | |
#"5.5.,., ; 8 4 @ # # # # @ O + @ @ @ @ # # # # & - P Y 8 z V C u 7 C J d > % $ + + + + + + + + O O O O O + V ] Q C V D X.4.5.5.5.", | |
#"5.5.3.x O ; 6 6 # @ # @ @ O @ + @ + @ @ @ @ @ # y { u l C D v 3 < p P Y k , & % $ + + + + + + + + O O O # b } ! D C D X.5.5.5.5.", | |
#"5.5.4. .O o # 6 6 = # # @ O + + O @ @ O @ @ @ = J C u V C H V i < , h Y Q c 2 & & $ + + + X + + + + O + O b | ^ H C J @.4.5.5.5.", | |
#"5.5.5.:.6 . @ , 6 ; # @ @ O @ O + O @ @ + @ 6 ` u V D J L W Z f 0 5 N Q ! m 2 & & # + + + + + + + O + # F ..^ J D J ;.5.5.5.5.", | |
#"5.5.5.4.' O o O ; 6 ; # O @ @ @ @ O O + + # V R l D P L ^ ( / Z j q e G ! ! N 4 & & # + + + + + + + O # ) [ ^ Y J J 1.5.5.5.5.", | |
#"5.5.5.5.<.p . . ; , > @ @ O + O O O O O > ( C C P Y C T ( { / E k r h P ~ Q N 2 & & # + + + + + @ O 5 [ _ ~ Q Y ) 3.5.5.5.5.", | |
#"5.5.5.5.5.@.6 . # , ; @ O + + + O @ @ e | V P Y Y i V W ( [ ] E n i B T ^ ^ N 6 & & # # + + @ O @ M ! / / ! T +.4.5.5.5.5.", | |
#"5.5.5.5.5.5.+.6 . . @ , ; @ O + + + O @ v ( J Y R S w u B I ] [ ] ~ B k G Q _ ! N 5 & * & + + + + : ^ D _ / / ! >.5.5.5.5.5.", | |
#"5.5.5.5.5.5.4.+.9 . o @ , > @ O + O O = Y Y T T R N g 0 u n E _ [ ] ~ Z B L ! ! ! C 4 & & & @ + @ h _ N _ _ _ ` 3.5.5.5.5.5.", | |
#"5.5.5.5.5.5.5.4.&.p . o o O , > # O O O ; ( Y R ^ ^ z c s q r k E / [ } / K Z Y ! _ ! S 5 & & # # 2 / v U _ _ _ $.4.5.5.5.5.5.", | |
#"5.5.5.5.5.5.5.5.4.-.d . o o o > 2 & O @ 2 ( ! R ^ R 8 p z h 7 0 j H / [ } ( L H Q ~ ! ! A 2 & # : S Y g _ _ ` ` 1.5.5.5.5.5.5.", | |
#"5.5.5.5.5.5.5.5.5.5.>.x o o o O : 2 & @ 8 } ( / / T : > e c d 0 q g G ^ { } ] E K Q ! ! ! N 5 ; h _ p L ` ` _ @.5.5.5.5.5.5.5.", | |
#"5.5.5.5.5.5.5.5.5.4.4.<.A @ o o o ; 4 & y } ( / _ Y : o = 8 x j q 3 f Z W ] } ] W E Q ! / ! N h / z c _ ] _ ` 1.5.5.5.5.5.5.5.", | |
#"5.5.5.5.5.5.5.5.5.5.5.5.3.F & . o o ; , p } ( ( _ T , . X = 6 l l w 5 i B W _ } { ~ W Q ^ ^ ^ ` N y ! ` ` ` *.5.5.5.5.5.5.5.5.", | |
#"5.5.5.5.5.5.5.5.5.5.5.5.5.3.R ; o o # p } _ _ _ ! 4 . . . # 4 d z e 5 u m I ( } { ^ W ~ ( ( C 8 P ` ` ` O.4.5.5.5.5.5.5.5.5.", | |
#"5.5.5.5.5.5.5.5.5.5.5.5.5.5.4. ., . o + 6 { _ _ _ ) e . . . O 2 a c e 3 r n L ( } } / ~ ^ V 7 J ` ` _ } 1.5.5.5.5.5.5.5.5.5.", | |
#"5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.o., o O , ) _ _ _ _ N @ o O > y c u 4 w k G ^ _ ^ P d 7 S ` ` ` [ ;.5.5.5.5.5.5.5.5.5.5.", | |
#"5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.#.6 o # T _ ( _ ` Q e . . o O ; 9 c a 5 0 g m h e , 8 J _ ` ` [ *.5.5.5.5.5.5.5.5.5.5.5.", | |
#"5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.4.=.9 O @ v _ _ _ ` ( D 3 + . o o & 8 l a 1 1 & # , a T ` ` ` ] %.4.5.5.5.5.5.5.5.5.5.5.5.", | |
#"5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.:.p + 6 ) _ _ ] _ _ S e : @ + O O O = 6 8 2 # : w v ( ` ` _ ' @.4.5.5.5.5.5.5.5.5.5.5.5.5.", | |
#"5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.,.x : S _ ] _ ] _ _ K m d p p 7 8 8 e a u y c ! ` ` ' _ ' *.4.5.5.5.5.5.5.5.5.5.5.5.5.5.", | |
#"5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.1.F e W _ ` ` ` _ _ ^ P P ^ ` ` ^ Y D D ! ` ] ` ` ` } :.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.", | |
#"5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.1.R v Q _ ` ] ] ` ] ` ` ) ^ ^ ( ( ' ` ` ` ' ` ' ..<.4.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.", | |
#"5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.3. .A Q _ _ ] ` ` ` ` ` { { ` ` ` ' ` _ ` [ &.4.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.", | |
#"5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.4.o.N Y ! _ ` ` ` ` { ` { ` ` ` ` ` ` @.1.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.", | |
#"5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.4.>._ S Y ^ ) ` ) _ _ ` ' _ / [ @.1.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.", | |
#"5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.4.<.+.` U U P Y R ) X.@.>.3.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.", | |
#"5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.4.4.4.3.1.1.4.4.4.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.", | |
#"5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5." | |
#};""" | |
#class EasyReflectorVP: | |
# def __init__(self, obj): | |
# '''Set this object to the proxy object of the actual view provider''' | |
# obj.Proxy = self | |
# | |
# def doubleClicked(self,vobj): | |
# vobj.Object.Enabled = not vobj.Object.Enabled | |
# | |
# def dropObject(self, vp, dropped): | |
# vp.Object.LinkedObjects += [dropped] | |
# vp.Object.LinkedObjects = list(set(vp.Object.LinkedObjects)) #remove duplicates | |
# | |
# def canDropObjects(self): | |
# return True | |
# | |
# def canDropObject(self, dropped): | |
# return hasattr(dropped, "ViewObject") | |
# | |
# def attach(self,vobj): | |
# self.Object = vobj.Object | |
# self.standard = coin.SoGroup() | |
# vobj.addDisplayMode(self.standard,"Standard") | |
# | |
# def onDelete(self, vobj, subelements): | |
# vobj.Object.Enabled = False | |
# vobj.Object.Document.recompute() | |
# return True | |
# | |
# def updateData(self, fp, prop): | |
# '''If a property of the handled feature has changed we have the chance to handle this here''' | |
# if prop == "Environment": | |
# fp.ViewObject.signalChangeIcon() | |
# | |
# def getDisplayModes(self,obj): | |
# '''Return a list of display modes.''' | |
# modes=["Standard"] | |
# return modes | |
# | |
# def claimChildren(self): | |
# return[] | |
# | |
# def getDefaultDisplayMode(self): | |
# '''Return the name of the default display mode. It must be defined in getDisplayModes.''' | |
# return "Standard" | |
# | |
# def setDisplayMode(self,mode): | |
# '''Map the display mode defined in attach with those defined in getDisplayModes.\ | |
# Since they have the same names nothing needs to be done. This method is optional''' | |
# return mode | |
# | |
# def onChanged(self, vp, prop): | |
# '''Here we can do something when a single property got changed''' | |
# #FreeCAD.Console.PrintMessage("Change property: " + str(prop) + "\n") | |
# pass | |
# | |
# def getIcon(self): | |
# '''Return the icon in XPM format which will appear in the tree view. This method is\ | |
# optional and if not defined a default icon is shown.''' | |
# iconTextured = __XPM__ | |
# | |
# if self.Object.Environment != "none" and self.Object.Enabled: | |
# return iconTextured | |
# else: | |
# return None #default app::featurepython icon | |
# | |
# def __getstate__(self): | |
# '''When saving the document this object gets stored using Python's json module.\ | |
# Since we have some un-serializable parts here -- the Coin stuff -- we must define this method\ | |
# to return a tuple of all serializable objects or None.''' | |
# return None | |
# | |
# def __setstate__(self,state): | |
# '''When restoring the serialized object from document we have the chance to set some internals here.\ | |
# Since no data were serialized nothing needs to be done here.''' | |
# return None | |
# | |
#CODE_ENDS_HERE | |
######################################## | |
BASENAME = 'easyreflector' | |
def makeObject(FP): | |
doc = FreeCAD.ActiveDocument | |
sel = Gui.Selection.getSelection() | |
fp = doc.addObject("App::FeaturePython","EasyReflector") | |
FP.EasyReflector(fp) | |
FP.EasyReflectorVP(fp.ViewObject) | |
if len(sel) >= 1: | |
fp.LinkedObjects = sel | |
else: | |
FreeCAD.Console.PrintWarning("EasyReflector: nothing selected. Select an \ | |
object prior to running the macro or drag/drop your object(s) on to it in the \ | |
combo view or edit the Linked Objects property.\n") | |
################# | |
def writeFile(): | |
with open(py_file,"w") as outfile: | |
for line in code.splitlines(): | |
if "#CODE_ENDS_HERE" in line: | |
break | |
if line.startswith('#'): | |
if line == "# -*- coding: utf-8 -*-": | |
line = "#" + line | |
outfile.write(line[1:]+"\n") #skip first character (#) | |
############ | |
#if __name__ == "__main__": | |
# makeObject(None) | |
# raise Exception("quick exit for testing/debugging") | |
############ | |
if __name__ == "__main__": | |
import os | |
fin = open(__file__, 'r') | |
code = fin.read() | |
fin.close() | |
version = code.splitlines()[1][16:] | |
real_path = os.path.realpath(__file__) | |
dir_path = os.path.dirname(real_path) | |
py_file = real_path.replace(".FCMacro",".py").replace('EasyReflector','easyreflector').replace("easyReflector","easyreflector") | |
bHasFile = os.path.exists(py_file) | |
noImport = False #user elects not to save import file | |
if not bHasFile: | |
from PySide import QtGui | |
window = QtGui.QApplication.activeWindow() | |
mb = QtGui.QMessageBox() | |
mb.setWindowTitle(BASENAME+" setup") | |
mb.setIcon(mb.Information) | |
mb.setStandardButtons(mb.Ok) | |
mb.addButton(mb.Cancel) | |
mb.setDefaultButton(mb.Cancel) | |
okBtn = mb.button(QtGui.QMessageBox.StandardButton.Ok) | |
cancelBtn = mb.button(QtGui.QMessageBox.StandardButton.Cancel) | |
okBtn.setText("Create file") | |
cancelBtn.setText("Do not create file") | |
caption = "In order for "+BASENAME+" objects to be parametric after saving and reloading file\n\ | |
we need to create another file on this computer. File to be created will be: \n\n"+py_file+"\n\n\ | |
This makes it available to the system upon restarting FreeCAD and loading documents containing the \ | |
"+BASENAME+" feature python objects. Create file now?\n\n" | |
mb.setText(caption) | |
ret = mb.exec_() | |
if ret == mb.Ok: | |
writeFile() | |
QtGui.QMessageBox.information(window,"Success","File successfully created. Please note: if you uninstall "+BASENAME+" macro you need to manually remove "+py_file+", too.\n") | |
else: | |
new_lines = [] | |
for line in code.splitlines(): | |
if line.startswith('#'): | |
if "CODE_ENDS_HERE" in line: | |
break | |
if line == "# -*- coding: utf-8 -*-": | |
new_lines.append(line+"\n") | |
continue | |
new_lines.append(line[1:]+"\n") | |
code = "".join(new_lines) | |
#credit to Mila Nautikus for his answer to a question on stackoverflow, which I modified here | |
#in this example the filename is easyreflector.py | |
#https://stackoverflow.com/questions/5362771/how-to-load-a-module-from-code-in-a-string | |
########## | |
import sys, importlib | |
my_name = BASENAME | |
my_spec = importlib.util.spec_from_loader(my_name, loader=None) | |
my_macro = importlib.util.module_from_spec(my_spec) | |
exec(code,my_macro.__dict__) | |
sys.modules[BASENAME] = my_macro | |
makeObject(my_macro) | |
noImport = True | |
if not noImport: #don't never use no double negatives | |
import addonmanager_utilities as utils | |
try: | |
import easyreflector as FP | |
except: | |
import EasyReflector as FP | |
if FP.__version__ != __version__: | |
writeFile() | |
from PySide import QtCore,QtGui | |
window = QtGui.QApplication.activeWindow() | |
mbox = QtGui.QMessageBox() | |
mbox.setWindowTitle(BASENAME+" updated") | |
mbox.setText(BASENAME+".py has been updated to version "+__version__+". \ | |
You must restart FreeCAD for the new changes to take effect and to use the macro.") | |
mbox.setIcon(mbox.Warning) | |
mbox.setStandardButtons(mbox.Ok) | |
mbox.addButton(QtGui.QMessageBox.Cancel) | |
mbox.setDefaultButton(mbox.Cancel) | |
okBtn = mbox.button(QtGui.QMessageBox.StandardButton.Ok) | |
cancelBtn = mbox.button(QtGui.QMessageBox.StandardButton.Cancel) | |
okBtn.setText("Restart now") | |
cancelBtn.setText("Restart later") | |
ret = mbox.exec_() | |
if ret == mbox.Ok: | |
QtCore.QTimer.singleShot(1000, utils.restart_freecad) | |
else: | |
makeObject(FP) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment