Last modified: 2019-03-19
1. Indentation
2. Importing modules
3. Methods
4. Type of values
5. Mutable and immutable object
6. Classes, Constants, and Auxiliary Functions
6.1 Classes
6.2 Constants
6.3 General purpose auxiliary functions
6.4 Deletion of class instances
7. Text Editor
8. Languages and encodings
1. Indentation
In Python language, the indentation level, i.e. blank space at the beginning of each line, is significant. Indentation by four spaces for each level is recommended insted of tabs or mixed. Read also Python document, "PEP 8 -- Style Guide for Python Code".
for i in range( 5 ): print( "i=", i )
This code outputs 5 lines to the console window.
2. Importing modules
At least you must import the ptsxpy module at the beginning of each script to use features of the plugin. At the same time, you may specify an alias (i.e. another name) to the module.
import ptsxpy as p cb1 = p.CreateCube( 2, 1., 1., 1. ) p.SceneAddObject( cb1, e_tsxFALSE ) p.SceneDraw()
In the sample script above, "p" is the alias of the module ptsxpy. If you don't specify any alias, you must describe full name at the point of use:
import ptsxpy # this is not recommended cb1 = ptsxpy.CreateCube( 2, 1., 1., 1. ) # this is not recommended ptsxpy.SceneAddObject( cb1, e_tsxFALSE ) # this is not recommended ptsxpy.SceneDraw() # this is not recommended
This is not recommended because it worsens the readability.
You can also import Python modules. In many cases, you may need "import sys" and "import math".
3. Methods
cb1 = p.CreateCube( 2, 1., 1., 1. )
The dot next of the alias "p" refers a member of it, and "CreareCube" is the name of a method. The parentheses following the method name means "call the method with some parameters". The code creates a cube with dimension 1.0 x 1.0 x 1.0 and each edge is divided in two (i.e each face is divided in four squares) .
4. Type of values
Please note that any value has its type. In the code above, the "2" without any dot is an integer, and "1." is short for a float value "1.0". The type (integer, float, ...) of each method are defined by ptsxpy (and tsxAPI functions called by ptsxpy).
Is 5/2 integer? or float? It's the matter of Python language. Please read Python official document and make sure it in your code. There are also python functions that convert a type to another type like; int(), float, str(), etc.
5. Mutable and immutable object
Please learn about tuple, list, and dict of Python language. Each of List and dict is only mutable object. Methods can change only the value of mutable arguments.
cb1 = p.CreateCube( 1, 1., 1., 1. )
p.SceneAddObject( cb1, false )
cb2 = [ 0 ] # this is a list to get a value from the method below
ret1 = p.GNodeCopy( cb1, cb2 ) # this changes the 1st element of cb2
v1 = Vec3f( 2., 2., 0. )
p.GNodeSetLocation( cb2[ 0 ], v1.p )
p.SceneAddObject( cb2[ 0 ], false )
The GNodeCopy() is one of methods that changes a argument. In the code above, cb1 is the address of a cube object. The GNodeCopy() clones it (i.e. makes secondary cube object) in the scene and returns its address to NOT the 2nd parameter, cb2, BUT the 1st element of the list passed as the 2nd parameter, cb2[ 0 ]. Why can we describe as following code?
cb2 = 0 # integer variable is immutable
ret1 = p.GNodeCopy( cb1, cb2 ) # the method fails
or simply why can we omit initialization of cb2 like cb1?
ret1 = p.GNodeCopy( cb1, cb2 ) # the method fails
The reason is that the code "cb2 = 0" initializes the cb2 as an integer, and integes are immutable objects. Again, each method (function) can change only immutable parameters in the Python language.
Note (Mar 19 2019): Changed the specication of p.GNodeCopy() so that it receives 32 bit address as the second parameter as with the original ptsxGNodeCopy(), and deleted lines above.
Don't confuse the Python objects (e.g. integer, tuple, list), C/C++ resouces (e.g. a memory area), and tS resource (e.g. cube object). Methods (and tsxAPI functions called by them) can change memory area pointed by a parameter of the method and can change location of a cube specified by a paramater of the method. What methods cannot change are Python immutable objects specified as parameters of the method.
About return objects: Methods return various objects like; integer, float, pointer, tuple, class instance, etc. You can use a 32 bit unsigned value as a pointer.
6. Classes, Constants, and Auxiliary Functions
Some classes and constants are predefined in a text module, ptsxpydef1.py, that is imported automatically. You can use them without importing the module and without describing the module name at the point of use.
Some general purpose auxiliary functions are predefined in a module, ptsxgp to implement C/C++ functions used by classes in ptsxpydef1.py. You may explicitly import the module and may use the functions if needed.
6.1 Classes
v1 = Vec3f( 1., 2., 3. ) p.GNodeSetLocation( cb1, v1.p )
In this code, the "Vec3f" is a class. It takes 3 float values as its parameters and returns an instance of the class in which its members x, y and z are assigned to the given value; 1.0, 2.0, and 3.0. The instance is assigned to the lefthand of the "=". The Vec3f class (and the instance) has another member, p, as an address that points an allocated memory area. In the case of Vec3f, byte length of the area is 12, and the first 4 byte is the storage for the float value, x, the second 4 bytes is for y, and last 4 bytes for z. (In addition, x86 architecture is Little Endian where the most significant byte (MSBy) is on the largest address in the 4 bytes)
Don't confuse the ".p" (referring a pointer member, p) with "p." (alias of ptsxpy explicitly defined in your scripts).
About the detail of each class, please read the ptsxpydef1.py directly. It is a plain text file.
6.2 Constants
Constants are needed for some methods to specify modes, boolean values, etc. About the detail of each constant, please read the ptsxpydef1.py directly. It is a plain text file.
6.3 General purpose auxiliary functions
General purpose auxiliary functions implements C/C++ functions used by classes in ptsxpydef1.py. You may import the module and may use the functions if needed. For example;
import ptsxgp print( ptsxgp.sizeof_struct_CtsxFaceVx() )
This code displays the byte length of a C/C++ struct defined in tsxAPI functions. (The value is differ between tS versions)
6.4 Deletion of class instances
Each class defined in ptsxpydef1.py has a destructor "__del__" in it and frees the allocated memory in the trueSpace layer by its constructor "__init__". You don't have to explicitly call destructors at the end of your script because they are automatically called. But be careful not to use already freed memory area like below:
##### Bad Example #####
wk = IntArray( 100 ) # Allocate an integer array and get a class object for it
p1 = wk.p # Get the pointer from the class object
wk = IntArray( 100 ) # Allocate another integer array and get a class object for it
p2 = wk.p # Get the pointer from the class object
# read/write the memory area pointed by p1 and p2 here.
IntArray is a class defined in ptsxdef1.py. In this example, class objects are assigned to a single variable, wk, twice. At the second assignment to wk, the destructor of the first class object is called and the allocated memory area is freed because the first wk is abandoned. As a result, p1 points an unallocated memory area and using (loading from or storing to)it causes an error or unexpected results. Following code does not use wk but also has the same problem.
##### Bad Example #####
p1 = IntArray( 100 ).p # Allocate an integer array and get pointer from a class object for it
p2 = IntArray( 100 ).p # Repeat that for p2
# read/write the memory area pointed by p1 and p2 here.
In this example, both class instance are not assignd to any variable. As a result, both p1 and p2 point unallocated areas, and using them causes an error or unexpected results.
We should do:
wk1 = IntArray( 100 ) p1 = wk1.p wk2 = IntArray( 100 ) p2 = wk2.p # read/write the memory area pointed by p1 and p2 here.
In above case, both wk1 and wk2 remain till the end of the script or till they are assigned again, and both p1 and p2 point valid memory area. We can assign wk1 and/or wk2 again without explicit deletion if we don't use any more:
wk1 = IntArray( 100 ) p1 = wk1.p wk2 = IntArray( 100 ) p2 = wk2.p # read/write the memory area pointed by p1 and p2 here. wk1 = IntArray( 100 ) # This is OK if we don't use above p1 any more p1 = wk1.p
Another way is to write the script without using classes that allocates memory in the trueSpace layer:
p1 = ptsxgp.alloc_int( 100 ) p2 = ptsxgp.alloc_int( 100 ) # read/write the memory area pointed by p1 and p2 here. p.Free( p1 ) p.Free( p2 )
In this case, each of p1 and p2 is not a class object but an unsigned integer that holds a 32 bit addresse for the allocated memory area. We must explicitly free the memory area allocated by ptsxgp.alloc_xxxx() functions.
7. Text Editor
You can use any text editor you like. It's more convenient to have syntax-highlighting function.
This is an example of Vim editor. You can wrote a following short text file with name like "syn1.sy" and apply it using ":so" command of vim to highlight p.xxxxx and ptsxhp.xxxxx.
sy match key1 "\<p\>\.[a-zA-Z0-9_]*" sy match key2 "ptsxgp\.[a-zA-Z0-9_]*" hi key1 guifg=#cc6600 gui=bold hi key2 guifg=#993300 gui=bold
(Note: This is not a Python code.)
8. Languages and encodings
You may want to use non-English languages in comments and strings displayed using print(). As long as you follow some rules, you may be able to do that. (Please note that the author cannot test for all circumstances.)
Default str type is Unicode in Python 3, and ascii in Python 2. If you use ptsxpy for Python 2, you must specify the encoding for the language in your script;
# coding=cp932 # 日本語のコメント (comment in Japanese) print( "こんにちは" )
The "coding=xxxxx" in the first line allows you to use your language in the script for Python 2. Executing your Python 2 script with your non-English language without the "coding=" line will cause an error. You need not to write the line for Python 3.
However, the plugin does not support Unicode or utf-8 completely.
print( "你好 안녕하세요 Сайн байна уу?" ) print( "नमस्ते ጤና ይስጥልኝ שלום გამარჯობათ السلام عليكم வணக்கம்" ) print( "ສະບາຍດີ สวัสดีครับ Xin chào ԲարեՎ こんにちは" )
Using multilanguage code displays some garbling letters to the console.
That may be fixed in the future version, but the author has no clear idea.