jumeaux-numeriques/twin_doc.py

471 lines
23 KiB
Python

import bge # Bibliothèque Blender Game Engine (UPBGE)
import importlib
import webbrowser
###############################################################################
# twin_doc.py
# @title: Documentation 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-2022 Philippe Roy
# @license: GNU GPL
###############################################################################
# UPBGE scene
scene = bge.logic.getCurrentScene()
# Colors
# color_link = (0.198, 0.109, 0.8, 1) # Violet
# color_link_hl = (0.8, 0.005, 0.315, 1) # Magenta
# Colors
color_doc_chap = (0.198, 0.109, 0.8, 1) # Violet
color_doc_fct = (0.198, 0.109, 0.8, 1) # Violet
color_doc_hl = (0.8, 0.005, 0.315, 1) # Magenta
# color_doc_activate = (0.936, 0.033, 1, 1) # Activé : Rose
color_doc_activate = (0.051, 0.270, 0.279,1) # Turquoise
# color_doc_activate = (0.936, 0.033, 1, 1) # Activé : Rose
# 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
# Cards description
card_description ={}
# Documentation du sytème
system=importlib.import_module(scene.objects['System']['name']+'_doc') # Système
system_card = system.get_system_card()
card_description.update(system.get_card_description())
###############################################################################
# Documentation Python
###############################################################################
# python_card=["function-card", "alternative-card", "loop-card", "flow-card", "text-card", "list-card", "dict-card", "oop-card", "console-card", "sleep-card"]
python_card=["function-card", "alternative-card", "loop-card", "flow-card", "console-card", "sleep-card"]
# Fonction
card_function_title="Fonction"
card_function_text=" La définition d\"une fonction se fait avec \n \'def\'. La fonction peut renvoyer une \n valeur avec \'return\'. \n\n"
card_function_text=card_function_text + " def fonction_1 (arguments) : \n instruction_1 \n instruction_2 \n ....\n return valeurs_renvoyées \n\n"
card_function_text=card_function_text + " Les arguments sont des données \n transmises à la fonction."
card_function_url=[["w3schools.com : functions","https://www.w3schools.com/python/python_functions.asp"]]
card_description.update({"function-card" : [card_function_title, card_function_text, card_function_url]})
# Alternative
card_alternative_title="Alternative"
card_alternative_text=" L\"alternative permet d\"éxécuter des \n instructions en fonction d\"un test. \n"
card_alternative_text=card_alternative_text + " Elle se programme en suivant la suite : \n \'if \' (si) ... \'else\' (sinon) ... \n\n"
card_alternative_text=card_alternative_text + " if condition :\n"
card_alternative_text=card_alternative_text + " instruction_1\n"
card_alternative_text=card_alternative_text + " else : \n"
card_alternative_text=card_alternative_text + " instruction_2\n\n"
card_alternative_text=card_alternative_text + "Le \'else\' (sinon) est facultatif."
card_alternative_url=[["w3schools.com : if ... else","https://www.w3schools.com/python/python_conditions.asp"]]
card_description.update({"alternative-card" : [card_alternative_title, card_alternative_text, card_alternative_url]})
# Boucles
card_loop_title="Boucles"
card_loop_text=" Il y a deux types de boucle : \n - avec \'for\' pour définir un nombre de \n répétition (ici n), \n - avec \'while\' (tant que) pour prendre \n en compte une condition. \n \n"
card_loop_text=card_loop_text + " for i in range (n) : \n instruction \n \n"
card_loop_text=card_loop_text + " while condition : \n instruction"
card_loop_url=[["w3schools.com : for","https://www.w3schools.com/python/python_for_loops.asp"],
["w3schools.com : while","https://www.w3schools.com/python/python_while_loops.asp"]]
card_description.update({"loop-card" : [card_loop_title, card_loop_text, card_loop_url]})
# Flux
card_flow_title="Contrôle du flux"
card_flow_text=""" Les structures (if, while, for) peuvent \n être gérées plus finement par les \n fonctions \'break\', \'continue\' et \'pass\'. \n
- \'break\' : termine l\"itération en cours et \n arrête la boucle.
- \'continue\' : termine l\"itération en cours et \n reprend la boucle.
- \'pass\' : instruction vide."""
card_flow_url=[["w3schools.com : break","https://www.w3schools.com/python/ref_keyword_break.asp"],
["w3schools.com : continue","https://www.w3schools.com/python/ref_keyword_break.asp"],
["w3schools.com : pass","https://www.w3schools.com/python/ref_keyword_pass.asp"]]
card_description.update({"flow-card" : [card_flow_title, card_flow_text, card_flow_url]})
# Chaine de caractère
card_text_title="Chaîne de caractères\n(texte)"
card_text_text="\nFIXME"
card_text_url=[["w3schools.com : strings","https://www.w3schools.com/python/python_strings.asp"]]
card_description.update({"text-card" : [card_text_title, card_text_text, card_text_url]})
# Liste
card_list_title="Liste"
card_list_text="FIXME"
card_list_url=[["w3schools.com : lists","https://www.w3schools.com/python/python_lists.asp"]]
card_description.update({"list-card" : [card_list_title, card_list_text, card_list_url]})
# Dictionnaire
card_dict_title="Dictionnaire"
card_dict_text="FIXME"
card_dict_url=[["w3schools.com : dictionaries","https://www.w3schools.com/python/python_dictionaries.asp"]]
card_description.update({"dict-card" : [card_dict_title, card_dict_text, card_dict_url]})
# Objet (POO)
card_oop_title="Programmation\norientée objet (POO)"
card_oop_text="\nFIXME"
card_oop_url=[["w3schools.com : classes & objects","https://www.w3schools.com/python/python_classes.asp"]]
card_description.update({"oop-card" : [card_oop_title, card_oop_text, card_oop_url]})
# Console
card_console_title="Console"
card_console_text=" Si vous avez executé Ropy dans un \n terminal (avec l\"option \'-con\'), vous \n pouvez utiliser le terminal comme \n console de debuggage.\n\n"
card_console_text= card_console_text + " print(\'Bonjour !\') \n -> Affiche le texte dans la console.\n\n"
card_console_text= card_console_text + " variable = input () \n -> Permet la saisie, par exemple : \n"
card_console_text= card_console_text + " entree = \'\'\n while entree == \'\' :\n entree = input ()"
card_console_url=[["w3schools.com : print","https://www.w3schools.com/python/ref_func_print.asp"],
["w3schools.com : input","https://www.w3schools.com/python/ref_func_input.asp"]]
card_description.update({"console-card" : [card_console_title, card_console_text, card_console_url]})
# Temps
card_sleep_title="Gestion du temps"
card_sleep_text=" Vous pouvez créer des temporisations \n dans le déroulement du script.\n\n"
card_sleep_text= card_sleep_text + " time.sleep(x) \n -> Marque d\"un temps d\"arrêt de \n x secondes.\n\n"
card_sleep_text= card_sleep_text + " Il faudra préalablement importer la \n bibliothèque \'time\' avec \'import time\'."
card_sleep_url=[["docs.python.org : sleep","https://docs.python.org/fr/3/library/time.html#time.sleep"]]
card_description.update({"sleep-card" : [card_sleep_title, card_sleep_text, card_sleep_url]})
###############################################################################
# Interface
###############################################################################
##
# Initialisation de la documentation
##
def init():
# Mettre les couleurs sur les icones (chapitres et cartes)
chap=("general", "system", "python")
for page in chap:
scene.objects["Doc-"+page].color = color_doc_chap
scene.objects["Doc-"+page+"-text"].color = color_doc_chap
for i in range(len(system_card)):
scene.objects[system_card[i]].color = color_doc_fct
scene.objects[system_card[i]+"-icon"].color = color_doc_fct
scene.objects[system_card[i]+"-text"].color = color_doc_fct
for i in range(len(python_card)):
scene.objects[python_card[i]].color = color_doc_fct
scene.objects[python_card[i]+"-icon"].color = color_doc_fct
scene.objects[python_card[i]+"-text"].color = color_doc_fct
# Cacher et mettre les couleurs sur les liens (URL)
scene.objects['Doc_chap-system-url_title'].setVisible(False,True)
scene.objects['Doc_chap-system-url_title'].color = color_doc_activate
scene.objects['Doc_chap-python-url_title'].setVisible(False,True)
scene.objects['Doc_chap-python-url_title'].color = color_doc_activate
for i in range(3):
scene.objects['Doc_chap-python-url'+str(i)].setVisible(False,True)
scene.objects['Doc_chap-python-url'+str(i)+'-colbox'].suspendPhysics()
scene.objects['Doc_chap-python-url'+str(i)].color = color_doc_chap
scene.objects['Doc_chap-system-url'+str(i)].setVisible(False,True)
scene.objects['Doc_chap-system-url'+str(i)+'-colbox'].suspendPhysics()
scene.objects['Doc_chap-system-url'+str(i)].color = color_doc_chap
# Chargement du texte
text_load()
# Mémorisation de la position des pages
for page in chap:
scene.objects["Doc_chap-"+page]['init_lx']=scene.objects["Doc_chap-"+page].worldPosition.x
scene.objects["Doc_chap-"+page]['init_ly']=scene.objects["Doc_chap-"+page].worldPosition.y
scene.objects["Doc_chap-"+page]['init_lz']=scene.objects["Doc_chap-"+page].worldPosition.z
# Page par défaut
scene.objects['Doc']['page_chap'] = "general"
##
# Ouvrir la documentation
##
def open():
# Placer la tablette
scene.active_camera = scene.objects["Camera-Doc"]
scene.objects['Doc_close'].color= color_doc_fct
scene.objects['Doc'].setVisible(True,True)
text_hide()
# Placer le nouveau chapitre
name_chap = scene.objects['Doc']['page_chap']
scene.objects['Doc-'+name_chap].color = color_doc_activate
scene.objects['Doc-'+name_chap+'-text'].color = color_doc_activate
scene.objects['Doc_chap-'+name_chap].worldPosition = scene.objects['Doc'].worldPosition
scene.objects['Doc_chap-'+name_chap].setVisible(True,True)
# URL
if name_chap == "system" or name_chap == "python":
name_fct = scene.objects['Doc_chap-'+name_chap]['page_fct']
scene.objects['Doc_chap-'+name_chap+'-url_title'].setVisible(False,True)
for i in range(3):
scene.objects['Doc_chap-'+name_chap+'-url'+str(i)].setVisible(False,True)
scene.objects['Doc_chap-'+name_chap+'-url'+str(i)+'-colbox'].suspendPhysics()
if name_fct !="":
if len(card_description[name_fct][2])>0:
scene.objects['Doc_chap-'+name_chap+'-url_title'].setVisible(True,True)
for i in range(len(card_description[name_fct][2])):
scene.objects['Doc_chap-'+name_chap+'-url'+str(i)]['Text'] = card_description[name_fct][2][i][0]
scene.objects['Doc_chap-'+name_chap+'-url'+str(i)].setVisible(True,True)
scene.objects['Doc_chap-'+name_chap+'-url'+str(i)+'-colbox'].restorePhysics()
scene.objects['Doc_chap-'+name_chap+'-url'+str(i)+'-colbox']['Url'] = card_description[name_fct][2][i][1]
# Afficher le texte de la carte active
if name_chap != "general" and scene.objects['Doc_chap-'+name_chap]['page_fct'] !="":
name_fct = scene.objects['Doc_chap-'+name_chap]['page_fct']
scene.objects['Doc_title']['Text'] = card_description[name_fct][0]
scene.objects['Doc_title'].setVisible(True, False)
text_show(name_fct)
else:
scene.objects['Doc_title']['Text'] = " "
scene.objects['Doc_title'].setVisible(False,True)
text_hide()
##
# Fermer la documentation
##
def close(cont):
if cont.sensors['Click'].status == JUST_ACTIVATED and cont.sensors['MO'].positive :
scene.active_camera = scene.objects["Camera"]
chap=("general", "system", "python")
for page in chap:
scene.objects["Doc_chap-"+page].setVisible(False,True)
scene.objects["Doc_chap-"+page].worldPosition.x = scene.objects["Doc_chap-"+page]['init_lx']
scene.objects["Doc_chap-"+page].worldPosition.y = scene.objects["Doc_chap-"+page]['init_ly']
scene.objects["Doc_chap-"+page].worldPosition.z = scene.objects["Doc_chap-"+page]['init_lz']
scene.objects['Doc'].setVisible(False,True)
##
# Highlight
##
def hl (cont):
# Activation
if cont.sensors['MO'].status == JUST_ACTIVATED :
obj = cont.owner
name=obj.name[:-7]
name_text=name+"-text"
name_icon=name+"-icon"
# Close ou lien
if name == "Doc_close" :
scene.objects[name].color = color_doc_hl
elif name == "Doc_chap-python-url0" or name == "Doc_chap-python-url1" or name == "Doc_chap-python-url2":
scene.objects[name].color = color_doc_hl
elif name == "Doc_chap-system-url0" or name == "Doc_chap-system-url1" or name == "Doc_chap-system-url2":
scene.objects[name].color = color_doc_hl
else:
if "Doc-" in name : # Chapitre
if name[4:] == scene.objects['Doc']['page_chap']:
scene.objects[name].color = color_doc_activate
scene.objects[name_text].color = color_doc_activate
else:
scene.objects[name].color = color_doc_hl
scene.objects[name_text].color = color_doc_hl
else: # Carte
name_chap = scene.objects['Doc']['page_chap']
if name == scene.objects['Doc_chap-'+name_chap]['page_fct'] :
scene.objects[name].color = color_doc_activate
scene.objects[name_text].color = color_doc_activate
scene.objects[name_icon].color = color_doc_activate
else:
scene.objects[name].color = color_doc_hl
scene.objects[name_text].color = color_doc_hl
scene.objects[name_icon].color = color_doc_hl
# Désactivation
if cont.sensors['MO'].status == JUST_RELEASED :
obj = cont.owner
name=obj.name[:-7]
name_text=obj.name[:-7]+"-text"
name_icon=obj.name[:-7]+"-icon"
# Close ou lien
if name == "Doc_close" :
scene.objects[name].color = color_doc_fct
elif name == "Doc_chap-python-url0" or name == "Doc_chap-python-url1" or name == "Doc_chap-python-url2":
scene.objects[name].color = color_doc_fct
elif name == "Doc_chap-system-url0" or name == "Doc_chap-system-url1" or name == "Doc_chap-system-url2":
scene.objects[name].color = color_doc_fct
else:
if "Doc-" in name : # Chapitre
if name[4:] == scene.objects['Doc']['page_chap']:
scene.objects[name].color = color_doc_activate
scene.objects[name_text].color = color_doc_activate
else:
scene.objects[name].color = color_doc_fct
scene.objects[name_text].color = color_doc_fct
else: # Carte
name_chap = scene.objects['Doc']['page_chap']
if name == scene.objects['Doc_chap-'+name_chap]['page_fct'] :
scene.objects[name].color = color_doc_activate
scene.objects[name_text].color = color_doc_activate
scene.objects[name_icon].color = color_doc_activate
else:
scene.objects[name].color = color_doc_fct
scene.objects[name_text].color = color_doc_fct
scene.objects[name_icon].color = color_doc_fct
##
# Afficher le chapitre
##
def chapter(cont):
if cont.sensors['Click'].status == JUST_ACTIVATED and cont.sensors['MO'].positive and cont.sensors['Click'].positive:
obj = cont.owner
scene.objects['Doc_title']['Text'] = " "
# Enlever l'ancien chapitre
scene.objects['Doc-'+scene.objects['Doc']['page_chap']].color = color_doc_chap
scene.objects['Doc-'+scene.objects['Doc']['page_chap']+'-text'].color = color_doc_chap
scene.objects["Doc_chap-"+scene.objects['Doc']['page_chap']].worldPosition.x = scene.objects["Doc_chap-"+scene.objects['Doc']['page_chap']]['init_lx']
scene.objects["Doc_chap-"+scene.objects['Doc']['page_chap']].worldPosition.y = scene.objects["Doc_chap-"+scene.objects['Doc']['page_chap']]['init_ly']
scene.objects["Doc_chap-"+scene.objects['Doc']['page_chap']].worldPosition.z = scene.objects["Doc_chap-"+scene.objects['Doc']['page_chap']]['init_lz']
if scene.objects['Doc']['page_chap'] != "general" and scene.objects["Doc_chap-"+scene.objects['Doc']['page_chap']]['page_fct'] !="":
text_hide(scene.objects["Doc_chap-"+scene.objects['Doc']['page_chap']]['page_fct'])
# Placer le nouveau chapitre
name_chap= obj.name[4:-7]
scene.objects['Doc-'+name_chap].color = color_doc_activate
scene.objects['Doc-'+name_chap+'-text'].color = color_doc_activate
scene.objects['Doc']['page_chap'] = name_chap
scene.objects['Doc_chap-'+name_chap].worldPosition = scene.objects['Doc'].worldPosition
scene.objects['Doc_chap-'+name_chap].setVisible(True,True)
# URL
if name_chap == "system" or name_chap == "python":
name_fct = scene.objects['Doc_chap-'+name_chap]['page_fct']
scene.objects['Doc_chap-'+name_chap+'-url_title'].setVisible(False,True)
for i in range(3):
scene.objects['Doc_chap-'+name_chap+'-url'+str(i)].setVisible(False,True)
scene.objects['Doc_chap-'+name_chap+'-url'+str(i)+'-colbox'].suspendPhysics()
if name_fct !="":
if len(card_description[name_fct][2])>0:
scene.objects['Doc_chap-'+name_chap+'-url_title'].setVisible(True,True)
for i in range(len(card_description[name_fct][2])):
scene.objects['Doc_chap-'+name_chap+'-url'+str(i)]['Text'] = card_description[name_fct][2][i][0]
scene.objects['Doc_chap-'+name_chap+'-url'+str(i)].setVisible(True,True)
scene.objects['Doc_chap-'+name_chap+'-url'+str(i)+'-colbox'].restorePhysics()
scene.objects['Doc_chap-'+name_chap+'-url'+str(i)+'-colbox']['Url'] = card_description[name_fct][2][i][1]
# Afficher le texte de la carte active
if name_chap != "general" and scene.objects['Doc_chap-'+name_chap]['page_fct'] !="":
name_fct = scene.objects['Doc_chap-'+name_chap]['page_fct']
scene.objects['Doc_title']['Text'] = card_description[name_fct][0]
scene.objects['Doc_title'].setVisible(True, False)
text_show(name_fct)
else:
scene.objects['Doc_title']['Text'] = " "
scene.objects['Doc_title'].setVisible(False,True)
text_hide()
##
# Cacher le texte
##
def text_hide(card=None):
if card is None:
for card in card_description:
for i in range (13):
scene.objects['Doc_text-l'+str(i+1)+'-'+str(card)].setVisible(False, False)
else:
for i in range (13):
scene.objects['Doc_text-l'+str(i+1)+'-'+card].setVisible(False, False)
##
# Afficher le texte
##
def text_show(card=None):
if card is None:
for card in card_description:
for i in range (13):
scene.objects['Doc_text-l'+str(i+1)+'-'+str(card)].setVisible(True, False)
else:
for i in range (13):
scene.objects['Doc_text-l'+str(i+1)+'-'+card].setVisible(True, False)
##
# Préchargement des textes
##
def text_load():
for i in range (13):
scene.objects['Doc_text-l'+str(i+1)+'-ref']['Text'] = ""
# Création des objets 3D
for card in card_description:
lines = card_description[card][1].split("\n")
for i in range (13):
doc_text= scene.addObject('Doc_text-l'+str(i+1), None, 0.00, True)
doc_text.setParent(scene.objects['Doc'])
doc_text.name = 'Doc_text-l'+str(i+1)+'-'+str(card)
doc_text.worldPosition.x = scene.objects['Doc_text-l'+str(i+1)+'-ref'].worldPosition.x
doc_text.worldPosition.y = scene.objects['Doc_text-l'+str(i+1)+'-ref'].worldPosition.y
doc_text.worldPosition.z = scene.objects['Doc_text-l'+str(i+1)+'-ref'].worldPosition.z
doc_text.setVisible(False, False)
if i >= len(lines):
scene.objects['Doc_text-l'+str(i+1)+'-'+str(card)]['Text']=""
else:
if len(lines[i]) ==0:
scene.objects['Doc_text-l'+str(i+1)+'-'+str(card)]['Text']=""
else:
scene.objects['Doc_text-l'+str(i+1)+'-'+str(card)]['Text']=lines[i]
##
# Afficher les details de la fonction à partir d'une carte
##
def card (cont):
if cont.sensors['Click'].status == JUST_ACTIVATED and cont.sensors['MO'].positive :
obj = cont.owner
name_chap = scene.objects['Doc']['page_chap']
name_fct= obj.name[:-7]
scene.objects['Doc_title']['Text'] = " "
# Enlever l'ancienne carte
if scene.objects['Doc_chap-'+name_chap]['page_fct'] !="":
text_hide(scene.objects['Doc_chap-'+name_chap]['page_fct'])
scene.objects[scene.objects['Doc_chap-'+name_chap]['page_fct']].color = color_doc_fct
scene.objects[scene.objects['Doc_chap-'+name_chap]['page_fct']+'-text'].color = color_doc_fct
scene.objects[scene.objects['Doc_chap-'+name_chap]['page_fct']+'-icon'].color = color_doc_fct
# Afficher le texte de la carte
scene.objects['Doc_chap-'+name_chap]['page_fct'] = name_fct
scene.objects[name_fct].color = color_doc_activate
scene.objects[name_fct+'-icon'].color = color_doc_activate
scene.objects[name_fct+'-text'].color = color_doc_activate
scene.objects['Doc_title']['Text'] = card_description[name_fct][0]
scene.objects['Doc_title'].setVisible(True, False)
text_show(name_fct)
# URL
if name_chap == "system" or name_chap == "python":
name_fct = scene.objects['Doc_chap-'+name_chap]['page_fct']
scene.objects['Doc_chap-'+name_chap+'-url_title'].setVisible(False,True)
for i in range(3):
scene.objects['Doc_chap-'+name_chap+'-url'+str(i)].setVisible(False,True)
scene.objects['Doc_chap-'+name_chap+'-url'+str(i)+'-colbox'].suspendPhysics()
if name_fct !="":
if len(card_description[name_fct][2])>0:
scene.objects['Doc_chap-'+name_chap+'-url_title'].setVisible(True,True)
for i in range(len(card_description[name_fct][2])):
scene.objects['Doc_chap-'+name_chap+'-url'+str(i)]['Text'] = card_description[name_fct][2][i][0]
scene.objects['Doc_chap-'+name_chap+'-url'+str(i)].setVisible(True,True)
scene.objects['Doc_chap-'+name_chap+'-url'+str(i)+'-colbox'].restorePhysics()
scene.objects['Doc_chap-'+name_chap+'-url'+str(i)+'-colbox']['Url'] = card_description[name_fct][2][i][1]
##
# Aller à la page internet
##
def link (cont):
if cont.sensors['Click'].status == JUST_ACTIVATED and cont.sensors['MO'].positive :
webbrowser.open(cont.owner['Url'])