#author("2021-12-05T13:24:18+09:00","default:Real2Virtual202111","Real2Virtual202111")
#author("2021-12-06T13:19:16+09:00","default:Real2Virtual202111","Real2Virtual202111")
[[Real2Virtual202111]]

* real2virtual_ex02.py [#h05e60ed]
- このライブラリを使わせていただいています。感謝します。
-- https://sites.google.com/site/3dprogramminginpython/


#code(Python){{
import math
from tkinter import *
import tkinter.font as tkFont
import matrix
import copy
import threading
import re

import socket
import time
import readchar
from Cube import Cube
        
class Space:
    ''' Coordiante-system: Right-handed, Matrices are column-major ones '''
    
    WIDTH = 1280.0
    HEIGHT = 960.0
    SPEED = 0.05
    EPSILON = 1.0e-8
    ZERO = EPSILON
    
    def __init__(self):
        print("start Space.__init__")
        self.root = Tk()
        self.root.resizable(False, False)
        self.root.title('3D')
        #self.chat_client=chat_client
        left = (self.root.winfo_screenwidth() - Space.WIDTH) / 2
        top = (self.root.winfo_screenheight() - Space.HEIGHT) / 2
        self.root.geometry('%dx%d+%d+%d' % (Space.WIDTH, Space.HEIGHT, left, top))
        self.graph = Canvas(self.root, width=Space.WIDTH, height=Space.HEIGHT, background='black')
        self.graph.pack()
        
        self.walls = [matrix.Vector3D(7.0, 0.0, 0.0), matrix.Vector3D(-7.0, 0.0, 0.0), matrix.Vector3D(0.0, 7.0, 0.0), matrix.Vector3D(0.0, -7.0, 0.0), matrix.Vector3D(0.0, 0.0, 7.0), matrix.Vector3D(0.0, 0.0, -7.0)]
        self.wallsnormals = [matrix.Vector3D(-1.0, 0.0, 0.0), matrix.Vector3D(1.0, 0.0, 0.0), matrix.Vector3D(0.0, -1.0, 0.0), matrix.Vector3D(0.0, 1.0, 0.0), matrix.Vector3D(0.0, 0.0, -1.0), matrix.Vector3D(0.0, 0.0, 1.0)]
        
#################
#		self.cubenormals = []
#		for i in range(len(self.cubefaces)):
#			poly = []
#			for j in range(len(self.cubefaces[i])):
#				poly.append(self.cube[self.cubefaces[i][j]])

#			self.cubenormals.append(self.calcNormalVec(poly))
#################
        self.ang = [0.0, 0.0, 0.0] # phi(x), theta(y), psi(z) of the camera
        self.trans = [0.0, 0.0, 2.0] # translation (x, y, z) of the camera

	#The matrices (Scale, Shear, Rotate, Translate) apply to the View/Camera

	#The Scale Matrix
        self.Scale = matrix.Matrix(4, 4)
        Scalex = 1.0
        Scaley = 1.0
        Scalez = 1.0
        self.Scale[(0,0)] = Scalex
        self.Scale[(1,1)] = Scaley
        self.Scale[(2,2)] = Scalez
        
        #The Shear Matrix
        self.Shearxy = matrix.Matrix(4, 4)
        self.Shearxy[(0,2)] = 0.0
        self.Shearxy[(1,2)] = 0.0
        self.Shearxz = matrix.Matrix(4, 4)
        self.Shearxz[(0,1)] = 0.0
        self.Shearxz[(2,1)] = 0.0
        self.Shearyz = matrix.Matrix(4, 4)
        self.Shearyz[(1,0)] = 0.0
        self.Shearyz[(2,0)] = 0.0
        self.Shear = self.Shearxy*self.Shearxz*self.Shearyz
        
        #The Rotation Matrices
        self.Rotx = matrix.Matrix(4,4)
        self.Roty = matrix.Matrix(4,4)
        self.Rotz = matrix.Matrix(4,4)
        #The Translation Matrix (will contain xoffset, yoffset, zoffset)
        self.Tr = matrix.Matrix(4, 4)	
        self.Tr[(0,3)] = self.trans[0]
        self.Tr[(1,3)] = self.trans[1]
        self.Tr[(2,3)] = self.trans[2]
        
        #The Projection Matrix
        self.Proj = matrix.Matrix(4, 4)	
        #foc controls how much of the screen is viewed
        fov = 60.0 #between 30 and 90 ?
        zfar = 100.0
        znear = 0.1
        S = 1/(math.tan(math.radians(fov/2)))
        A = Space.WIDTH/Space.HEIGHT
        self.Proj[(0,0)] = S/A
        self.Proj[(1,1)] = S
        self.Proj[(2,2)] = (zfar+znear)/(znear-zfar)
        self.Proj[(3,2)] = -1.0
        self.Proj[(2,3)] = 2*(zfar*znear)/(znear-zfar)
#		self.Proj[(3,3)] = 0.0

        #ToScreen Matrix
        self.toSC = matrix.Matrix(4, 4)
        self.toSC[(0,0)] = Space.WIDTH/2
        self.toSC[(1,1)] = -Space.HEIGHT/2
        self.toSC[(0,3)] = Space.WIDTH/2
        self.toSC[(1,3)] = Space.HEIGHT/2
        
#		self.root.bind("<B1-Motion>", self.dragcallback)
#		self.root.bind("<ButtonRelease-1>", self.releasecallback)
        self.root.bind("<Key>", self.keycallback)
#		self.root.bind("<KeyRelease>", self.keyreleasecallback)
        
        self.fnt = tkFont.Font(family='Helvetica', size=12, weight='bold')
        cube1=Cube(self)
        cube1.set_name("s*")
        self.cube1=cube1
        self.polygons_3D=[cube1]
        
        self.update(self.polygons_3D)
        #self.client_start()
        
        #self.mainloop()
    
    def start_3d(self):
        self.root.mainloop()

    def lookUpCube(self,name):
        for i in range(len(self.polygons_3D)):
           cx=self.polygons_3D[i]
           if name==cx.name :
               return cx
        return None

    def update(self,polygons_3D):
        # Main simulation loop.
        self.graph.delete(ALL)
        
        self.Rotx[(1,1)] = math.cos(math.radians(360.0-self.ang[0]))
        self.Rotx[(1,2)] = -math.sin(math.radians(360.0-self.ang[0]))
        self.Rotx[(2,1)] = math.sin(math.radians(360.0-self.ang[0]))
        self.Rotx[(2,2)] = math.cos(math.radians(360.0-self.ang[0]))
        
        self.Roty[(0,0)] = math.cos(math.radians(360.0-self.ang[1]))
        self.Roty[(0,2)] = math.sin(math.radians(360.0-self.ang[1]))
        self.Roty[(2,0)] = -math.sin(math.radians(360.0-self.ang[1]))
        self.Roty[(2,2)] = math.cos(math.radians(360.0-self.ang[1]))
        
        self.Rotz[(0,0)] = math.cos(math.radians(360.0-self.ang[2]))
        self.Rotz[(0,1)] = -math.sin(math.radians(360.0-self.ang[2]))
        self.Rotz[(1,0)] = math.sin(math.radians(360.0-self.ang[2]))
        self.Rotz[(1,1)] = math.cos(math.radians(360.0-self.ang[2]))
        
        #The Rotation matrix
        self.Rot = self.Rotx*self.Roty*self.Rotz
        
        #Translation (just copying)
        self.Tr[(0,3)] = -self.trans[0]
        self.Tr[(1,3)] = -self.trans[1]
        self.Tr[(2,3)] = -self.trans[2]
        
        #The Transformation matrix
        self.Tsf = self.Scale*self.Shear*self.Rot*self.Tr
        
        #Computing the normals in __init__ and only rotating them here is the same.
#		print '+++++++++++++++'
#		for i in range(len(self.cubenormals)):
#			print self.Rot*self.cubenormals[i]
#		print '+++++++++++++++'
        
#		print '************'
        #Cube
        for ic in range(len(polygons_3D)):
            cubex=polygons_3D[ic]
            cubex.update()
            cubefaces=cubex.cubefaces
            cls=cubex.cls
            for i in range(len(cubefaces)):
                poly = [] #transformed polygon
                for j in range(len(cubefaces[0])):
                    cube=cubex.cube
                    v = cube[cubefaces[i][j]]
                    #Scale, Shear, Rotate the vertex around X axis, then around Y axis, and finally around Z axis and Translate.
                    r=self.Tsf*v
                    poly.append(r)
                n=self.calcNormalVec(poly)
                #print n
                if not self.isPolygonFrontFace(poly[0], n): #Backface culling
                    continue
                poly2d = []
                inviewingvolume = False
                for j in range(len(poly)):
                    #put the point from 3D to 2D
                    ps =self.Proj*poly[j]
                    # Puut the screenpoint in the list of transformed vertices
                    p=self.toSC*ps
                    x=int(p.x)
                    y = int(p.y)
                    poly2d.append((x, y))
                    #if only one point is in the screen (x[-1,1], y[-1,1], z[-1,1]) then draw the whole polygon
                    if (-1.0 <= ps.x <= 1.0) and (-1.0 <= ps.y <= 1.0) and (-1.0 <= ps.z <= 1.0):
                        inviewingvolume = True
                    
                    if inviewingvolume:
                        self.graph.create_polygon(*poly2d, fill=cls[i])
                        cfx=cubex.cfaces
                        xface=cfx[i]
                        xface_led=xface[0]
                        for k in range(len(xface_led)): #LED
                            v=xface_led[k]
                            r=self.Tsf*v
                            ps=self.Proj*r
                            p = self.toSC*ps
                            x, y = int(p.x), int(p.y)
                            self.graph.create_rectangle(x, y, x+3, y+3, fill="magenta")
                        v=xface[1] #photo tr
                        r=self.Tsf*v
                        ps=self.Proj*r
                        p=self.toSC*ps
                        x,y=int(p.x), int(p.y)
                        self.graph.create_rectangle(x,y, x+3, y+3, fill="cyan")
#            cfx=cubex.cfaces
#            for i in range(len(cfx)):
#                xface=cfx[i]
#                xface_led=xface[0]
#                for j in range(len(xface_led)):
#                    v=xface_led[j]
#                    r=self.Tsf*v
#                    ps=self.Proj*r
#                    p = self.toSC*ps
#                    x, y = int(p.x), int(p.y)
#                    self.graph.create_rectangle(x, y, x+3, y+3, fill="magenta")
#                v=xface[1]
#                r=self.Tsf*v
#                ps=self.Proj*r
#                p=self.toSC*ps
#                x,y=int(p.x), int(p.y)
#                self.graph.create_rectangle(x,y, x+3, y+3, fill="cyan")
	#Texts (these are in camera-CS)
        txt1 = 'xpos: '+str(self.trans[0])+' ypos: '+str(self.trans[1])+' zpos: '+str(self.trans[2])
        txt2 = 'xrot: '+str(self.ang[0])+' yrot: '+str(self.ang[1])+' zrot: '+str(self.ang[2])
        self.idTxt1 = self.graph.create_text(30,30, text=txt1, fill='white', anchor=SW, font=self.fnt)
        self.idTxt2 = self.graph.create_text(30,60, text=txt2, fill='white', anchor=SW, font=self.fnt)
        vFwd = self.getForwardVec2(self.ang[1])
        txt3 = 'Fwd: '+str(vFwd)
        self.idTxt3 = self.graph.create_text(30,90, text=txt3, fill='white', anchor=SW, font=self.fnt)
        
    def isPolygonFrontFace(self, v, n):#Clockwise?
        '''v is a vertex of the polygon, n is the normal-vector of the polygon.'''
        
        #The camera should be at (0.0, 0.0, 0.0) but that doesn't work well.
        #It seems that the camera is at (0.0, 0.0, 1.0)
        c = matrix.Vector3D(0.0, 0.0, 1.0)
        vv = v-c
        
        r = vv.dot(n)
        return r < 0.0
    
    def calcNormalVec(self, p):
        '''p is an array of vertices of the polygon/face'''
        
        v1 = p[0]-p[1]
        v2 = p[0]-p[3]
        
        v = v1.cross(v2)
        v.normalize()
        
        return v
    
    def getForwardVec1(self): #Where the camera is facing. Inverting a matrix is slow
        m = self.Rot.invert()
        
        f1 = m[(0,2)]
        f2 = m[(1,2)]
        f3 = m[(2,2)]
        
        v = matrix.Vector3D(f1, f2, f3)
        v.normalize()

		#Forward vector is really backward one, so need to be negated
        return -v
    
    def getForwardVec2(self, yrot): #Where the camera is facing.
        f1 = -math.sin(math.radians(yrot))
        f2 = 0.0
        f3 = -math.cos(math.radians(yrot))
        v = matrix.Vector3D(f1, f2, f3)
        
        return v
    
    def isCollisionPlanes(self, campos, camdir):
        num = len(self.walls)
        for i in range(num):
            iscol, dist = self.isCollisionPlane(self.walls[i], self.wallsnormals[i], campos, camdir)
            
            if iscol and dist < 0.1:
                #print( i+1, dist)
                return True
            
        return False
			
    
    def isCollisionPlane(self, p, n, campos, camdir):
        '''instead of pointonplane (p) and normalofplane (n) we could pass a polygon and calculate its normal vector here. campos is the position of the camera and camdir is the forward vector of the camera'''
        
        dist = 0.0
        
        #Dot Product Between Plane Normal And Ray Direction
        dotprod = camdir.dot(n)
        
        #Determine If Ray Parallel To Plane
        if ((dotprod < Space.ZERO) and (dotprod > -Space.ZERO)):
            return False, dist
        
        #Find Distance To Collision Point
        dist = (n.dot(p-campos))/dotprod
        
        #Test If Collision Behind Start
        if (dist < -Space.ZERO):
            return False, dist
        
        return True, dist
    
    def isCollisionCube(self, campos,polygons_3D):
        '''Checks if the camera is inside the cube (this is the bounding-box-technique (bbt) but we have a cube so we do not need to calculate a bb) '''
        for i in range(len(polygons_3D)):
            cube=(polygons_3D[i]).cube
            cubefaces=(polygons_3D[i]).cubefaces
            
            if (campos.z >= cube[cubefaces[0][0]].z and campos.z <= cube[cubefaces[2][0]].z) and (campos.y >= cube[cubefaces[5][0]].y and 
                 campos.y <= cube[cubefaces[4][0]].y) and (campos.x >= cube[cubefaces[3][0]].x and campos.x <= cube[cubefaces[1][0]].x):
                return True
            
        return False
    
    def keycallback(self, event):
#		print event.char
#		print event.keycode
#		print event.keysym
        
        #Foward
        if event.keysym == 'Up':
            vFwd = self.getForwardVec2(self.ang[1])
            
            #Is there a collison?
            pos = matrix.Vector3D(self.trans[0]+vFwd.x*Space.SPEED, self.trans[1], self.trans[2]+vFwd.z*Space.SPEED)
            if self.isCollisionPlanes(pos, vFwd):
                return
            
            if self.isCollisionCube(pos,self.polygons_3D):
                return
            
            self.trans[0] += vFwd.x*Space.SPEED
            self.trans[2] += vFwd.z*Space.SPEED
            
        #Backward
        elif event.keysym == 'Down':
            vFwd = self.getForwardVec2(self.ang[1])
            vBck = -vFwd
            
            #Is there a collison?
            pos = matrix.Vector3D(self.trans[0]-vFwd.x*Space.SPEED, self.trans[1], self.trans[2]-vFwd.z*Space.SPEED)
            if self.isCollisionPlanes(pos, vBck):
                return
            
            if self.isCollisionCube(pos,self.polygons_3D):
                return
            
            self.trans[0] -= vFwd.x*Space.SPEED
            self.trans[2] -= vFwd.z*Space.SPEED
            
        #Turn right
        elif event.keysym == 'Right':
            self.ang[1] -= 1.5
        #Turn left
        elif event.keysym == 'Left':
            self.ang[1] += 1.5
		#Upwards
        elif event.keysym == 'u':
            #Is there a collison?
            pos = matrix.Vector3D(self.trans[0], self.trans[1]+Space.SPEED, self.trans[2])
            vUp = matrix.Vector3D(0.0, 1.0, 0.0)
            if self.isCollisionPlanes(pos, vUp):
                return
            
            if self.isCollisionCube(pos,self.polygons_3D):
                return
            
            self.trans[1] += Space.SPEED
        #Downwards
        elif event.keysym == 'd':
            #Is there a collison?
            pos = matrix.Vector3D(self.trans[0], self.trans[1]-Space.SPEED, self.trans[2])
            vDwn = matrix.Vector3D(0.0, -1.0, 0.0)
            if self.isCollisionPlanes(pos, vDwn):
                return
            
            if self.isCollisionCube(pos,self.polygons_3D):
                return
            
            self.trans[1] -= Space.SPEED
        #Quit
        elif event.keysym == 'Escape':
            self.quit()
            
        if self.ang[1] >= 360.0:
            self.ang[1] -= 360.0
        if self.ang[1] < 0.0:
            self.ang[1] += 360.0
            
        self.update(self.polygons_3D)

    def quit(self):
        self.root.quit()
        
    def client_start(self):
        """ start client """
        print("start client_start")
        handle_thread = threading.Thread(target=self.handler, daemon=True)
        self.parse("send up \"str (this s* f2d1 next s*4 f4d1)\".")
        self.parse("send up \"str (this s*4 f2d1 next s*44 f4d1)\".")
        self.update(self.polygons_3D)
        handle_thread = threading.Thread(target=self.handler, daemon=True)
        handle_thread.start()
    
    def handler(self):
        """ receive commands from terminal """
        while True:
            print("input...")
            line=input()
            self.parse(line)
            self.update(self.polygons_3D)
            
    def clear(self):
        self.polygons_3D=[self.cube1]
        self.update(self.polygons_3D)
            
    def parse(self,line):
        #self.python2fwb(">"+line)
        print(line)
        p=line.find("send up ")
        if(p<0):
            return
        xl=line[(p+len("send up ")):]
        #print("xl="+xl)
        px=parser(xl)
        px.rb()
        if  not (px.key("\"")):
            return
        if not px.key("str "):
            return
        px.rb()
        if not px.key("("):
            return
        px.rb()
        if not px.key("this "):
            return
        px.rb()
        xn=[""]
        if not px.d_name(xn):
            return
        px.rb()
        dn1=xn[0]
        cn=[(0,0)]
        if not px.connect(cn):
            return
        cn1=cn[0]
        px.rb()
        if not px.key("next "):
            return
        px.rb()
        xn=[""]
        if not px.d_name(xn):
            return
        dn2=xn[0]
        px.rb()
        if not px.connect(cn):
            return
        cn2=cn[0]
        px.rb()
        if not px.key(")"):
            return
        px.rb()
        if not px.key("\""):
            return
        px.rb()
        if not px.key("."):
            return
        print("dn1="+dn1)
        cube1=self.lookUpCube(dn1)
        if cube1 == None:
            print("new "+dn1)
            cube1=Cube(self)
            cube1.set_name(dn1)
            self.polygons_3D.append(cube1)
        print("dn2="+dn2)
        cube2=self.lookUpCube(dn2)
        if cube2 == None:
            print("new "+dn2)
            cube2=Cube(self)
            cube2.set_name(dn2)
            self.polygons_3D.append(cube2)
        print(cn1)
        print(cn2)
        if1=cn1[0]
        if2=cn2[0]
        id1=cn1[1]
        id2=cn2[1]
        v2=cube1.get_next_place_position(if1)
        cube2.moveTo(v2.x,v2.y,v2.z)
        cube1.rotate_nextdoor_cube_until_match_the_face(if1, cube2, if2)
        cube1.rotate_nextdoor_cube_until_match_the_direction(if1,cube2,if2,id2)
        self.update(self.polygons_3D)

class parser:
#
# srs.
# ok.
# fid=2. received=ack1 face 4 dir 0 uDir 0.
# this face(2):dir(0)<-> next face(4):dir(0)
# send up "str (this s* f2d0 next s*4 f4d0)".
# fid=2, received=send up "str (this s*4 f2d0 next s*44 f4d0)".
# str (this s*4 f2d0 next s*44 f4d0)
# ok
# fid=2, received=send up "str (this s*44 f2d0 next s*444 f4d0)".
# str (this s*44 f2d0 next s*444 f4d0)".
# ok
#    
    def __init__(self,line):
        self.line=line
        print("parser init "+line)
    def alpha(self,p2a):
        #print("alpha line="+self.line)
        c=self.line[0]
        p2a[0]=c
        if(c.isalpha()):
          self.line=self.line[1:]
          return True
        return False
    def digit(self,p2i):
        #print("digit line="+self.line)
        c=self.line[0]
        if(c.isdigit()):
            p2i[0]=int(c)
            self.line=self.line[1:]
            return True
        return False
    def d_name(self,xn):
        #print("d_name line="+self.line)
        cl=['']
        if not self.alpha(cl):
            return False
        xn[0]=xn[0]+cl[0]
        if not self.key("*"):
            return False
        xn[0]=xn[0]+"*"
        dx=[0]
        while self.digit(dx):
            xn[0]=xn[0]+str(dx[0])
        return True
    
    def connect(self,tx):
        #print("connect line="+self.line)
        if not self.key("f"):
            return False
        fx=[0]
        if not self.digit(fx):
            return False
        if not self.key("d"):
            return False
        dx=[0]
        if not self.digit(dx):
            return False
        tx[0]=(fx[0],dx[0])
        return True
        
    def key(self,key):
        #print("key line="+self.line)
        #print("key="+key)
        tf=self.line.startswith(key)
        print(tf)
        if(self.line.startswith(key)):
            lk=len(key)
            self.line=self.line[lk:]
            return True
        return False
    def rb(self):
        while self.key(' '):
            continue            
      
#
#    +-----------------------------------------------------+
#    |                                             TESLA   |
#    |    +-----------+          +--------------+  DICE    |
#    |    | mbed      |          |m5atom        |          |
#    |    |           |<--UART-->|tcp_server_ex1|          |
#    |    +-----------+          +--------------+          |
#    |                            ^                        |
#    +--------------------------- | -----------------------+
#                                 |
#                                wifi.... SSID YAMA-M5ATOM-EX01
#                                 |       PASS  12345678
#                                 |
#    +--------------------------- | -----------------------+
#    |                            v                PC      |
#    |                      +------------------+           |
#    |                      |Chat_Client       |
#                           |    |             |
#                           |    v             |
#                           |   handler        |
#                           |    |             |
#                           |    v             |
#                           |   parser         |
#                           |    |             |
#                           +----|-------------+
#                                |
#                                | put
#                                v
#                           +------------------+
#                           |ex04.py           |
#                           |    |             |
#                           |    v             |
#                           |  handler         |
#                           +------------------+
#                          
# coding: utf-8
#from PIL import Image, ImageFont, ImageDraw
#import time
#import sys
#import requests
#import os
#import socket
#import threading
#from collections import deque
#import subprocess
#import copy

class Chat_Client:
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    HOST = '192.168.4.1'
    PORT = 23
    def __init__(self):
        print("start Chat_Client.__init__")

    def set_space(self,space):
        self.space=space
    def start_input_thread(self):
      handle_thread2 = threading.Thread(target=self.start_input, args=(self.sock,), daemon=True)
      handle_thread2.start()
        
    def start_input(self,sock):
        print("sock=")
        print(sock)
        print("input...")
        line=""
        cx=bytearray(8)
        while True:
          try:
            line=input()
            if line=="clear.":
                self.send_message("srr.")
                self.space.clear()
            else:
                for i in range(len(line)):
                    c=line[i]
                    #c=readchar.readkey()
                    #print(c)
                    #cx[0]=c.encode('utf-8')
                    #cx[1]=0x00
                    sock.sendall(c.encode('ascii',errors='replace'))
                    time.sleep(0.01)
          except:
            print("error")

    def send_message_nl(self,py2x_message):
      msg=py2x_message+'\n'
      self.sock.sendall(msg.encode('ascii',errors='replace'))
      
    def send_message(self,py2x_message):
      msg=py2x_message
      self.sock.sendall(msg.encode('ascii',errors='replace'))

    def parse(self,line):
      vf.parse(line)
      
    def client_start(self):
      """start client"""
      self.sock.connect((self.HOST, self.PORT))
      handle_thread = threading.Thread(target=self.handler, args=(self.sock,), daemon=True)
      handle_thread.start()
 
    def handler(self,sock):
      """receive the message from the server and print it."""
 
      while True:
        lx=""
        while True:
          data = sock.recv(1024)
          dl=len(data)
          try:
             rd=data.decode('utf-8')
          except:
             rd='?'*dl
          for i in range(dl):
              c=rd[i]
              lx=lx+c
              if c=="." or c=="\n":
                  print("[receive] "+lx)
                  self.parseLines(lx)
                  lx=""
              #print(c)
          if c=="." or c=="\n":
              break
        print("[receive]-"+lx)
        
        if self.space!=None:
           print("parse-"+lx)
           self.parseLines(lx)
           
    def parseLines(self,ls):
        lsx=ls.splitlines()
        for i in range(len(lsx)):
            self.space.parse(lsx[i])

if __name__ == "__main__":
    client=Chat_Client()
    space=Space()
    client.set_space(space)
    client.client_start()
    client.start_input_thread()
    space.start_3d()


}}
----
#counter



トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS