mirror of
https://forge.apps.education.fr/blender-edutech/ropy.git
synced 2024-01-27 08:23:20 +01:00
Page Crédits et choix du script
This commit is contained in:
parent
5df7aebc65
commit
fbc1069d4a
28
README.md
28
README.md
@ -64,15 +64,27 @@ Le code source, les fichiers blender et les assets sont hébergés sur le dépô
|
||||
Les bibliothèques suivantes ne sont pas incluses par défaut dans l'environnement UPBGE :
|
||||
- [**Pylint**](https://pylint.pycqa.org) : vérificateur du code Python
|
||||
- [**pySerial**](https://pyserial.readthedocs.io) : communication sur le port série
|
||||
- [**pyFirmata**](https://pyfirmata.readthedocs.io) : protocole Firmata (protocole générique de communication entre un logiciel et un microcontrôleur)
|
||||
- [**wxPython**](https://www.wxpython.org/) : interface graphique utilisateur (GUI, utilisé ici pour Windows)
|
||||
- [**pyQt5**](https://www.riverbankcomputing.com/software/pyqt/) : interface graphique utilisateur (GUI, utilisé ici pour GNU/Linux)
|
||||
|
||||
Il faut donc les installer localement (dans UPBGE), les étapes sont :
|
||||
- **GNU/Linux** : La configuration ici présente est UPBGE installé sur ~ avec Python 3.9 :
|
||||
- Aller dans le répertoire local de Python de UPBGE: $ cd ~/UPBGE-0.30-linux-x86_64/3.0/python/bin
|
||||
- Installer le gestionnaire de paquet pip : $ ./python3.9 -m ensurepip --default-pip
|
||||
- Installer Pylint : $ ./pip install pylint -t ~/UPBGE-0.30-linux-x86_64/3.0/python/lib/python3.9/site-packages
|
||||
- Installer pySerial : $ ./pip install pyserial -t ~/UPBGE-0.30-linux-x86_64/3.0/python/lib/python3.9/site-packages
|
||||
|
||||
- **Windows** : La configuration ici présente est UPBGE installé sur le bureau utilisateur (prenom.nom) avec la distribution Anaconda installée :
|
||||
- Avec Anaconda Navigator ouvrir un terminal Powershell
|
||||
- Installer Pylint : pip install pylint -t C:\Users\prenom.nom\Desktop\UPBGE-0.30-windows-x86_64\3.0\python\lib\site-packages
|
||||
- Installer pySerial : pip install pyserial -t C:\Users\prenom.nom\Desktop\UPBGE-0.30-windows-x86_64\3.0\python\lib\site-packages
|
||||
- Télécharger le script ['get-pip.py'](https://bootstrap.pypa.io/get-pip.py) pour installer le gestionnaire de paquet [**Pip**](https://pip.pypa.io)
|
||||
- Installer le gestionnaire de paquet Pip : $ ./python3.9 get-pip.py
|
||||
- Installer Pylint : $ ./pip install pylint
|
||||
- Installer pySerial : $ ./pip install pyserial
|
||||
- Installer pyFirmata : $ ./pip install pyfirmata
|
||||
- Installer PyQt5 : $ ./pip install PyQt5
|
||||
|
||||
- **Windows** : La configuration ici présente est UPBGE installé sur le bureau utilisateur (prenom.nom) :
|
||||
- Ouvrir un terminal Powershell (éventuellement en passant par Anaconda Navigator)
|
||||
- Aller dans le répertoire local de Python de UPBGE: cd C:\Users\prenom.nom\Desktop\UPBGE-0.30-windows-x86_64\3.0\python\bin
|
||||
- Télécharger le script ['get-pip.py'](https://bootstrap.pypa.io/get-pip.py) pour installer le gestionnaire de paquet [**Pip**](https://pip.pypa.io)
|
||||
- Installer le gestionnaire de paquet Pip : python.exe get-pip.py
|
||||
- Aller dans le répertoire 'Scripts' : cd C:\Users\prenom.nom\Desktop\UPBGE-0.30-windows-x86_64\3.0\python\Scripts
|
||||
- Installer Pylint : pip.exe install pylint
|
||||
- Installer pySerial : pip.exe install pyserial
|
||||
- Installer pyFirmata : pip.exe install pyfirmata
|
||||
- Installer wxPython : pip.exe install wxpython
|
||||
|
BIN
ropy-31.blend
BIN
ropy-31.blend
Binary file not shown.
BIN
ropy-32.blend
Normal file
BIN
ropy-32.blend
Normal file
Binary file not shown.
57
rp.py
57
rp.py
@ -9,6 +9,7 @@ import sys
|
||||
import os
|
||||
import webbrowser # Lien internet
|
||||
import threading # Multithreading
|
||||
import subprocess # Multiprocessus
|
||||
import xml.etree.ElementTree as ET # Creating/parsing XML file
|
||||
import runpy # Exécution de script Python légère (sans import)
|
||||
from pylint import epylint as lint # Mesure de la qualité d'un code Python
|
||||
@ -39,6 +40,7 @@ import rp_about # About
|
||||
# Debug flag
|
||||
scene = bge.logic.getCurrentScene()
|
||||
scene.objects['Commands']['debug_fps']=False
|
||||
scene.objects['Commands']['script'] = os.path.join(os.getcwd(), "rp_cmd.py") # Script par défaut
|
||||
|
||||
# Memory
|
||||
sys.setrecursionlimit(10**5) # Limite sur la récursivité (valeur par défaut : 1000) -> segfault de Blender
|
||||
@ -210,17 +212,25 @@ def terrain_init (cont):
|
||||
# cam2.setViewport(int(width / 2), 0, width, height)
|
||||
|
||||
##
|
||||
# Mise en route et pause du cycle
|
||||
# Validation du code Python
|
||||
##
|
||||
|
||||
def python_validation():
|
||||
(pylint_stdout, pylint_stderr) = lint.py_run('rp_cmd.py --disable=C --disable=W --disable=R', return_std=True)
|
||||
def python_validation(file):
|
||||
(pylint_stdout, pylint_stderr) = lint.py_run(file+' --disable=C --disable=W --disable=R', return_std=True)
|
||||
stdout = pylint_stdout.read()
|
||||
stderr = pylint_stderr.read()
|
||||
if " error (" in stdout: # Présence d'erreur
|
||||
print(stdout)
|
||||
|
||||
# UI : information
|
||||
scene.objects['Cmd-text']['modal']= True
|
||||
scene.objects['Cmd-text']['Text']= "Erreur dans le script ... "
|
||||
scene.objects['Cmd-text'].setVisible(True,False)
|
||||
print(stdout) # Affichage console
|
||||
return False
|
||||
else:
|
||||
scene.objects['Cmd-text']['modal']= False
|
||||
scene.objects['Cmd-text']['Text']= ""
|
||||
scene.objects['Cmd-text'].setVisible(False,False)
|
||||
return True
|
||||
|
||||
def terrain_run ():
|
||||
@ -251,14 +261,13 @@ def terrain_run ():
|
||||
time.sleep(0.125)
|
||||
|
||||
# Nombre de ligne du script Python
|
||||
# print (os.getcwd())
|
||||
file = open('rp_cmd.py', 'r')
|
||||
file = open(scene.objects['Commands']['script'], 'r')
|
||||
file_txt = file.read()
|
||||
scene.objects['Points']['nbligne'] = len(file_txt.split("\n"))-28 # 28 lignes utilisées de base
|
||||
file.close()
|
||||
scene.objects['Rover']['stop'] = False
|
||||
if python_validation():
|
||||
runpy.run_module('rp_cmd', run_name='start') # Execution du script utilisateur
|
||||
if python_validation(scene.objects['Commands']['script']):
|
||||
runpy.run_path(scene.objects['Commands']['script'], run_name='start') # Execution du script utilisateur
|
||||
|
||||
# Arrêt de la pause
|
||||
else:
|
||||
@ -280,8 +289,8 @@ def terrain_stop ():
|
||||
def terrain_end (cont):
|
||||
if cont.sensors['End cycle'].positive:
|
||||
scene.objects['Terrain']['run']=False
|
||||
if python_validation():
|
||||
runpy.run_module('rp_cmd', run_name='stop') # Fin du script utilisateur
|
||||
if python_validation(scene.objects['Commands']['script']):
|
||||
runpy.run_path(scene.objects['Commands']['script'], run_name='stop') # Fin du script utilisateur
|
||||
|
||||
# Commandes
|
||||
scene.objects['Pause'].setVisible(False,False)
|
||||
@ -444,6 +453,7 @@ def cmd_init(cont):
|
||||
scene.objects['Points-Map-text'].setVisible(True,False)
|
||||
scene.objects['Points-Twins'].setVisible(False,True)
|
||||
scene.objects['Points-Twins-text'].setVisible(False,False)
|
||||
scene.objects['Script-text']['Text']=scene.objects['Commands']['script']
|
||||
# scene.objects['Info-1-text'].setVisible(False,False)
|
||||
# scene.objects['Info-2-text'].setVisible(False,False)
|
||||
|
||||
@ -536,6 +546,7 @@ def cmd_hl(cont):
|
||||
"Task-cmd":"Liste des tâches",
|
||||
"Task_close-cmd":"Fermer la liste des tâches",
|
||||
"ResetView": "Reset de la vue (Touche Début)",
|
||||
"File": "Changer le fichier de commandes",
|
||||
"About-cmd": "A propos",
|
||||
"Speed_down": "Moins vite (-)",
|
||||
"Speed_up": "Plus vite (+)",
|
||||
@ -547,6 +558,7 @@ def cmd_hl(cont):
|
||||
# "Aim":"Show aim",
|
||||
# "Doc-cmd":"Documentation",
|
||||
# "ResetView": "Reset view (Home key)",
|
||||
# "File": "Change the commands file",
|
||||
# "About-cmd": "About",
|
||||
# "Speed_down": "Speed down (-)",
|
||||
# "Speed_up": "Speed up (+)",
|
||||
@ -641,6 +653,9 @@ def cmd_click (cont):
|
||||
if obj.name=="Doc-cmd-colbox":
|
||||
sound_play (snd_open)
|
||||
tablet_open ()
|
||||
if obj.name=="File":
|
||||
sound_play (snd_open)
|
||||
file_open ()
|
||||
if obj.name=="About-cmd":
|
||||
sound_play (snd_open)
|
||||
about_open ()
|
||||
@ -1337,6 +1352,28 @@ def store_close_click(cont):
|
||||
sound_play (snd_close)
|
||||
store_close()
|
||||
|
||||
###############################################################################
|
||||
# Fichier
|
||||
###############################################################################
|
||||
|
||||
def file_open():
|
||||
|
||||
# Terminer le processus file précédent
|
||||
if ('file_proc' in scene.objects['Commands']):
|
||||
if scene.objects['Commands']['file_proc'].poll()==None:
|
||||
scene.objects['Commands']['file_proc'].terminate()
|
||||
|
||||
# Démarrer le processus file
|
||||
if sys.platform=="linux": # wxPython ne s'installe pas bien sur GNU/linux -> Qt5
|
||||
scene.objects['Commands']['file_proc'] = subprocess.Popen([sys.executable, os.path.join(os.getcwd(), "rp_file_qt.py")], stdout=subprocess.PIPE, encoding = 'utf8')
|
||||
else: # Qt5 ne s'installe pas bien sur Windows -> wxPython
|
||||
scene.objects['Commands']['file_proc'] = subprocess.Popen([sys.executable, os.path.join(os.getcwd(), "rp_file_wx.py")], stdout=subprocess.PIPE, encoding = 'utf8')
|
||||
|
||||
stout = scene.objects['Commands']['file_proc'].communicate()
|
||||
if stout[0][:-1] != 'None':
|
||||
scene.objects['Commands']['script'] = stout[0][:-1]
|
||||
scene.objects['Script-text']['Text']=scene.objects['Commands']['script']
|
||||
|
||||
###############################################################################
|
||||
# About
|
||||
###############################################################################
|
||||
|
97
rp_about.py
97
rp_about.py
@ -23,24 +23,52 @@ 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"],
|
||||
'wxWidgets' : ["wxWidgets","Bibliothèque GUI","https://www.wxwidgets.org", "wxWindows Library Licence"],
|
||||
'wxPython' : ["wxPython","API Python de wxWidgets","https://www.wxpython.org", "GNU GPL"],
|
||||
'Qt5' : ["Qt5","Bibliothèque GUI","https://www.qt.io", "GNU LGPL-3"],
|
||||
'PyQt' : ["PyQt","API Python de Qt5","https://www.riverbankcomputing.com/software/pyqt","GNU GPL"],
|
||||
'Polygonrunway' : ["Roman Klčo","Modèles 3D","https://www.patreon.com/polygonrunway/",""],
|
||||
'KayKit' : ["Kay Lousberg","Modèles 3D","www.kaylousberg.com","CC0 1.0"],
|
||||
'Kenney' : ["Kenney","Modèles 3D, icônes et sons","https://www.kenney.nl","CC0 1.0"],
|
||||
'Game-icons.net' : ["Game-icons.net","Icônes","https://game-icons.net","CC BY 3.0"],
|
||||
'Mainframe' : ["Mainframe","Police de caractères","https://www.dafont.com/fr/mainframe.font", "CC BY 4.0"]}
|
||||
|
||||
###############################################################################
|
||||
# Page About
|
||||
###############################################################################
|
||||
|
||||
##
|
||||
# Ouverture
|
||||
##
|
||||
|
||||
def open():
|
||||
scene.objects['About_close'].color= color_link
|
||||
scene.objects['About_credits'].color= color_link
|
||||
|
||||
# Configuration
|
||||
scene.objects['About_screen-up'].color= color_link
|
||||
scene.objects['About_screen-down'].color= color_link
|
||||
scene.objects['About_screen']['Text']= "SCREEN SIZE : "+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
|
||||
# scene.objects['About_screen']['Text']= "SCREEN SIZE : "+str(bge.render.getWindowWidth()) +" x "+str(bge.render.getWindowHeight())
|
||||
|
||||
# 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_link-kay'].color= color_link
|
||||
scene.objects['About_link-kenney'].color= color_link
|
||||
scene.objects['About_link-polygonrunway'].color= color_link
|
||||
scene.objects['About_link-icons'].color= color_link
|
||||
|
||||
|
||||
# Animation
|
||||
scene.objects['About'].setVisible(True,True)
|
||||
scene.objects['About'].worldPosition = [0, 1.53623, -1.8] # old [0, 1.53623, -0.892838]
|
||||
scene.objects['About']['timer'] = 0
|
||||
@ -98,11 +126,7 @@ def link(cont):
|
||||
link={
|
||||
'About_link-git' : 'https://gitlab.com/blender-edutech/ropy',
|
||||
'About_link-gpl' : 'https://www.gnu.org/licenses/gpl-3.0.html',
|
||||
'About_link-upbge' : 'https://www.upbge.org',
|
||||
'About_link-kay' : 'https://www.kaylousberg.com',
|
||||
'About_link-kenney' : 'https://www.kenney.nl',
|
||||
'About_link-polygonrunway' : 'https://www.patreon.com/polygonrunway/',
|
||||
'About_link-icons' : 'https://game-icons.net/'}
|
||||
'About_link-upbge' : 'https://www.upbge.org'}
|
||||
webbrowser.open(link [name])
|
||||
|
||||
def link_hl(cont):
|
||||
@ -116,3 +140,56 @@ def link_hl(cont):
|
||||
obj = cont.owner
|
||||
name=obj.name[:-7]
|
||||
scene.objects[name].color = color_link
|
||||
|
||||
###############################################################################
|
||||
# Page Crédits
|
||||
###############################################################################
|
||||
|
||||
def credits(cont):
|
||||
if cont.sensors['Click'].status == JUST_ACTIVATED and cont.sensors['MO'].positive :
|
||||
|
||||
# Mémorisation de la position des pages avant changement
|
||||
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
|
||||
|
||||
# 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['Credits_close'].color= color_link
|
||||
scene.objects['About'].setVisible(False,True)
|
||||
scene.objects['Credits'].setVisible(True,True)
|
||||
|
||||
# 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])
|
||||
|
23
rp_file_qt.py
Normal file
23
rp_file_qt.py
Normal file
@ -0,0 +1,23 @@
|
||||
import sys
|
||||
from PyQt5 import QtWidgets
|
||||
from PyQt5.QtWidgets import QApplication, QFileDialog
|
||||
|
||||
###############################################################################
|
||||
# twin_file_qt.py
|
||||
# @title: Selecteur de fichier (pyQt5)
|
||||
# @project: Blender-EduTech
|
||||
# @lang: fr
|
||||
# @authors: Philippe Roy <philippe.roy@ac-grenoble.fr>
|
||||
# @copyright: Copyright (C) 2023 Philippe Roy
|
||||
# @license: GNU GPL
|
||||
###############################################################################
|
||||
|
||||
def dialog():
|
||||
file , check = QFileDialog.getOpenFileName(None, "Sélection du fichier de commande", "", "Python Files (*.py)")
|
||||
if check:
|
||||
return file
|
||||
|
||||
app = QApplication(sys.argv)
|
||||
file = dialog()
|
||||
print (file)
|
||||
sys.exit(0)
|
22
rp_file_wx.py
Normal file
22
rp_file_wx.py
Normal file
@ -0,0 +1,22 @@
|
||||
import wx
|
||||
|
||||
###############################################################################
|
||||
# twin_file_wx.py
|
||||
# @title: Selecteur de fichier (wxPython)
|
||||
# @project: Blender-EduTech
|
||||
# @lang: fr
|
||||
# @authors: Philippe Roy <philippe.roy@ac-grenoble.fr>
|
||||
# @copyright: Copyright (C) 2023 Philippe Roy
|
||||
# @license: GNU GPL
|
||||
###############################################################################
|
||||
|
||||
app = wx.App()
|
||||
frame = wx.Frame(None, -1, 'win.py')
|
||||
# frame.SetDimensions(0,0,200,50)
|
||||
|
||||
openFileDialog = wx.FileDialog(frame, "Sélection du fichier de commande", "", "",
|
||||
"Fichier Python (*.py)|*.py", wx.FD_OPEN | wx.FD_FILE_MUST_EXIST)
|
||||
|
||||
openFileDialog.ShowModal()
|
||||
print(openFileDialog.GetPath())
|
||||
openFileDialog.Destroy()
|
Loading…
x
Reference in New Issue
Block a user