Opened 12 years ago

Closed 12 years ago

#1034 closed enhancement (fixed)

Journal Integration

Reported by: asaf Owned by: asaf
Priority: High Milestone: Unspecified
Component: Physics Version: Unspecified
Severity: Unspecified Keywords:
Cc: brian, garycmartin, erikos, kne Distribution/OS: Unspecified
Bug Status: Assigned

Description

Save contraptions when closing the activity and load them when opening an old journal entry.

Change History (12)

comment:1 Changed 12 years ago by asaf

Planning on using pickling available in pyBox2D version 2.0.2b1

comment:2 Changed 12 years ago by asaf

  • Status changed from new to accepted

It works now. I have to do some cleanup and a commit to elements the pickling feature. I'll try to commit everything and close the ticket soon.

comment:3 Changed 12 years ago by brian

:) excellent!

Let me know if you need any help with the elements commit or elements eggbuilding.

comment:4 follow-up: Changed 12 years ago by erikos

As another serialization alternative - we use a lot json (cjson) in sugar and other activities to serialize python objects. http://git.sugarlabs.org/projects/browse/repos/mainline/blobs/master/model.py#line62

comment:5 Changed 12 years ago by asaf

  • Resolution set to fixed
  • Status changed from accepted to closed

Many weeks of reading resulted in less than 10 lines of code in the activity but here it is. I guess we'll consider changing from pickling to another scheme when necessity arises.

comment:6 in reply to: ↑ 4 Changed 12 years ago by asaf

  • Cc erikos added

Replying to erikos:

As another serialization alternative - we use a lot json (cjson) in sugar and other activities to serialize python objects. http://git.sugarlabs.org/projects/browse/repos/mainline/blobs/master/model.py#line62

When I try to serialize with

cjson.encode(self.game.world)

I get

EncodeError: object is not JSON encodable

I think it has to do that what I want to serialize is not made of pure-python objects.

comment:7 Changed 12 years ago by asaf

  • Cc kne added
  • Priority changed from Unspecified by Maintainer to High
  • Resolution fixed deleted
  • Status changed from closed to reopened

Reopened for the sake of forward compatibility.

The plan is to have more control on the savefile format. The suggested implementation is to create a set of classes which structure mimics the structure of the world object. For example:

class Ball:
   pos
   radius
   dynamic
   density
   ...

class Rect:
   pos
   with
   height
   ...

Then create instancees of this objects for each object in the world and put them all in an array and pass that array to cjson.encode . The ideal thing would be to infer this structure from the Add class in elements but that is something to think about a bit more.

comment:8 Changed 12 years ago by erikos

Asaf, yes the traceback above suggests that the world object contains non serializable parts. Maybe looking at the pickle code in elements helps.

def pickle_save(self, fn, additional_vars={}):^M
        import cPickle as pickle^M
        self.add.remove_mouseJoint()^M
    ^M
        if not additional_vars and hasattr(self, '_pickle_vars'):^M
            additional_vars=dict((var, getattr(self, var)) for var in self._pickle_vars)^M
^M
        save_values = [self.world, box2d.pickle_fix(self.world, additional_vars, 'save')]^M
^M
        try:^M
            pickle.dump(save_values, open(fn, 'wb'))^M
        except Exception, s:^M
            print 'Pickling failed: ', s^M
            return^M
^M
        print 'Saved to %s' % fn

comment:9 follow-up: Changed 12 years ago by kne

SWIG objects are not serializable because they exist both on the Python (the shadow classes) and C++-side (the actual structure itself). As such, the somewhat complicated procedure found in here was created. It eventually boils everything down to dictionaries when saving and then recreates them upon loading.

Should you take the JSON route of starting from scratch, you will have to take into account things like joints and controllers. When saving, you want to first save the world's shape list. Then enumerate each joint in the world, writing the index of the shape instead of another copy of the shape definition (as you don't want the shape to be created again). Any references to shapes in your code also have to be fixed like this (which is why the pickle_fix method was introduced).

I did my best to introduce the same-named properties in the shapes as the definitions (as of course they weren't present in the original C++ code). I think there was perhaps one property that didn't get changed though, so take a look at the pickling code as a reference.

You might be able to get by with a somewhat hackish method of using the getstate/setstates that I painstakingly (*cough*) wrote for the pickling functionality. Use them to get the necessary data and then use the JSON serializer as you please.

comment:10 in reply to: ↑ 9 ; follow-up: Changed 12 years ago by asaf

Replying to kne:

Should you take the JSON route of starting from scratch, you will have to take into account things like joints and controllers. When saving, you want to first save the world's shape list. Then enumerate each joint in the world, writing the index of the shape instead of another copy of the shape definition (as you don't want the shape to be created again). Any references to shapes in your code also have to be fixed like this (which is why the pickle_fix method was introduced).

What do you mean by controllers?
Is there a body index or unique id already defined or should I add one to body.userData ?

comment:11 in reply to: ↑ 10 Changed 12 years ago by kne

Replying to asaf:

What do you mean by controllers?

controllers See also the pybox2d buoyancy testbed. If you haven't seen those, you also likely haven't seen the thin line segments, so check those out too.

Is there a body index or unique id already defined or should I add one to body.userData ?

I indexed every body from world.bodyList in my implementation. The body's hash is simply its memory address.

comment:12 Changed 12 years ago by asaf

  • Resolution set to fixed
  • Status changed from reopened to closed

Resolved with JSON format. The save/load functions are implemented at the level of elements. The save/load functions do not support all the features of pybox2d but they support all that the activity requires.

Note: See TracTickets for help on using tickets.