prototypes
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
follow log
clear
reattach
Log Messages
X

Menu
# Constraining Points and Lines in Lively Lively Kernel uses the Browser DOM / SVG to display its graphics. This means updates are observed and not regularly pushed... making constraining them more troublesome, because the constraint system has to guess how to make the underlying system aware of its changes. in NewThinglab we tried to implement simple Points and Lines using JavaScripts getter and setter, but that did not play nicely with babelsberg. On this page we change the implementation to simple observers for Line.start, Line.end, and Point.pos: connect(this, "end", this, "updateEnd", {}); connect(this, "start", this, "updateStart", {}); this.end = pt(10,10) this.start = pt(100,100) But after activating the constraints it does not work either... So what do we do? #ToDo #OpenQuestion
Formatter
Mon Jan 27 2014 14:49:11 GMT+0100 (Central Europe Standard Time)
enabled
migrate parts

FormattedText12

Point
remove
prototypes
migrate <lively.morphic.Morph#78124... - Point1> found protoype <lively.morphic.Morph#CEAED... - Point> migrate <lively.morphic.Morph#56A0C... - Point2> found protoype <lively.morphic.Morph#CEAED... - Point> migrate <lively.morphic.Morph#31053... - Point3> found protoype <lively.morphic.Morph#CEAED... - Point> migrate <lively.morphic.Morph#953AD... - Point5> found protoype <lively.morphic.Morph#CEAED... - Point>
Line2: (245.4,217.4) --> (425.0,100.0) Line3: (79.9,51.9) --> (163.9,157.9) Point3: (335.2,158.7) Point5: (245.4,217.4) Point6: (425.0,100.0) Point7: (121.9,104.9)

