Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature all logic in python (aka. allpy) #410

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Binary file removed data/props/basics.blend
Binary file not shown.
Binary file added data/props/basics_wo_logic.blend
Binary file not shown.
27 changes: 0 additions & 27 deletions src/morse/builder/creator.py
Expand Up @@ -76,30 +76,3 @@ def __init__(self, name="ActuatorCreator", classpath="morse.core.actuator.Actuat
blendname=None):
ComponentCreator.__init__(self, name, 'actuators', blendname)
self.properties(Component_Tag = True, classpath = classpath)

# helpers

def get_properties_str(name):
""" Returns the Game properties of the Blender object represented by the name

get_properties_str('Sick') gives
laser_range = 30.0, Component_Tag = True, scan_window = 180.0,
Visible_arc = True, resolution = 0.25,
classpath = 'morse.sensors.sick.LaserScannerClass'
"""
obj = bpymorse.get_object(name)
properties_dictionary = get_properties(obj)
return ", ".join(["%s = %s"%(pname, properties_dictionary[pname]) \
for pname in properties_dictionary])

def get_properties(obj):
import json
properties_dictionary = {}
properties = obj.game.properties
for name in properties.keys():
properties_dictionary[name] = properties[name].value
if properties[name].type == 'TIMER':
properties_dictionary[name] = "timer(%f)"%properties_dictionary[name]
elif type(properties_dictionary[name]) is str:
properties_dictionary[name] = json.dumps(properties_dictionary[name])
return properties_dictionary
3 changes: 2 additions & 1 deletion src/morse/builder/environment.py
@@ -1,6 +1,7 @@
import logging; logger = logging.getLogger("morsebuilder." + __name__)
import os
import json
import morse.builder.setup
from morse.builder.morsebuilder import *
from morse.builder.abstractcomponent import Configuration
from morse.core.morse_time import TimeStrategies
Expand Down Expand Up @@ -269,7 +270,7 @@ def create(self, name=None):
# define 'Scene_Script_Holder' as the blender object of Enrivonment
if not 'Scene_Script_Holder' in bpymorse.get_objects():
# Add the necessary objects
base = Component('props', 'basics')
morse.builder.setup.init_morse()

# Set Scene_Script_Holder as core Environment object
self.set_blender_object(bpymorse.get_object('Scene_Script_Holder'))
Expand Down
353 changes: 353 additions & 0 deletions src/morse/builder/setup.py

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion src/morse/sensors/camera.py
Expand Up @@ -64,7 +64,6 @@ def default_action(self):
""" Update the texture image. """
# Configure the texture settings the first time the sensor is called
if not self._texture_ok:
self._texture_ok = True
if blenderapi.isfastmode():
logger.warning("Running in fastmode! No camera support!")
else:
Expand All @@ -78,6 +77,7 @@ def default_action(self):
else:
self._camera_running = True

return

if self._camera_running:
# Update all objects pose/orientation before to refresh the image
Expand Down Expand Up @@ -130,6 +130,8 @@ def _setup_video_texture(self):
# Get the reference to the scene
scene_map = blenderapi.get_scene_map()
logger.info("Scene %s from %s"% (self.scene_name, repr(scene_map.keys()) ) )
if self.scene_name not in scene_map:
return
self._scene = scene_map[self.scene_name]
self._morse_scene = scene_map['S.MORSE_LOGIC']

Expand Down Expand Up @@ -175,3 +177,4 @@ def _setup_video_texture(self):
detail)

blenderapi.cameras()[self.name()] = vt_camera
self._texture_ok = True
3 changes: 2 additions & 1 deletion src/morse/sensors/video_camera.py
Expand Up @@ -105,12 +105,13 @@ def capture(self, n):

def default_action(self):
""" Update the texture image. """

# Grab an image from the texture
if self.bge_object['capturing'] and (self._n != 0) :

# Call the action of the parent class
morse.sensors.camera.Camera.default_action(self)
if not self._camera_running:
return

# NOTE: Blender returns the image as a binary string
# encoded as RGBA
Expand Down
1 change: 1 addition & 0 deletions testing/base/gyroscope_testing.py
Expand Up @@ -13,6 +13,7 @@
pass

import sys
import math
from pymorse import Morse


Expand Down
1 change: 1 addition & 0 deletions testing/base/velocity_testing.py
Expand Up @@ -4,6 +4,7 @@
"""

import sys
import math
from morse.testing.testing import MorseTestCase
from pymorse import Morse

Expand Down
1 change: 1 addition & 0 deletions testing/base/video_camera_testing.py
Expand Up @@ -17,6 +17,7 @@
import sys
import time
import base64
import math
import struct
import zlib
from pymorse import Morse
Expand Down
1 change: 1 addition & 0 deletions testing/robots/segway/segway_vw.py
Expand Up @@ -4,6 +4,7 @@
"""

import sys
import math
from morse.testing.testing import MorseTestCase
from pymorse import Morse

Expand Down
186 changes: 186 additions & 0 deletions tools/builder_generator.py
@@ -0,0 +1,186 @@
# usage: blender file.blend -P builder_generator.py > file.py
import bpy, json

# helpers (c/p following in a Blender Text editor, run it, look at your console)

def select_only(obj):
bpy.ops.object.select_all(action='DESELECT')
obj.select = True
bpy.context.scene.objects.active = obj

