jumeaux-numeriques/twin_about.py

420 lines
19 KiB
Python

import bge # Bibliothèque Blender Game Engine (UPBGE)
import bpy # Blender
import sys
import webbrowser
###############################################################################
# twin_about.py
# @title: A propos de l'environnement 3D pour jumeau numérique
# @project: Blender-EduTech
# @lang: fr
# @authors: Philippe Roy <philippe.roy@ac-grenoble.fr>
# @copyright: Copyright (C) 2020-2024 Philippe Roy
# @license: GNU GPL
###############################################################################
# UPBGE scene
scene = bge.logic.getCurrentScene()
eevee = bpy.context.scene.eevee
# Colors
color_link = (0.198, 0.109, 0.8, 1) # Violet
color_link_hl = (0.8, 0.005, 0.315, 1) # Magenta
# color_link = (0.051, 0.270, 0.279,1) # Turquoise
# color_link = (0.024, 0.006, 0.8, 1) # Bleu
# color_link = (0.8, 0.005, 0.315, 1) # Magenta
# UPBGE constants
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
###############################################################################
# Crédits
###############################################################################
credits_description = {
'Blender' : ["Blender","Plateforme de modélisation et d\"animation 3D","https://blender.org", "GNU GPL"],
'UPBGE' : ["UPBGE","Moteur de jeu 3D","https://upbge.org", "GNU GPL"],
'Python' : ["Python","Langage de programmation","https://python.org", "PSFL"],
'Pylint' : ["Pylint","Bibliothèque de vérification d\"un code Python","https://pylint.pycqa.org", "GNU GPL"],
'pySerial' : ["pySerial","Bibliothèque de communication série","https://pyserial.readthedocs.io", "BSD-3-Clause"],
'pyFirmata' : ["pyFirmata","Bibliothèque du protocole Firmata","https://pyfirmata.readthedocs.io", "MIT Licence"],
'Matplotlib' : ["Matplotlib","Bibliothèque de visualisation graphique de données","https://matplotlib.org", "BSD"],
'wxWidgets' : ["wxWidgets","Bibliothèque GUI","https://www.wxwidgets.org", "wxWindows Library Licence"],
'wxPython' : ["wxPython","API Python de wxWidgets","https://www.wxpython.org", "GNU GPL"],
'Qt6' : ["Qt6","Bibliothèque GUI","https://www.qt.io", "GNU LGPL-3"],
'PyQt' : ["PyQt","API Python de Qt6","https://www.riverbankcomputing.com/software/pyqt","GNU GPL"],
'Game-icons.net' : ["Game-icons.net","Icônes","https://game-icons.net/","CC BY 3.0"],
'Kenney' : ["Kenney","Icônes","https://www.kenney.nl/","CC0 1.0"],
'EspressoDolce' : ["Espresso Dolce","Police de caractères","https://www.dafont.com/fr/espresso-dolce.font", "OFL"]}
###############################################################################
# Interface
###############################################################################
##
# Ouverture
##
def open():
scene.objects['System']['manip_mode']=9 # Fenêtre modale About
scene.active_camera = scene.objects["Camera-About"]
# scene.removeOverlayCollection(bpy.data.collections['Hud']) # Crash de UPBGE sur la supression de l'Overlay
scene.objects['Twins-icon'].setVisible(False,True) # Crash de UPBGE sur la supression de l'Overlay
scene.objects['Twins-text'].setVisible(False,True) # Crash de UPBGE sur la supression de l'Overlay
scene.objects['Script-icon'].setVisible(False,True) # Crash de UPBGE sur la supression de l'Overlay
scene.objects['Script-text'].setVisible(False,True) # Crash de UPBGE sur la supression de l'Overlay
scene.objects['About_close'].color= color_link
scene.objects['About_credits'].color= color_link
scene.objects["About_text-git"].color = color_link
scene.objects["About_text2-git"].color = color_link
scene.objects["About_text-upbge"].color = color_link
# Mémorisation de la position des pages
scene.objects["About"]['init_lx']=scene.objects["About"].worldPosition.x
scene.objects["About"]['init_ly']=scene.objects["About"].worldPosition.y
scene.objects["About"]['init_lz']=scene.objects["About"].worldPosition.z
scene.objects["Credits"]['init_lx']=scene.objects["Credits"].worldPosition.x
scene.objects["Credits"]['init_ly']=scene.objects["Credits"].worldPosition.y
scene.objects["Credits"]['init_lz']=scene.objects["Credits"].worldPosition.z
# Configuration
scene.objects['About_screen-up'].color= color_link
scene.objects['About_screen-down'].color= color_link
scene.objects['About_screen']['Text']= "Taille écran : "+str(bge.render.getWindowWidth()) +" x "+str(bge.render.getWindowHeight())
scene.objects['About_quality-up'].color= color_link
scene.objects['About_quality-down'].color= color_link
quality_txt=("Inconvenant", "Basse", "Moyenne", "Haute", "Épique")
scene.objects['About_quality']['Text']= "Qualité : "+quality_txt[scene.objects['About']['quality']]
# Liens
scene.objects['About_link-git'].color= color_link
scene.objects['About_link-gpl'].color= color_link
scene.objects['About_link-upbge'].color= color_link
scene.objects['About'].setVisible(True,True)
# Taille de l'écran : Boutons < et > ("640x360", "960x540", "1280x720", "1920x1080")
if bge.render.getWindowWidth() <=640:
scene.objects['About_screen-down'].setVisible(False,True)
scene.objects['About_screen-down-colbox'].suspendPhysics (True)
else:
scene.objects['About_screen-down'].setVisible(True,True)
scene.objects['About_screen-down-colbox'].restorePhysics()
if bge.render.getWindowWidth() >= 1920:
scene.objects['About_screen-up'].setVisible(False,True)
scene.objects['About_screen-up-colbox'].suspendPhysics (True)
else:
scene.objects['About_screen-up'].setVisible(True,True)
scene.objects['About_screen-up-colbox'].restorePhysics()
# Qualité du rendu : Boutons < et >
if scene.objects['About']['quality']==4:
scene.objects['About_quality-up'].setVisible(False,True)
scene.objects['About_quality-up-colbox'].suspendPhysics (True)
else:
scene.objects['About_quality-up'].setVisible(True,True)
scene.objects['About_quality-up-colbox'].restorePhysics()
if scene.objects['About']['quality']==0:
scene.objects['About_quality-down'].setVisible(False,True)
scene.objects['About_quality-down-colbox'].suspendPhysics (True)
else:
scene.objects['About_quality-down'].setVisible(True,True)
scene.objects['About_quality-down-colbox'].restorePhysics()
##
# Fermer
##
def close(cont):
if cont.sensors['Click'].status == JUST_ACTIVATED and cont.sensors['MO'].positive :
scene.objects['System']['manip_mode']=0 # Enlever la fenêtre modale
scene.active_camera = scene.objects["Camera"]
# scene.addOverlayCollection(scene.cameras['Camera-Hud'], bpy.data.collections['Hud']) # Crash de UPBGE sur la supression de l'Overlay
scene.objects['Twins-icon'].setVisible(True,True) # Crash de UPBGE sur la supression de l'Overlay
scene.objects['Twins-text'].setVisible(True,True) # Crash de UPBGE sur la supression de l'Overlay
scene.objects['Script-icon'].setVisible(True,True) # Crash de UPBGE sur la supression de l'Overlay
scene.objects['Script-text'].setVisible(True,True) # Crash de UPBGE sur la supression de l'Overlay
bpy.context.view_layer.update() # Bug de mise à jour
# scene.objects['Cmd-text']['Text']= " " # Redraw pour afficher scene.objects['Twins-icon'] et scene.objects['Twins-text']
scene.objects['About'].setVisible(False,True)
##
# Highlight
##
def hl(cont):
# Focus souris
if cont.sensors['MO'].status == JUST_ACTIVATED:
obj = cont.owner
name=obj.name[:-7]
scene.objects[name].color = color_link_hl
# Liens composés de texte
if name == "About_link-git":
scene.objects["About_text-git"].color = color_link_hl
scene.objects["About_text2-git"].color = color_link_hl
if name == "About_link-upbge":
scene.objects["About_text-upbge"].color = color_link_hl
# Perte du focus souris
if cont.sensors['MO'].status == JUST_RELEASED:
obj = cont.owner
name=obj.name[:-7]
scene.objects[name].color = color_link
# Liens composés de texte
if name == "About_link-git":
scene.objects["About_text-git"].color = color_link
scene.objects["About_text2-git"].color = color_link
if name == "About_link-upbge":
scene.objects["About_text-upbge"].color = color_link
##
# Liens
##
def link(cont):
if cont.sensors['Click'].status == JUST_ACTIVATED and cont.sensors['MO'].positive :
obj = cont.owner
name=obj.name[:-7]
link={
'About_link-git' : 'https://forge.apps.education.fr/blender-edutech/jumeaux-numeriques',
'About_link-gpl' : 'https://www.gnu.org/licenses/gpl-3.0.html',
'About_link-upbge' : 'https://www.upbge.org'}
webbrowser.open(link [name])
###############################################################################
# Crédits
###############################################################################
def credits(cont):
if cont.sensors['Click'].status == JUST_ACTIVATED and cont.sensors['MO'].positive :
# Afficher la page Crédits
scene.objects["Credits"].worldPosition.x = scene.objects["About"]['init_lx']
scene.objects["Credits"].worldPosition.y = scene.objects["About"]['init_ly']
scene.objects["Credits"].worldPosition.z = scene.objects["About"]['init_lz']
scene.objects["About"].worldPosition.x = scene.objects["Credits"]['init_lx']
scene.objects["About"].worldPosition.y = scene.objects["Credits"]['init_ly']
scene.objects["About"].worldPosition.z = scene.objects["Credits"]['init_lz']
scene.objects['About'].setVisible(False,True)
scene.objects['Credits'].setVisible(True,True)
scene.objects['Credits_close'].color= color_link
# Afficher les descriptions
credits_description_list=list (credits_description)
for i in range(len(credits_description_list)):
scene.objects["Credits_url-"+str(i+1)]['Text']= credits_description[credits_description_list[i]][0]
scene.objects["Credits_url-"+str(i+1)].color= color_link
scene.objects["Credits_text-"+str(i+1)]['Text']= credits_description[credits_description_list[i]][1]
scene.objects["Credits_license-"+str(i+1)]['Text']= credits_description[credits_description_list[i]][3]
def credits_close(cont):
if cont.sensors['Click'].status == JUST_ACTIVATED and cont.sensors['MO'].positive :
# Revenir à la page About
scene.objects["Credits"].worldPosition.x = scene.objects["Credits"]['init_lx']
scene.objects["Credits"].worldPosition.y = scene.objects["Credits"]['init_ly']
scene.objects["Credits"].worldPosition.z = scene.objects["Credits"]['init_lz']
scene.objects["About"].worldPosition.x = scene.objects["About"]['init_lx']
scene.objects["About"].worldPosition.y = scene.objects["About"]['init_ly']
scene.objects["About"].worldPosition.z = scene.objects["About"]['init_lz']
scene.objects['Credits'].setVisible(False,True)
scene.objects['About'].setVisible(True,True)
def credits_link(cont):
if cont.sensors['Click'].status == JUST_ACTIVATED and cont.sensors['MO'].positive :
obj = cont.owner
idx=int(obj.name[12:-7])
webbrowser.open(credits_description[list(credits_description)[idx-1]][2])
###############################################################################
# Configuration
###############################################################################
##
# Taille de l'écran
##
def get_near_pos(value_list,value):
delta=[]
for i in range (len(value_list)):
delta.append(abs(value-value_list[i]))
return delta.index(min(delta))
# Taille de l'écran +
def screen_up(cont):
if cont.sensors['Click'].status == JUST_ACTIVATED and cont.sensors['MO'].positive :
screen_width_mode=[640, 960, 1280, 1920]
screen_height_mode=[360, 540, 720,1080]
screen_mode_txt=["640x360", "960x540", "1280x720", "1920x1080"]
i = get_near_pos(screen_width_mode, bge.render.getWindowWidth())
if i>=0 and i<3 :
if bge.render.getWindowWidth()<screen_width_mode[i]:
screen_width=screen_width_mode[i]
screen_height=screen_height_mode[i]
else:
screen_width=screen_width_mode[i+1]
screen_height=screen_height_mode[i+1]
scene.objects['About_screen']['Text']= "Taille écran : "+str(screen_width) +" x "+str(screen_height)
bge.render.setWindowSize(screen_width,screen_height)
# Boutons < et >
if screen_width <=640:
scene.objects['About_screen-down'].setVisible(False,True)
scene.objects['About_screen-down-colbox'].suspendPhysics (True)
else:
scene.objects['About_screen-down'].setVisible(True,True)
scene.objects['About_screen-down-colbox'].restorePhysics()
if screen_width >= 1920:
scene.objects['About_screen-up'].setVisible(False,True)
scene.objects['About_screen-up-colbox'].suspendPhysics (True)
else:
scene.objects['About_screen-up'].setVisible(True,True)
scene.objects['About_screen-up-colbox'].restorePhysics()
# Taille de l'écran -
def screen_down(cont):
if cont.sensors['Click'].status == JUST_ACTIVATED and cont.sensors['MO'].positive :
screen_width_mode=[640, 960, 1280, 1920]
screen_height_mode=[360, 540, 720,1080]
screen_mode_txt=["640x360", "960x540", "1280x720", "1920x1080"]
i = get_near_pos(screen_width_mode, bge.render.getWindowWidth())
if i>0 and i<=3 :
if bge.render.getWindowWidth()>screen_width_mode[i]:
screen_width=screen_width_mode[i]
screen_height=screen_height_mode[i]
else:
screen_width=screen_width_mode[i-1]
screen_height=screen_height_mode[i-1]
scene.objects['About_screen']['Text']= "Taille écran : "+str(screen_width) +" x "+str(screen_height)
bge.render.setWindowSize(screen_width,screen_height)
# Boutons < et >
if screen_width <=640:
scene.objects['About_screen-down'].setVisible(False,True)
scene.objects['About_screen-down-colbox'].suspendPhysics (True)
else:
scene.objects['About_screen-down'].setVisible(True,True)
scene.objects['About_screen-down-colbox'].restorePhysics()
if screen_width >= 1920:
scene.objects['About_screen-up'].setVisible(False,True)
scene.objects['About_screen-up-colbox'].suspendPhysics (True)
else:
scene.objects['About_screen-up'].setVisible(True,True)
scene.objects['About_screen-up-colbox'].restorePhysics()
##
# Qualité du rendu
##
def quality_up(cont):
if cont.sensors['Click'].status == JUST_ACTIVATED and cont.sensors['MO'].positive :
scene.objects['About']['quality'] +=1
quality_apply(scene.objects['About']['quality'])
# Boutons < et >
if scene.objects['About']['quality']==4:
scene.objects['About_quality-up'].setVisible(False,True)
scene.objects['About_quality-up-colbox'].suspendPhysics (True)
if scene.objects['About']['quality']==1:
scene.objects['About_quality-down'].setVisible(True,True)
scene.objects['About_quality-down-colbox'].restorePhysics()
def quality_down(cont):
if cont.sensors['Click'].status == JUST_ACTIVATED and cont.sensors['MO'].positive :
scene.objects['About']['quality'] -=1
quality_apply(scene.objects['About']['quality'])
# Boutons < et >
if scene.objects['About']['quality']==0:
scene.objects['About_quality-down'].setVisible(False,True)
scene.objects['About_quality-down-colbox'].suspendPhysics (True)
if scene.objects['About']['quality']==3:
scene.objects['About_quality-up'].setVisible(True,True)
scene.objects['About_quality-up-colbox'].restorePhysics()
##
# Qualité du rendu EEVEE de 0 à 4
##
def quality_apply(quality, start_flag=False):
# Texte du About
quality_txt=("Inconvenant", "Basse", "Moyenne", "Haute", "Épique")
scene.objects['About_quality']['Text']= "Qualité : "+quality_txt[quality]
if start_flag== False and sys.platform!="linux": # Plantage sur Windows -> redémarrage après changement
return
# Inconvenant
if quality== 0:
eevee.use_taa_reprojection = False
eevee.use_ssr = False # Screen space reflection
eevee.use_gtao = False # Ambient occlusion
eevee.taa_render_samples = 1
eevee.taa_samples = 1
eevee.use_volumetric_lights = False
eevee.use_volumetric_shadows = False
eevee.shadow_cascade_size='64'
eevee.shadow_cube_size='64'
# Basse
if quality== 1:
eevee.use_taa_reprojection = True
eevee.use_ssr = True # Screen space reflection
eevee.use_ssr_refraction = False # Screen space refractions
eevee.use_ssr_halfres = True
eevee.use_gtao = False
eevee.taa_render_samples = 32
eevee.taa_samples = 8
eevee.use_volumetric_lights = True
eevee.use_volumetric_shadows = False
eevee.shadow_cascade_size='1024'
eevee.shadow_cube_size='512'
# Moyenne
if quality== 2:
eevee.use_taa_reprojection = True
eevee.use_ssr = True # Screen space reflection
eevee.use_ssr_refraction = True # Screen space refractions
eevee.use_ssr_halfres = True
eevee.use_gtao = False
eevee.taa_render_samples = 64
eevee.taa_samples = 16
eevee.use_volumetric_lights = True
eevee.use_volumetric_shadows = False
eevee.shadow_cascade_size='1024'
eevee.shadow_cube_size='512'
# Haute
if quality== 3:
eevee.use_taa_reprojection = True
eevee.use_ssr = True
eevee.use_ssr_refraction = True
eevee.use_ssr_halfres = False
eevee.use_gtao = False
eevee.taa_render_samples = 64
eevee.taa_samples = 16
eevee.use_volumetric_lights = True
eevee.use_volumetric_shadows = False
eevee.shadow_cascade_size='1024'
eevee.shadow_cube_size='512'
# Épique
if quality== 4:
eevee.use_taa_reprojection = True
eevee.use_ssr = True
eevee.use_ssr_refraction = True
eevee.use_ssr_halfres = False
eevee.use_gtao = True
eevee.taa_render_samples = 64
eevee.taa_samples = 16
eevee.use_volumetric_lights = True
eevee.use_volumetric_shadows = True
eevee.shadow_cascade_size='4096'
eevee.shadow_cube_size='4096'