Clear
var point = this.get("Bin").get("Point").duplicate(); line.owner.addMorph(point); // no constraint.... yet point.setPosition(line.getEnd().copy()) // fuck you, mutable value classes. fyvm. always: { point.getPosition().eqPt(line.getEnd()) }
$morph("StartPointConstraint").addScript(function onDropOn(morph) { var line = morph; if (!line.isLine) return; var point = this.get("Bin").get("Point").duplicate(); line.owner.addMorph(point); // no constraint.... yet point.setPosition(line.getStart().copy()); point.addConstraints(function keepPositions() { always: { point.getPosition().eqPt(line.getStart()) } }, {point: point, line: line}) this.remove(); });
# Persistant Constraints Adding a constraint to an object using the addConstraints method similar to addScript. Different to addScript the addConstraints method is executed once after definition and after restoring allowing the babelsberg syntax to take effect inside of it.
## Prototypical Implementation We don't make use of babelsberg's code rewriting yet and have to pass the variable bindings explicitly.
this.addScript(function onrestore() { if (this.constraints) { this.constraints.each((function (ea) { var func = this[ea]; try { func.apply(this, ""); } catch (e) { console.log("Error initializing object constraint: " + func + " Error:" + e); } }).bind(this)); } });
this.addScript(function addConstraints(func, mapping) { if (!func.name) throw new Error("added constraint without name: " + func); this.addScript.apply(this, [func, func.name, mapping]); func.isConstraintFunc = true; if (!this.constraints) this.constraints = []; if (!this.constraints.include(func.name)) this.constraints.push(func.name); func.apply(this, []); });
## Alternative Implementation Idea: Use a Serialization Plugin Persist and restore all constraints in the system.....
module('users.timfelgentreff.babelsberg.constraintinterpreter').load(true);
$morph('DrawBoard').removeAllMorphs()
getLine = (function getLine() {
    var line = this.get('Bin').get('Line').duplicate();
    this.get('DrawBoard').addMorph(line)
    return line;
}).bind(this);
getPoint = (function getPoint() {
    var point = this.get('Bin').get('Point').duplicate();
    bbb.unconstrainAll(point)
    this.get('DrawBoard').addMorph(point)
    return point;
}).bind(this);
var newLine = getLine(),
    newPoint1 = getPoint(),
    newPoint2 = getPoint(),
    newPoint3 = getPoint();
bbb.defaultSolver = new ClSimplexSolver()
newLine.direction = pt(100,100)
always: {
    newLine.getStart().subPt(newLine.getEnd()).eqPt(newLine.direction)
}
stay: {
    priority: "weak"
    newLine.direction.x && newLine.direction.y
}
always: {
    newPoint1.getPosition().eqPt(newLine.getStart())
}
always: {
    newPoint2.getPosition().eqPt(newLine.getEnd())
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Clear


LivelyTests.js:ConstraintsSerializationTest:-- all --:testSerializeConstrainedObject (proto)
X

Menu
N

...
../
babelsberg-lively.js
cassowary_ext.js (not parsed)
constraintinterpreter.js
core_ext.js (not parsed)
crp.js (not parsed)
csp_ext.js
deltablue_ext.js
LivelyTests.js
PerformanceTests.js
src_transform.js (not parsed)
src_transform_test.js
tests.js (not parsed)
ConstraintsSerializationTest
-- all --
default category
getSerializer (proto)
setUp (proto)
testSerializeConstrainedObject (proto)
testSerializePlainObject (proto)
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
        var json = this.serializer.serialize(obj);
        console.log("JSON: " + json)
        this.assert(json && json != "null", "serialization has no result")
        this.assert(json.match("__constraints"), "no constraints serialized")
        var obj2 = this.deserializer.deserialize(json)
        this.assert(obj2.c, "normal variable missing")
        this.assert(obj2.a, "constrained variable not derserialized")
        
        this.assert(obj2.a, "constrained variable not derserialized")
        var copiedConstraint = obj2.__constrainedVariables__.a._constraints.first()
        this.assert(copiedConstraint, "copied has no predicate")
        this.assert(copiedConstraint._predicate, "copied constraint has no predicate")
        obj2.a = 4
        LastObj = obj2
        this.assertEquals(obj2.b, obj2.a * 2, " copied constrained failed")
        
    }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
>
<
TestRunner
X
M

lively.tests.TestFrameworkTests
Load module

TestSuiteTest

lively

tests

TestFrameworkTests

AsyncTestCaseTest

MockTest

NativeStackTest

TestCaseTest

TestResultTest

users

timfelgentreff

babelsberg

LivelyTests

ConstraintsSerializationTest

testSerializeConstrainedObject

testSerializePlainObject
Browse
Run
1 run, 0 failed
Reset
Bench
search for: basicCopy
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
[class] lively.morphic.Morph>>basicCopy
[class] lively.morphic.Morph>>copy ("var copy = this.basicCopy();")
2 matches
searchOnServer
CodeSearch for basicCopy
X

Menu
// changed at Wed Jun 10 2015 14:56:59 GMT+0200 (Central Europe Daylight Time) by jenslincke
this.addScript(function basicCopy() {
    // this.basicCopy()
    var obj = this;
    var serializer =  lively.persistence.Serializer.createObjectGraphLinearizerForCopy();
    serializer.showLog = true;
    var copyPlugin = new Global.CopyOnlySubmorphsPlugin();
    copyPlugin.root = obj;
    serializer.addPlugin(copyPlugin);
    return serializer.copy(obj);
});
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
<lively.morphic.Box#1C23E... - DrawBoard1>
Tag:
run
save
Tests

-- ALL --
basicCopy
onrestore
reset
Scripts
-
+
-
Connections
+
-- ALL --
all
ObjectEditor -- DrawBoard1>>basicCopy
X

Menu
babelsberg-lively.js
X

Menu
N

...
../
babelsberg-lively.js
cassowary_ext.js
constraintinterpreter.js
core_ext.js
crp.js
csp_ext.js
deltablue_ext.js
LivelyTests.js
PerformanceTests.js
src_transform.js (not parsed)
src_transform_test.js
tests.js (not parsed)
DoNotSerializeConstraintsPlugin
MorphSetConstrainedPositionLayer
SerializeConstraintsPlugin
-----
-----
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
                // var source = this.getSerializer().register(ea.obj);
                var ref = this.getSerializer().register(ea.value);
                source[ea.propName]
                alertOK('got something:' + ea.propName + " -> " + printObject(ref))
                ea.objCopy[ea.propName] = ref
            }
        }, this)
    },
});
// lively.persistence.pluginsForLively.push(DoNotSerializeConstraintsPlugin);
// lively.persistence.pluginsForLively.remove(DoNotSerializeConstraintsPlugin)
if (!lively.persistence.pluginsForLively.include(SerializeConstraintsPlugin))
     lively.persistence.pluginsForLively.push(SerializeConstraintsPlugin);
// lively.persistence.pluginsForLively.remove(SerializeConstraintsPlugin)
});
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
>
<
// changed at Wed Jun 10 2015 14:58:20 GMT+0200 (Central Europe Daylight Time) by jenslincke
this.addScript(function basicCopy() {
    // this.basicCopy()
    var obj = this;
    var serializer = lively.persistence.Serializer.createObjectGraphLinearizerForCopy();
    serializer.showLog = true;
    var copyPlugin = new Global.CopyOnlySubmorphsPlugin();
    copyPlugin.root = obj;
    serializer.addPlugin(copyPlugin);
    return serializer.copy(obj);
});
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
<lively.morphic.Box#1C23E... - DrawBoard1>
Tag:
run
save
Tests