def roundv(v,r=3):
return tuple([round(e, r) for e in v])

def do_all():
print("base = AbstractComponent(category='props', filename='basics_wo_logic')")
meshes = [o.name for o in bpy.data.objects if o.type == 'MESH']
print("base.append_meshes(%s)"%repr(meshes))
for obj in bpy.data.objects:
print("# %s : %s"%(obj.type, obj.name))
if obj.type == 'MESH':
print("select_only(bpy.data.objects['%s'])"%obj.name)
else:
print("bpy.ops.object.add(type='%s', location=%s, rotation=%s)" % \
(obj.type, repr(obj.location), repr(obj.rotation_euler)))
print("bpy.context.object.name = '%s'" % obj.name)
if obj.scale != (1,1,1):
print("bpy.context.object.scale = %s" % repr(obj.scale))

print("bpy.context.object.game.physics_type = '%s'" % obj.game.physics_type)
print("bpy.context.object.hide_render = %s" % obj.hide_render)
print_properties(obj)
print_all_logic(obj)

# set children - parent relationship
for obj in bpy.data.objects:
for child in obj.children:
# child.parent = obj
print("bpy.data.objects['%s'].parent = bpy.data.objects['%s']" % \
(child.name, obj.name) )

# set children - parent relationship
for text in bpy.data.texts:
print("# text : %s"%text.name)
print("new_text()")
print("text = get_last_text()")
print("text.name = '%s'" % text.name)
print("text_str = %s" % json.dumps(text.as_string()) )
print("text.write(text_str)")


def get_properties(obj):
import json
map_prop = {}
properties = obj.game.properties
for name in properties.keys():
map_prop[name] = properties[name].value
if properties[name].type == 'TIMER':
map_prop[name] = "timer(%f)"%map_prop[name]
elif type(map_prop[name]) is str:
map_prop[name] = json.dumps(map_prop[name])
return map_prop

def print_properties(obj):
""" Returns the Game properties of the Blender objects """
map_prop = get_properties(obj)
if not map_prop:
return
str_prop = ", ".join(["%s=%s"%(pname, map_prop[pname]) \
for pname in map_prop.keys()])
print("properties(bpy.context.object, %s)" % str_prop)

def print_all_logic(obj):
print("game = bpy.context.object.game")
for brick in obj.game.actuators:
print_logic(brick, 'actuator')
for brick in obj.game.controllers:
print_logic(brick, 'controller')
for act in brick.actuators:
print("game.controllers['%s'].link(actuator=game.actuators['%s'])" % \
(brick.name, act.name) )
for brick in obj.game.sensors:
print_logic(brick, 'sensor')
for ctr in brick.controllers:
print("game.sensors['%s'].link(game.controllers['%s'])" % \
(brick.name, ctr.name) )

# map the default values of game logic bricks to filter the output
map_attr_default = {
'default': {
'__module__': '',
'type': '',
#'name': '',
'show_expanded': '',
},
'sensor': {
'default': {
'frequency': 0,
'invert': False,
'use_level': False,
'use_pulse_false_level': False,
'use_pulse_true_level': False,
'use_tap': False,
'pin': False,
},
'PROPERTY': {
'evaluation_type': 'PROPEQUAL',
'property': '',
'value': '',
'value_max': '',
'value_min': '',
},
'KEYBOARD': {
'log': '',
'modifier_key_1': 'NONE',
'modifier_key_2': 'NONE',
'target': '',
'use_all_keys': False,
},
'MOUSE': {
'use_pulse': False,
},
},
'controller': {
'default': {
'use_priority': False,
'states': 1,
},
'PYTHON': {
'mode': 'SCRIPT',
'module': '',
'use_debug': False,
},
},
'actuator': {
'default': {
'pin': False,
},
'VISIBILITY': {
'apply_to_children': False,
'use_occlusion': False,
},
},
}

def print_logic(brick, sca):
print("add_%s(type='%s', name='%s')"%(sca, brick.type, brick.name))

for attr in dir(brick):
if attr in map_attr_default['default'].keys():
continue # skip
value = getattr(brick, attr)
if attr in map_attr_default[sca]['default'].keys() and \
value == map_attr_default[sca]['default'][attr]:
continue # skip default to save readibility
if brick.type in map_attr_default[sca] and \
attr in map_attr_default[sca][brick.type].keys() and \
value == map_attr_default[sca][brick.type][attr]:
continue # skip default to save readibility
if type(value).__name__ in ['int', 'float', 'bool']:
print("game.%ss[-1].%s = %s" % (sca, attr, str(value)) )
if type(value).__name__ == 'str':
print("game.%ss[-1].%s = %s" % (sca, attr, json.dumps(value)) )

_header = """# usage: blender -P {file}
import os, sys, subprocess

def ext_exec(cmd, python=None):
if not python:
python = 'python%i.%i'%(sys.version_info.major, sys.version_info.minor)
return subprocess.getoutput('%s -c"%s"' % (python, cmd) )

def fix_python_path(python=None):
pythonpath = ext_exec("import os,sys;print(os.pathsep.join(sys.path))")
sys.path.extend(pythonpath.split(os.pathsep))

fix_python_path()

from morse.builder.bpymorse import *
from morse.builder import AbstractComponent
from mathutils import Vector, Euler
"""

if __name__ == '__main__':
print(_header)
do_all()
print("\n\n# TODO remove the following lines (Blender output messages)\n\n")