- script template use new property syntax
- Python could set the axis/hat to a negative index and crash blender (nobody complained)
- Servo control UI had overlapping text
- CValue warning ShowDeprecationWarning("val = ob.attr", "val = ob['attr']"); had false positives because of python using getattr() internally. Only show the wanring now when a CValue is found.
- Py functions that accepted a vector and a GameObject were slowed down by PySequence_Check() first called on the GameObject, though this would fail it would try and get attributes from the game object - ending up in ~8 attribute lookups each time. Avoiding PySequence_Check() makes ob.getDistanceTo(otherOb) over twice as fast.
- Joystick hat events could crash the BGE for joysticks with more then 4 hats.
- PLY Import failed on PLY files from Carve, added some extra types.
Internal texts file on disk is not used it seems python warnings dont support this (even though exceptions do).
The most common cause of this is passing a float as an argument to a method that took an int.
get around this by setting __file__ in the namespace to the script name before executing the script, the file lines are not found but at least the output is not weird and confusing.
Added read only 'mode' attribute to the python controller so there is a way to tell if its executing a module or a script. Updated docs to better explain execution methods.
if(SDL_PollEvent(&sdl_event)) // if -> while fixed it
removed 'm_buttonnum' was misleading, wasn't used as you expect.
Added gravity to variable to world to be used by collada.
bug reported by blenderage on blenderartist (found other bugs too).
- "All Hat Events" didnt work.
- Multiple hats didnt work
- use a menu with direction names rather then have the user guess. disallow zero as a direction.
- Allow up to 4 hats (was 2).
- Python api was clamping the axis to 2, maximum is currently JOYAXIS_MAX - 16
- New python attributes hatValues and hatSingle, match axis functions.
- Use SDL Axis events to fill in the axis and hat array rather then filling in every axis with SDL_JoystickGetAxis for each axis event.
SCA_RandomActuator: The random generator was shared between replicas and not deleted. Added ref counting between replicas to allow deletion at the end.
KX_Camera: The scenegraph node was not deleted for temporary cameras (ImageMirror and shadow), causing 500 bytes leak per frame and per shadow light.
KX_GameActuator: Global dictionary buffer was not deleted after saving.
KX_MotionState: The motion state for compound child was not deleted
KX_ReplaceMeshActuator: The mesh was unnecessarily converted for each actuator and not deleted, causing large memleak.
After these fix, YoFrankie runs without memleak.
Previous patch was not sorting the state actuators. This was causing
some problems with YoFrankie that relies on the order of actuators
when multiple state actuators are activated at once.
Active state actuators will now be sorted per object. This doesn't
change the fact that state actuators are executed before all other
actuators as before.
Incidently, made the logic loop faster.
use PY_SET_ATTR_FAIL and PY_SET_ATTR_SUCCESS return values so the fake subclassing can know if a value failed to be set or if it was missing from the type. (with PY_SET_ATTR_MISSING)
Also noticed some other mistakes.
- KX_LightObject, setting the type didnt check for an int.
- KX_SoundActuator, didnt return an error when assigning an invalid orientation value
- KX_GameObject, worldOrientation didnt return an error value.
A new bookmark button is available on the controller UI.
When set, the controller is guaranteed to execute before all
other non-bookmarked controllers, provided it is scheduled
for execution.
This is useful for initialization scripts that run once at startup or
scripts that must set some prerequisite for the other controllers at
the start of each logic frame.
This feature is also available at python level with the "bookmark"
attribute. It can be changed during the game.
Note that if several script are bookmarked, their relative order of
execution is not guaranteed. Make sure they don't depend on each other.
- corrections to docs
- disallow calling controller.activate(actuator) when the controller is not active. (Raise a SystemError)
- Added 2 new attributes, CValue.name - deprecates CValue.getName(), KX_GameObject.children deprecated KX_GameObject.getChildren(), (same for getChildrenRecursive()).
A new type of "Sensor" physics object is available in the GE for advanced
collision management. It's called Sensor for its similarities with the
physics objects that underlie the Near and Radar sensors.
Like the Near and Radar object it is:
- static and ghost
- invisible by default
- always active to ensure correct collision detection
- capable of detecting both static and dynamic objects
- ignoring collision with their parent
- capable of broadphase filtering based on:
* Actor option: the collisioning object must have the Actor flag set to be detected
* property/material: as specified in the collision sensors attached to it
Broadphase filtering is important for performance reason: the collision points
will be computed only for the objects that pass the broahphase filter.
- automatically removed from the simulation when no collision sensor is active on it
Unlike the Near and Radar object it can:
- take any shape, including triangle mesh
- be made visible for debugging (just use the Visible actuator)
- have multiple collision sensors using it
Other than that, the sensor objects are ordinary objects. You can move them
freely or parent them. When parented to a dynamic object, they can provide
advanced collision control to this object.
The type of collision capability depends on the shape:
- box, sphere, cylinder, cone, convex hull provide volume detection.
- triangle mesh provides surface detection but you can give some volume
to the suface by increasing the margin in the Advanced Settings panel.
The margin applies on both sides of the surface.
Performance tip:
- Sensor objects perform better than Near and Radar: they do less synchronizations
because of the Scenegraph optimizations and they can have multiple collision sensors
on them (with different property filtering for example).
- Always prefer simple shape (box, sphere) to complex shape whenever possible.
- Always use broadphase filtering (avoid collision sensor with empty propery/material)
- Use collision sensor only when you need them. When no collision sensor is active
on the sensor object, it is removed from the simulation and consume no CPU.
Known limitations:
- When running Blender in debug mode, you will see one warning line of the console:
"warning btCollisionDispatcher::needsCollision: static-static collision!"
In release mode this message is not printed.
- Collision margin has no effect on sphere, cone and cylinder shape.
Other performance improvements:
- Remove unnecessary interpolation for Near and Radar objects and by extension
sensor objects.
- Use direct matrix copy instead of quaternion to synchronize orientation.
Other bug fix:
- Fix Near/Radar position error on newly activated objects. This was causing
several detection problems in YoFrankie
- Fix margin not passed correctly to gImpact shape.
- Disable force/velocity actions on static objects
This commit extends the technique of dynamic linked list to the logic
system to eliminate as much as possible temporaries, map lookup or
full scan. The logic engine is now free of memory allocation, which is
an important stability factor.
The overhead of the logic system is reduced by a factor between 3 and 6
depending on the logic setup. This is the speed-up you can expect on
a logic setup using simple bricks. Heavy bricks like python controllers
and ray sensors will still take about the same time to execute so the
speed up will be less important.
The core of the logic engine has been much reworked but the functionality
is still the same except for one thing: the priority system on the
execution of controllers. The exact same remark applies to actuators but
I'll explain for controllers only:
Previously, it was possible, with the "executePriority" attribute to set
a controller to run before any other controllers in the game. Other than
that, the sequential execution of controllers, as defined in Blender was
guaranteed by default.
With the new system, the sequential execution of controllers is still
guaranteed but only within the controllers of one object. the user can
no longer set a controller to run before any other controllers in the
game. The "executePriority" attribute controls the execution of controllers
within one object. The priority is a small number starting from 0 for the
first controller and incrementing for each controller.
If this missing feature is a must, a special method can be implemented
to set a controller to run before all other controllers.
Other improvements:
- Systematic use of reference in parameter passing to avoid unnecessary data copy
- Use pre increment in iterator instead of post increment to avoid temporary allocation
- Use const char* instead of STR_String whenever possible to avoid temporary allocation
- Fix reference counting bugs (memory leak)
- Fix a crash in certain cases of state switching and object deletion
- Minor speed up in property sensor
- Removal of objects during the game is a lot faster
controller.actuators[name] and controller.sensors[name]
Made a read-only sequence type for logic brick sensors and actuators which can access single items or be used like a list or dictionary.
We could use a python dictionary or CValueList but that would be slower to create.
So you can do...
for s in controller.sensors: print s
print controller.sensors["Sensor"]
print controller.sensors[0]
sensors = list(controller.sensors)
This sequence type keeps a reference to the proxy it came from and will raise an error on access if the proxy has been removed.
also deprecated getActuators() and getSensors() for 'sensors' and 'actuators' attributes.
an example of getting every sensor connected to an object.
all_sensors = [s for c in ob.controllers for s in c.sensors]
When enabled, this option converts any positive trigger from the sensor
into a pair of positive+negative trigger, with the negative trigger sent
in the next frame. The negative trigger from the sensor are not passed
to the controller as the option automatically generates the negative triggers.
From the controller point of view, the sensor is positive only for 1 frame,
even if the underlying sensor state remains positive.
The option interacts with the other sensor option in this way:
- Level option: tap option is mutually exclusive with level option. Both
cannot be enabled at the same time.
- Invert option: tap option operates on the negative trigger of the
sensor, which are converted to positive trigger by the invert option.
Hence, the controller will see the sensor positive for 1 frame when
the underlying sensor state turns negative.
- Positive pulse option: tap option adds a negative trigger after each
repeated positive pulse, unless the frequency option is 0, in which case
positive pulse are generated on every frame as before, as long as the
underlying sensor state is positive.
- Negative pulse option: this option is not compatible with tap option
and is ignored when tap option is enabled.
Notes:
- Keyboard "All keys" is handled specially when tap option is set:
There will be one pair of positive/negative trigger for each new
key press, regardless on how many keys are already pressed and there
is no trigger when keys are released, regardless if keys are still
pressed.
In case two keys are pressed in succesive frames, there will
be 2 positive triggers and 1 negative trigger in the following frame.
- when the attribute check function failed it didnt set an error raising a SystemError instead
- Rasterizer.getMaterialMode would never return KX_BLENDER_MULTITEX_MATERIAL
- PropertySensor value attribute checking function was always returning a fail.
- Vertex Self Shadow python script didnt update for meshes with modifiers.
- Added support for any number of attributes, this means packages are supported automatically.
so as well as "myModule.myFunc" you can do "myPackage.myModule.myFunc", nested packages work too.
- pass the controller to the python function as an argument for functions that take 1 arg, this check is only done at startup so it wont slow things down.
added support for
- Vast performance increase when removing scene containing large number of
objects: the sensor/controller map was updated for each deleted object,
causing massive slow down when the number of objects was large (O(n^2)).
- Use reference when scanning the sensor map => avoid useless copy.
- Remove dynamically the object bounding box from the DBVT when the object
is invisible => faster culling.
Option to run a function in a module rather then a script from a python controller, this has a number of advantages.
- No allocating and freeing the namespace dictionary for every time its triggered
(hard to measure the overhead here, but in a test with calling 42240 scripts a second each defining 200 vars, using modules was ~25% faster)
- Ability to use external python scripts for game logic.
- Convenient debug option that lets you edit scripts while the game engine runs.
PyObjectPlus::ProcessReplica() is now called when any of its subclasses are replicated.
This is important because PyObjectPlus::ProcessReplica() NULL's the 'm_proxy' python pointer I added recently.
Without this a replicated subclass of PyObjectPlus could have an invalid pointer (crashing the BGE).
This change also means CValue::AddDataToReplica() can be moved into CValue::ProcessReplica() since ProcessReplica is always called.
Separate getting a normal attribute and getting __dict__, was having to do too a check for __dict__ on each class (multiple times per getattro call from python) when its not used that often.
- initialize pythons sys.argv in the blenderplayer
- ignore all arguments after a single " - " in the blenderplayer (like in blender), so args can be passed to the game.
- add a utility function PyOrientationTo() - to take a Py euler, quat or 3x3 matrix and convert into a C++ MT_Matrix3x3.
- add utility function ConvertPythonToMesh to get a RAS_MeshObject from a KX_MeshProxy or a name.
- Added error prefix arguments to ConvertPythonToGameObject, ConvertPythonToMesh and PyOrientationTo so the error messages can include what function they came from.
- deprecated brick.getOwner() for the "owner" attribute.
- More verbose error messages.
- BL_Shader wasnt setting error messages on some errors
- FilterNormal depth attribute was checking for float which is bad because scripts often expect ints assigned to float attributes.
- Added a check to PyVecTo for a tuple rather then always using a generic python sequence. On my system this is over 2x faster with an optmized build.
- comments to PyObjectPlus.h
- remove unused/commented junk.
- renamed PyDestructor to py_base_dealloc for consistency
- all the PyTypeObject's were still using the sizeof() their class, can use sizeof(PyObjectPlus_Proxy) now which is smaller too.
This changes how the BGE classes and Python work together, which hasnt changed since blender went opensource.
The main difference is PyObjectPlus - the base class for most game engine classes, no longer inherit from PyObject, and cannot be cast to a PyObject.
This has the advantage that the BGE does not have to keep 2 reference counts valid for C++ and Python.
Previously C++ classes would never be freed while python held a reference, however this reference could be problematic eg: a GameObject that isnt in a scene anymore should not be used by python, doing so could even crash blender in some cases.
Instead PyObjectPlus has a member "PyObject *m_proxy" which is lazily initialized when python needs it. m_proxy reference counts are managed by python, though it should never be freed while the C++ class exists since it holds a reference to avoid making and freeing it all the time.
When the C++ class is free'd it sets the m_proxy reference to NULL, If python accesses this variable it will raise a RuntimeError, (check the isValid attribute to see if its valid without raising an error).
- This replaces the m_zombie bool and IsZombie() tests added recently.
In python return values that used to be..
return value->AddRef();
Are now
return value->GetProxy();
or...
return value->NewProxy(true); // true means python owns this C++ value which will be deleted when the PyObject is freed