Scripted objects saving attributes: Difference between revisions

From FreeCAD Documentation
(→‎Saving all attributes: The original tuple for self.color was converted to a list, but otherwise all attributes were loaded the same.)
(Removed work in progress)
Line 1: Line 1:
{{Work_in_progress}}
<languages/>
<languages/>
<translate>
<translate>

Revision as of 02:29, 11 May 2020

Introduction

Scripted objects are rebuilt every time a FCStd document is opened. To do this the document keeps a reference to the module and Python class that were used to create the object, along with its properties.

Attributes of the class used to create the object can also be saved, that is, "serialized". This can be further controlled by the __getstate__ and __setstate__ methods of the class.

Saving all attributes

By default, attributes saved in an object class are those from the __dict__ dictionary of the class.

# various_states.py
class VariousStates:
    def __init__(self, obj):
        obj.addProperty("App::PropertyLength", "Length")
        obj.addProperty("App::PropertyArea", "Area")
        obj.Length = 15
        obj.Area = 300
        obj.Proxy = self

        Type = dict()
        Type["Version"] = "Custom"
        Type["Release"] = "production"
        self.Type = Type
        self.Type = "Custom"
        self.ver = "0.18"
        self.color = (0, 0, 1)
        self.width = 2.5

    def execute(self, obj):
        pass

An object can be created using this class, and it can be saved to my_document.FCstd. If no particular viewprovider is assigned to the new object, its proxy class is simply set to a value different from None, in this case, to 1.

import FreeCAD as App
import various_states

doc = App.newDocument()
doc.FileName = "my_document.FCStd"

obj = doc.addObject("Part::FeaturePython", "Custom")
various_states.VariousStates(obj)

if App.GuiUp:
    obj.ViewObject.Proxy = 1

doc.recompute()
doc.save()

When we re-open the file we can inspect the dictionary of the object's class.

>>> obj = App.ActiveDocument.Custom
>>> print(obj.Proxy)
<various_states.VariousStates object at 0x7f0a899bde10>
>>> print(obj.Proxy.__dict__)
{'Type': {'Version': 'Custom', 'Release': 'production'}, 'ver': '0.18', 'color': [0, 0, 1], 'width': 2.5}

We see that all attributes that start with self in the class were saved. These can be of different types, including string, list, float, and dictionary. The original tuple for self.color was converted to a list, but otherwise all attributes were loaded the same.

Saving specific attributes

We can define a class similar to the first one, that implements specific attributes to save.

# various_states.py
class CustomStates:
    def __init__(self, obj):
        obj.addProperty("App::PropertyLength", "Length")
        obj.addProperty("App::PropertyArea", "Area")
        obj.Length = 15
        obj.Area = 300
        obj.Proxy = self

        Type = dict()
        Type["Version"] = "Custom"
        Type["Release"] = "production"
        self.Type = Type
        self.ver = "0.18"
        self.color = (0, 0, 1)
        self.width = 2.5

    def execute(self, obj):
        pass

    def __getstate__(self):
        return self.color, self.width

    def __setstate__(self, state):
        self.color = state[0]
        self.width = state[1]

The return value of __getstate__ is the object that will be serialized. This can be a single value, or a tuple of values. When the object is restored, the class calls the __setstate__ method, passing the state variable with the serialized content. In this case state is a tuple that is unpacked into the respective variables to reconstruct the "state" that original existed.

state = (self.color, self.width)
state = ((0, 0, 1), 2.5)

We can create an object with this class, and save the document, just like in the previous example. When we re-open the file we can inspect the dictionary of the object's class.

>>> obj2 = App.ActiveDocument.Custom2
>>> print(obj2.Proxy)
<various_states.CustomStates object at 0x7fb399496630>
>>> print(obj2.Proxy.__dict__)
{'color': [0, 0, 1], 'width': 2.5}

The original tuple for self.color was converted to a list, but otherwise the information was recovered fine. Instead of restoring all attributes like in the previous case, only the attributes that we specified in __getstate__ and __setstate__ were restored.

Links