-- ALL --
basicCopy
onrestore
reset
Scripts
-
+
-
Connections
+
-- ALL --
all
ObjectEditor -- DrawBoard1>>basicCopy
X

Menu
Serializing done in 170ms
AttributeConnection>>update: Error: Could not create solver: Tableau: [Z:obj] <==> 2*[em2:slack] + 1*[em5:slack] + 2*[ep1:slack] + 2*[em7:slack] + -1*[d1:dummy] + 2*[em4:slack] + 1*[em6:slack] + 2*[ep3:slack] + 2*[em8:slack] + -1*[d2:dummy] [v1750:129.55094764496152] <==> 129.55094764496152 + -1*[ep2:slack] + 1*[em2:slack] + -1*[d1:dummy] + -1*[ep7:slack] + 1*[em7:slack] [v1757:213.55094764496152] <==> 213.55094764496152 + -1*[ep2:slack] + 1*[em2:slack] [v1764:34.43779320698104] <==> 34.43779320698104 + -1*[ep4:slack] + 1*[em4:slack] + -1*[d2:dummy] + -1*[ep8:slack] + 1*[em8:slack] [v1771:140.43779320698104] <==> 140.43779320698104 + -1*[ep4:slack] + 1*[em4:slack] [v1778:-84] <==> -84 + -1*[ep7:slack] + 1*[em7:slack] [v1785:-106] <==> -106 + -1*[ep8:slack] + 1*[em8:slack] [em1:slack] <==> -1*[ep2:slack] + 1*[em2:slack] + -1*[d1:dummy] + 1*[ep1:slack] + -1*[ep7:slack] + 1*[em7:slack] [em3:slack] <==> -1*[ep4:slack] + 1*[em4:slack] + -1*[d2:dummy] + 1*[ep3:slack] + -1*[ep8:slack] + 1*[em8:slack] Columns: [ep2:slack] => 3 {[v1757:213.55094764496152], [v1750:129.55094764496152], [em1:slack]} [em2:slack] => 4 {[v1757:213.55094764496152], [Z:obj], [v1750:129.55094764496152], [em1:slack]} [ep4:slack] => 3 {[v1771:140.43779320698104], [v1764:34.43779320698104], [em3:slack]} [em4:slack] => 4 {[v1771:140.43779320698104], [Z:obj], [v1764:34.43779320698104], [em3:slack]} [em5:slack] => 1 {[Z:obj]} [em6:slack] => 1 {[Z:obj]} [d1:dummy] => 3 {[Z:obj], [v1750:129.55094764496152], [em1:slack]} [d2:dummy] => 3 {[Z:obj], [v1764:34.43779320698104], [em3:slack]} [ep1:slack] => 2 {[Z:obj], [em1:slack]} [ep7:slack] => 3 {[v1778:-84], [v1750:129.55094764496152], [em1:slack]} [em7:slack] => 4 {[Z:obj], [v1778:-84], [v1750:129.55094764496152], [em1:slack]} [ep3:slack] => 2 {[Z:obj], [em3:slack]} [ep8:slack] => 3 {[v1785:-106], [v1764:34.43779320698104], [em3:slack]} [em8:slack] => 4 {[Z:obj], [v1785:-106], [v1764:34.43779320698104], [em3:slack]} Infeasible rows: 0 {} External basic variables: 6 {[v1750:129.55094764496152], [v1757:213.55094764496152], [v1764:34.43779320698104], [v1771:140.43779320698104], [v1778:-84], [v1785:-106]} External parametric variables: 0 {} _stayPlusErrorVars: [[ep1:slack],[ep2:slack],[ep3:slack],[ep4:slack],[ep5:slack],[ep6:slack],[ep7:slack],[ep8:slack]] _stayMinusErrorVars: [[em1:slack],[em2:slack],[em3:slack],[em4:slack],[em5:slack],[em6:slack],[em7:slack],[em8:slack]] _editVarMap: stack:Error: Could not create solver: Tableau: [Z:obj] <==> 2*[em2:slack] + 1*[em5:slack] + 2*[ep1:slack] + 2*[em7:slack] + -1*[d1:dummy] + 2*[em4:slack] + 1*[em6:slack] + 2*[ep3:slack] + 2*[em8:slack] + -1*[d2:dummy] [v1750:129.55094764496152] <==> 129.55094764496152 + -1*[ep2:slack] + 1*[em2:slack] + -1*[d1:dummy] + -1*[ep7:slack] + 1*[em7:slack] [v1757:213.55094764496152] <==> 213.55094764496152 + -1*[ep2:slack] + 1*[em2:slack] [v1764:34.43779320698104] <==> 34.43779320698104 + -1*[ep4:slack] + 1*[em4:slack] + -1*[d2:dummy] + -1*[ep8:slack] + 1*[em8:slack] [v1771:140.43779320698104] <==> 140.43779320698104 + -1*[ep4:slack] + 1*[em4:slack] [v1778:-84] <==> -84 + -1*[ep7:slack] + 1*[em7:slack] [v1785:-106] <==> -106 + -1*[ep8:slack] + 1*[em8:slack] [em1:slack] <==> -1*[ep2:slack] + 1*[em2:slack] + -1*[d1:dummy] + 1*[ep1:slack] + -1*[ep7:slack] + 1*[em7:slack] [em3:slack] <==> -1*[ep4:slack] + 1*[em4:slack] + -1*[d2:dummy] + 1*[ep3:slack] + -1*[ep8:slack] + 1*[em8:slack] Columns: [ep2:slack] => 3 {[v1757:213.55094764496152], [v1750:129.55094764496152], [em1:slack]} [em2:slack] => 4 {[v1757:213.55094764496152], [Z:obj], [v1750:129.55094764496152], [em1:slack]} [ep4:slack] => 3 {[v1771:140.43779320698104], [v1764:34.43779320698104], [em3:slack]} [em4:slack] => 4 {[v1771:140.43779320698104], [Z:obj], [v1764:34.43779320698104], [em3:slack]} [em5:slack] => 1 {[Z:obj]} [em6:slack] => 1 {[Z:obj]} [d1:dummy] => 3 {[Z:obj], [v1750:129.55094764496152], [em1:slack]} [d2:dummy] => 3 {[Z:obj], [v1764:34.43779320698104], [em3:slack]} [ep1:slack] => 2 {[Z:obj], [em1:slack]} [ep7:slack] => 3 {[v1778:-84], [v1750:129.55094764496152], [em1:slack]} [em7:slack] => 4 {[Z:obj], [v1778:-84], [v1750:129.55094764496152], [em1:slack]} [ep3:slack] => 2 {[Z:obj], [em3:slack]} [ep8:slack] => 3 {[v1785:-106], [v1764:34.43779320698104], [em3:slack]} [em8:slack] => 4 {[Z:obj], [v1785:-106], [v1764:34.43779320698104], [em3:slack]} Infeasible rows: 0 {} External basic variables: 6 {[v1750:129.55094764496152], [v1757:213.55094764496152], [v1764:34.43779320698104], [v1771:140.43779320698104], [v1778:-84], [v1785:-106]} External parametric variables: 0 {} _stayPlusErrorVars: [[ep1:slack],[ep2:slack],[ep3:slack],[ep4:slack],[ep5:slack],[ep6:slack],[ep7:slack],[ep8:slack]] _stayMinusErrorVars: [[em1:slack],[em2:slack],[em3:slack],[em4:slack],[em5:slack],[em6:slack],[em7:slack],[em8:slack]] _editVarMap: at SerializeConstraintsPlugin.eval (eval at <anonymous> (https://lively-kernel.org/babelsberg/generated/0e1aacb473ced3acc5c6474ec88e13ec/combinedModules.js:61179:21), <anonymous>:95:27) at Array.forEach (native) at exports.arr.each (https://lively-kernel.org/babelsberg/generated/0e1aacb473ced3acc5c6474ec88e13ec/combinedModules.js:12233:16) at Array.prop (https://lively-kernel.org/babelsberg/generated/0e1aacb473ced3acc5c6474ec88e13ec/combinedModules.js:10434:25) at SerializeConstraintsPlugin.deserializationDone (eval at <anonymous> (https://lively-kernel.org/babelsberg/generated/0e1aacb473ced3acc5c6474ec88e13ec/combinedModules.js:61179:21), <anonymous>:91:30) at ObjectGraphLinearizer.Object.subclass.letAllPlugins (https://lively-kernel.org/babelsberg/generated/0e1aacb473ced3acc5c6474ec88e13ec/combinedModules.js:18849:26) at ObjectGraphLinearizer.Object.subclass.deserializeJso (https://lively-kernel.org/babelsberg/generated/0e1aacb473ced3acc5c6474ec88e13ec/combinedModules.js:19027:14) at ObjectGraphLinearizer.Object.subclass.copy (https://lively-kernel.org/babelsberg/generated/0e1aacb473ced3acc5c6474ec88e13ec/combinedModules.js:19047:21) at Box.basicCopy (eval at <anonymous> (https://lively-kernel.org/babelsberg/generated/0e1aacb473ced3acc5c6474ec88e13ec/combinedModules.js:10468:75), <anonymous>:10:23) at Box.runScript (eval at <anonymous> (https://lively-kernel.org/babelsberg/generated/0e1aacb473ced3acc5c6474ec88e13ec/combinedModules.js:10468:75), <anonymous>:5:36)
serialization done