import bge # Blender Game Engine (UPBGE) import bpy # Blender import webbrowser import math import xml.etree.ElementTree as ET # Creating/parsing XML file import jumeau_doc # Documentation import jumeau_about # About ############################################################################### # jumeau.py # @title: Bibliothèque générale du l'environnement 3D pour le développement de jumeau numérique # @project: Blender-EduTech # @lang: fr # @authors: Philippe Roy # @copyright: Copyright (C) 2020-2022 Philippe Roy # @license: GNU GPL # # Cet environnement 3D est programmable en Python. Il est destiné à la découverte de la programmation de système pluritechnologique. # ############################################################################### # UPBGE scene eevee = bpy.context.scene.eevee scene = bge.logic.getCurrentScene() # print("Objets de la scene : ", scene.objects) # Config file jumeau_config = ET.parse('jumeau_config.xml') jumeau_config_tree = jumeau_config.getroot() # Couleurs color_cmd = [0.8, 0.8, 0.8, 1] # Blanc color_cmd_hl = [0.8, 0.619, 0.021, 1] # Jaune color_rep_enabled = [0.8, 0.8, 0.8, 1] # Blanc color_rep_disabled = [0, 0, 0, 1] # Noir # Constantes JUST_ACTIVATED = bge.logic.KX_INPUT_JUST_ACTIVATED JUST_RELEASED = bge.logic.KX_INPUT_JUST_RELEASED ACTIVATE = bge.logic.KX_INPUT_ACTIVE # JUST_DEACTIVATED = bge.logic.KX_SENSOR_JUST_DEACTIVATED ############################################################################### # Gestion du clavier ############################################################################### # Mode : Orbit(0) par défaut, Pan(1) avec Shift, Zoom (2) avec Ctrl, Eclaté (1) avec Shift def keyboard(cont): obj = scene.objects['System'] keyboard = bge.logic.keyboard # Touche ESC if JUST_ACTIVATED in keyboard.inputs[bge.events.ESCKEY].queue: # Maj du fichier de config (screen size : data/config/screen/width-> [0][0].text) screen_width = bge.render.getWindowWidth() screen_height = bge.render.getWindowHeight() jumeau_config_tree[0][0].text=str(screen_width) jumeau_config_tree[0][1].text=str(screen_height) buffer_xml = ET.tostring(jumeau_config_tree) with open("jumeau_config.xml", "wb") as f: f.write(buffer_xml) # Sortir bge.logic.endGame() # Shift -> mode 1 : Pan (clic milieu) ou Eclaté (clic gauche) if JUST_ACTIVATED in keyboard.inputs[bge.events.LEFTSHIFTKEY].queue: obj['manip_mode']=1 if JUST_ACTIVATED in keyboard.inputs[bge.events.RIGHTSHIFTKEY].queue: obj['manip_mode']=1 # Ctrl -> mode 2 : Zoom (clic milieu) if JUST_ACTIVATED in keyboard.inputs[bge.events.LEFTCTRLKEY].queue: obj['manip_mode']=2 if JUST_ACTIVATED in keyboard.inputs[bge.events.RIGHTCTRLKEY].queue: obj['manip_mode']=2 # Pas de modificateur -> mode 0 : Orbit (clic milieu) if JUST_RELEASED in keyboard.inputs[bge.events.LEFTSHIFTKEY].queue: obj['manip_mode']=0 if JUST_RELEASED in keyboard.inputs[bge.events.RIGHTSHIFTKEY].queue: obj['manip_mode']=0 if JUST_RELEASED in keyboard.inputs[bge.events.LEFTCTRLKEY].queue: obj['manip_mode']=0 if JUST_RELEASED in keyboard.inputs[bge.events.RIGHTCTRLKEY].queue: obj['manip_mode']=0 # Touche Home -> Reset de la vue if JUST_ACTIVATED in keyboard.inputs[bge.events.HOMEKEY].queue: manip_reset() # Touche Space -> Play et Pause if JUST_ACTIVATED in keyboard.inputs[bge.events.SPACEKEY].queue: if scene.objects['System']['anim'] == True: # anim_pause() scene.objects['Pause'].setVisible(False,False) scene.objects['Play'].setVisible(True,False) else: # anim_play() scene.objects['Play'].setVisible(False,False) scene.objects['Pause'].setVisible(True,False) ############################################################################### # Commandes ############################################################################### ## # Initialisation des commandes ## def cmd_init(): # Fichier de config (screen size : data/config/screen/width-> [0][0].text, height-> [0][1].text) bge.render.setWindowSize(int(jumeau_config_tree[0][0].text),int(jumeau_config_tree[0][1].text)) scene.objects['Play-Hl'].setVisible(False,False) scene.objects['Pause-Hl'].setVisible(False,False) scene.objects['Reset-view-Hl'].setVisible(False,False) scene.objects['Doc-cmd-Hl'].setVisible(False,False) scene.objects['About-cmd-Hl'].setVisible(False,False) ## # Highlight des commandes ## def cmd_hl(cont): obj = cont.owner # Activation if cont.sensors['MO'].status == JUST_ACTIVATED and scene.objects['System']['manip_mode']==0: if obj.name!="Play" and obj.name!="Pause" and obj.name!="Play-Hl" and obj.name!="Pause-Hl": obj.setVisible(False,True) scene.objects[obj.name+'-Hl'].setVisible(True,True) # obj.color = color_cmd_hl # Play et pause if obj.name=="Pause" or obj.name=="Play": if scene.objects['System']['anim'] == True: scene.objects['Pause'].setVisible(False,False) scene.objects['Pause-Hl'].setVisible(True,False) else: scene.objects['Play'].setVisible(False,False) scene.objects['Play-Hl'].setVisible(True,False) # Désactivation if cont.sensors['MO'].status == JUST_RELEASED and scene.objects['System']['manip_mode']==0: if obj.name!="Play" and obj.name!="Pause" and obj.name!="Play-Hl" and obj.name!="Pause-Hl": scene.objects[obj.name+'-Hl'].setVisible(False,True) obj.setVisible(True,True) # Play et pause if obj.name=="Pause" or obj.name=="Play": if scene.objects['System']['anim'] == True: scene.objects['Pause-Hl'].setVisible(False,False) scene.objects['Pause'].setVisible(True,False) else: scene.objects['Play-Hl'].setVisible(False,False) scene.objects['Play'].setVisible(True,False) ## # Click sur les commandes ## def cmd_click(cont): obj = cont.owner if cont.sensors['Click'].status == JUST_ACTIVATED and cont.sensors['MO'].positive and scene.objects['System']['manip_mode']==0: # Play et pause if obj.name=="Pause" or obj.name=="Run": # Pause if scene.objects['System']['anim'] == True: anim_pause() scene.objects['Pause'].setVisible(False,False) scene.objects['Pause-Hl'].setVisible(False,False) scene.objects['Play-Hl'].setVisible(True,False) else: # Play anim_play() scene.objects['Play'].setVisible(False,False) scene.objects['Play-Hl'].setVisible(False,False) scene.objects['Pause-Hl'].setVisible(True,False) # Reset-colors if obj.name=="Reset-colors" : color_reset() # Reset-view if obj.name=="Reset-view" : manip_reset() # About if obj.name=="About-cmd" : if scene.objects['System']['anim'] == True: # Rendu meilleur en pause scene.objects['About']['anim']= True anim_pause() else: scene.objects['About']['anim'] = False cine_about.open() # Aide if obj.name=="Help-cmd" : if scene.objects['System']['anim'] == True: # Rendu meilleur en pause scene.objects['Doc']['anim']= True anim_pause() else: scene.objects['Doc']['anim'] = False cine_doc.open() ############################################################################### # Manipulation du mécanisme ############################################################################### ## # Dessiner une cercle (bas niveau) ## def circle (center, radius, color): ang = 0 ang_step = 0.1 while ang< 2 * math.pi: x0 = center[0]+float(radius*math.cos(ang)*0.95) y0 = center[1] z0 = center[2]+float(radius*math.sin(ang)) x1 = center[0]+float(radius*math.cos(ang+ang_step)*0.95) y1 = center[1] z1 = center[2]+float(radius*math.sin(ang+ang_step)) bge.render.drawLine([x0,y0,z0],[x1,y1,z1],color) ang += ang_step ## # Initialisation de la vue 3D ## # def manip_init(cont): def manip_init(): # Configuration du moteur de rendu eevee.use_eevee_smaa = True # Fenêtres scene.objects['About'].setVisible(False,True) scene.objects['Doc'].setVisible(False,True) # Mémorisation de la position des composants for objet in scene.objects['System']['objects'] : scene.objects[objet]['init_lx']=scene.objects[objet].worldPosition.x scene.objects[objet]['init_ly']=scene.objects[objet].worldPosition.y scene.objects[objet]['init_lz']=scene.objects[objet].worldPosition.z if 'init_rx' in scene.objects[objet]: scene.objects[objet]['init_rx'] = scene.objects[objet].worldOrientation.to_euler().x if 'init_ry' in scene.objects[objet]: scene.objects[objet]['init_ry'] = scene.objects[objet].worldOrientation.to_euler().y if 'init_rz' in scene.objects[objet]: scene.objects[objet]['init_rz'] = scene.objects[objet].worldOrientation.to_euler().z # Mémorisation de la position de la caméra scene.objects['Camera']['init_lx']=scene.objects['Camera'].worldPosition.x scene.objects['Camera']['init_ly']=scene.objects['Camera'].worldPosition.y scene.objects['Camera']['init_lz']=scene.objects['Camera'].worldPosition.z # Mémorisation de la position du modèle scene.objects['System']['init_lx']=scene.objects['System'].worldPosition.x scene.objects['System']['init_ly']=scene.objects['System'].worldPosition.y scene.objects['System']['init_lz']=scene.objects['System'].worldPosition.z scene.objects['System']['init_rx']=scene.objects['System'].worldOrientation.to_euler().x scene.objects['System']['init_ry']=scene.objects['System'].worldOrientation.to_euler().y scene.objects['System']['init_rz']=scene.objects['System'].worldOrientation.to_euler().z ## # Atteindre une orientation (bas niveau) ## def applyRotationTo(obj, rx=None, ry=None, rz=None): rres=0.001 # resolution rotation # x if rx is not None: while (abs(rx-obj.worldOrientation.to_euler().x) > rres) : if obj.worldOrientation.to_euler().x-rx > rres: obj.applyRotation((-rres, 0, 0), True) if rx-obj.worldOrientation.to_euler().x > rres: obj.applyRotation((rres, 0, 0), True) # print ("delta x ",rx-obj.worldOrientation.to_euler().x) # y if ry is not None: while (abs(ry-obj.worldOrientation.to_euler().y) > rres) : if obj.worldOrientation.to_euler().y-ry > rres: obj.applyRotation((0, -rres, 0), True) if ry-obj.worldOrientation.to_euler().y > rres: obj.applyRotation((0, rres, 0), True) # print ("delta y ",ry-obj.worldOrientation.to_euler().y) # z if rz is not None: while (abs(rz-obj.worldOrientation.to_euler().z) > rres) : if obj.worldOrientation.to_euler().z-rz > rres: obj.applyRotation((0, 0, -rres), True) if rz-obj.worldOrientation.to_euler().z > rres: obj.applyRotation((0, 0, rres), True) # print ("delta z ",rz-obj.worldOrientation.to_euler().z) ## # Reset de la manipulation de la vue ## def manip_reset(): scene.objects['Camera'].worldPosition.x = scene.objects['Camera']['init_lx'] scene.objects['Camera'].worldPosition.y = scene.objects['Camera']['init_ly'] scene.objects['Camera'].worldPosition.z = scene.objects['Camera']['init_lz'] applyRotationTo(scene.objects['System'], 0, 0, 0) scene.objects['System'].worldPosition.x = scene.objects['System']['init_lx'] scene.objects['System'].worldPosition.y = scene.objects['System']['init_ly'] scene.objects['System'].worldPosition.z = scene.objects['System']['init_lz'] for objet in scene.objects['System']['objects'] : scene.objects[objet].setVisible(True,False) scene.objects[objet].restorePhysics() if objet+"_Lines.GP" in scene.objects: scene.objects[objet+"_Lines.GP"].setVisible(True,False) ## # Position de départ pour la manipulation de la vue ## def manip_start(cont): obj = cont.owner obj['click_x']=cont.sensors['ClickM'].position[0] obj['click_y']=cont.sensors['ClickM'].position[1] ## # Manipulation du modèle ou de la caméra ## def manip(cont): obj = cont.owner sensibilite_orbit=0.0005 sensibilite_pan=0.005 sensibilite_zoom=0.01 delta_x=cont.sensors['DownM'].position[0]-obj['click_x'] delta_y=cont.sensors['DownM'].position[1]-obj['click_y'] # Orbit if obj['manip_mode']==0: x0 = scene.objects['Orbit'].worldPosition.x y0 =scene.objects['Orbit'].worldPosition.y z0 =scene.objects['Orbit'].worldPosition.z width = bge.render.getWindowWidth() height = bge.render.getWindowHeight() dist_orbit_y_base=200 # Pour 1280 x 720 radius_orbit_y_base=5 diag_base= math.sqrt(1280**2+720**2) diag= math.sqrt(width**2+height**2) dist_orbit_y = dist_orbit_y_base*(diag/diag_base) radius_orbit_y=radius_orbit_y_base*(diag/diag_base) dist_orbit = math.sqrt(((width/2)-obj['click_x'])**2+((height/2)-obj['click_y'])**2) if obj['click_y']> height/2 : dist_orbit = dist_orbit+((math.sqrt(((height/2)-obj['click_y'])**2)/175)*25) # Correction des Y sous le centre ? if dist_orbit= abs(delta_y): scene.objects['System'].applyRotation((0, delta_x*sensibilite_orbit, 0), False) else: scene.objects['System'].applyRotation((0, delta_y*sensibilite_orbit, 0), False) # Pan if obj['manip_mode']==1: # Shift scene.objects['System'].applyMovement((delta_x*sensibilite_pan, -delta_y*sensibilite_pan, -delta_y*sensibilite_pan), False) # scene.objects['Camera'].applyMovement((delta_x*-sensibilite_pan, delta_y*sensibilite_pan, 0), True) # Zoom if obj['manip_mode']==2: # Ctrl scene.objects['Camera'].applyMovement((0, 0, (delta_x+delta_y)*sensibilite_zoom), True) scene.objects['Camera'].applyMovement((0, 0, (delta_x+delta_y)*sensibilite_zoom), True) ## # Zoom ## def manip_wheel(cont): obj = cont.owner sensibilite_wheel = 20 if cont.sensors['WheelUp'].positive: scene.objects['Camera'].applyMovement((0, 0, -sensibilite_wheel), True) if cont.sensors['WheelDown'].positive: scene.objects['Camera'].applyMovement((0, 0, sensibilite_wheel), True)