interact.py

Created by frablock

Created on June 15, 2023

7.16 KB

Implémentation d’élément d’UI :

  • input pour kandinsky (voir fonction keyboard)

  • affichage popup

  • menu de sélection/menu de sélection par pointeur

  • Des icônes

  • Affichage des images

Ce script est un assemblage d’élément qui me semblent utiles à la création d’interface

Si vous souhaitez gagner de la place, supprimez les commentaires

LICENCE CC4.0 BY SA NC


#Fichier contenant des fonctions utiles
from kandinsky import fill_rect, draw_string, set_pixel, get_pixel
from ion import *
import ion
from time import sleep


#configs
sleeping_time=0.1




def image(im,pal,t=4,px=0,py=0,suppr="",bs=40):
 """
 inspiré par https://my.numworks.com/python/schraf/photov2
 im : image
 pal : palette

 t : taille d'un pixel

 px : placement origine x
 py : placement origine y

 suppr : Couleur à supprimer (image transparente, couleur encodée)

 bs : nombre de pixel par ligne
 """
 r,i=0,0
 while r<len(im):
  s,n=im[r],'';r+=1
  while r<len(im)and'9'>=im[r]>='0':n+=im[r];r+=1
  nb=1 if n==''else int(n);c=pal[ord(s)-65]
  for j in range(nb):
    if str(s)!=str(suppr):fill_rect(px+t*(i%bs),py+t*(i//bs),t,t,(c[0],c[1],c[2]))
    i+=1


def base(number, base, original_base=10):
    """
    Sert à convertir des nombres de différentes bases
    Utile pour la fonction icone
    """
    if base == "bin":
        return bin(int(number, original_base))[2:]
    elif base == "hex":
        return hex(int(number, original_base))[2:]

def icone(icon="happy",x=0,y=0,t=5,col=(0,0,0)):
    """
    x,y position
    t taille
    icone : nom de l'icone, ou icone en format ("base hex",w,h)
    col couleur de l'icone
    """

    pre_icon={"up_arrow":("c4a1",6,3),"down_arrow":("2148c",6,3),"right_arrow":("4454",3,6),"left_arrow":("1511",3,6),
    "settings":("f801b03f747c7d800f0e1b3e626c8cf9b0e1e0037c7cdd901b003e0",15,15),"cross":("1151151",5,5),"check":("8a88",5,4),"menu":("1f07c1f",5,5),
    "happy":("a5022e",5,5),"sad":("a501d1",5,5),"pen":("30007003700f603f00fe03f80fe03f80fe01f806e00f803c006000",15,15),"search":("1e00ff038606061806300c6018c030c0c1c380ff80f3800380038003",15,15),"heart":("66ffff7e3c1800",8,8),
    "image":("7fff80030006020c14187233136c20c0018003fffc0000000",15,15),"folder":("3e087a018060180601ffc00",10,10),"text":("ffe0180679806798067980601807ff",10,12),"python":("3c00420042004200c307f3e80218021840184014c020c3004200420042003c0",16,16),"game":("3eab060ff",7,5)}

    a=pre_icon.get(icon,icon)
    b=base(a[0],"bin",16)
    for i in range(a[1]*a[2]-len(b)):b="0"+b
    for i in range(a[1]*a[2]):
        if int(b[i]):fill_rect(x+i%a[1]*t,y+i//a[1]*t,t,t,col)


def wait_clicks(keys):
    """
    Attends jusqu'à une pression sur le clavier pour lancer une fonction
    keys : {KEY_UP:fonction,KEY_OK:fonction}
    """
    a=1
    while a:
        for k,i in keys.items():
            if keydown(k):
                a=0
                i()


def popup(a,c="white",x=10,y=75,w=300,h=75,f=None):
    """
    a : texte à afficher
    c : couleur de la popup

    x,y : position origine

    w,h : taille et hauteur

    f : fonction associée : (fonction,texte)
    """
    assert f is None or type(f)==list or type(f)==tuple, "(fonction,texte)"
    fill_rect(x,y,w,h,(0,0,0));fill_rect(x+1,y+1,w-2,h-2,c);draw_string(a,x+2,y+2,(0,0,0),c);draw_string('[OK]' if f is None else "[OK] "+str(f[1])+"\n[UP] Annuler",x+2,y+h-20,(0,0,0),c)
    wait_clicks({KEY_OK:lambda:None} if f is None else {KEY_OK:f[0],KEY_UP:lambda:None})
def select(options):
    """
    Menu de sélection à choix multiples
    options : {"Texte affiché":fonction,"autre texte":autre fonction}
    """
    assert len(options)>=2, "manques d'option"
    p=len(options)//2
    for i,(a,b) in enumerate(sorted(options.items())):
        fill_rect(20,40+(i-p)*20,280,20,"white" if i-p!=0 else "black")
        draw_string(str(a),41,40+(i-p)*20,"black" if i-p!=0 else "white","white" if i-p!=0 else "black")
    e=0
    while not keydown(KEY_OK):
        if keydown(KEY_DOWN):
            p=p+1 if 0<=p<len(options) else 0
            e=1
        if keydown(KEY_UP):
            p=p-1 if 0<=p<len(options) else len(options)-1
            e=1
        if e:
            e=0
            for i,(a,b) in enumerate(sorted(options.items())):
                if 2>(i-p)>-2:
                    fill_rect(20,40+(i-p)*20,280,20,"white" if i-p!=0 else "black")
                    draw_string(str(a),41,40+(i-p)*20,"black" if i-p!=0 else "white","white" if i-p!=0 else "black")
                    icone("up_arrow" if i-p<0 else "down_arrow",21,40+(i-p)*25,2)
            sleep(0.5)
    sleep(1)
    return sorted(options.items())[p][1]()


def keyboard(t=""):
    """
    Petite zone d'input simpliste pour kandinsky
    t :  texte par défaut
    """
    text=t
    m_text=chr(124)
    main_mode=13
    rang=len(text)

    letters="abcdefghijklmnopqrstuvwxyz ?!"
    numbers=("exp()","log()","log10()","1j",",","**","sin()","cos()","tan()","pi","sqrt()","**2","7","8","9","(",")","4","5","6","*","/","1","2","3","+","-","0",".")
    shift=("[","]","{","}","_","->","asin()","acos()","atan()","=","<",">","μ","","Ω","()",":)",":(")

    mode={13:letters,14:numbers,12:shift}
    mode_l={12:"shift",13:"alpha",14:"12345"}

    icone("pen",300,180)

    while not keydown(KEY_OK):
        fill_rect(0,200,320,1,(0,0,0))
        fill_rect(0,201,320,30,"white")
        draw_string(m_text,0,202,(0,0,0),"white")
        draw_string(mode_l[main_mode],0,180)


        for key in range(18,49+1):
            if keydown(key):
                try:
                    l=mode[main_mode][key-18 if key<=34 else key-19 if key<=40 else key-20]
                    rang+=len(l)
                    text=text[:rang-1]+l+text[rang-1:]
                except:
                    text+=""
                sleep(sleeping_time)

        for key in (12,13,14):
            if keydown(key):
                main_mode=key
                sleep(sleeping_time)
        
        if keydown(17):
            text=text[:rang-1]+text[rang:]
            rang-=1
            sleep(sleeping_time)

        if keydown(0):
            rang=rang-1 if rang-1>0 else len(text)-1
            sleep(sleeping_time)
        if keydown(3):
            rang=rang+1 if len(text)>rang else 0
            sleep(sleeping_time)

        t1=text[rang-20:rang] if len(text)>30 else text[:rang]
        t2=text[rang:rang+20] if len(text)>30 else text[rang:]
        m_text=t1+chr(124)+t2

    sleep(0.5)
    return text

def pointer_menu(buttons:list,col=(255,0,0)):
    """
    buttons:[{"bouton1":{"co":(x,y,w,h),"f"=fonction,couleur texte, background,"v":visible)}]
    col : couleur du pointeur

    menu de séléction par pointeur
    """
    pointer=[50,50]
    scol=[]

    depl={KEY_UP:(0,-1),KEY_DOWN:(0,+1),KEY_LEFT:(-1,0),KEY_RIGHT:(+1,0)}

    for i in range(16):
                    a=get_pixel(pointer[0]-1+i%4,pointer[1]-1+i//4)
                    scol+=[a]
    while 1:
        fill_rect(pointer[0],pointer[1],2,2,col)
        for k,e in depl.items():
            if keydown(k):
                for n,i in enumerate(scol):
                    set_pixel(pointer[0]-1+n%4,pointer[1]-1+n//4,i)
                pointer[0]+=e[0] if 0<pointer[0]+e[0]<310 else 0
                pointer[1]+=e[1] if 0<pointer[1]+e[1]<210 else 0
                scol=[]
                for i in range(16):
                    a=get_pixel(pointer[0]-1+i%4,pointer[1]-1+i//4)
                    scol+=[a]
        if keydown(KEY_OK):
            for n,b in buttons.items():
                if b["co"][0]<=pointer[0]<=b["co"][0]+b["co"][2] and b["co"][1]<=pointer[1]<=b["co"][1]+b["co"][3]:
                    sleep(0.5)
                    return b["f"]()

During your visit to our site, NumWorks needs to install "cookies" or use other technologies to collect data about you in order to:

With the exception of Cookies essential to the operation of the site, NumWorks leaves you the choice: you can accept Cookies for audience measurement by clicking on the "Accept and continue" button, or refuse these Cookies by clicking on the "Continue without accepting" button or by continuing your browsing. You can update your choice at any time by clicking on the link "Manage my cookies" at the bottom of the page. For more information, please consult our cookies policy.