ya2 · news · projects · code · about

new item
authorFlavio Calva <f.calva@gmail.com>
Sat, 29 Oct 2022 08:44:22 +0000 (09:44 +0100)
committerFlavio Calva <f.calva@gmail.com>
Fri, 11 Nov 2022 16:12:54 +0000 (17:12 +0100)
15 files changed:
assets/images/buttons/trashcan.png [new file with mode: 0644]
assets/scenes/basketball.json
assets/scenes/box.json
assets/scenes/domino.json
assets/scenes/domino_box.json
assets/scenes/domino_box_basketball.json
assets/scenes/teeter_domino_box_basketball.json
assets/scenes/teeter_tooter.json
pmachines/app.py
pmachines/editor/inspector.py
pmachines/editor/scene.py
pmachines/items/box.py
pmachines/items/item.py
pmachines/scene.py
prj.org

diff --git a/assets/images/buttons/trashcan.png b/assets/images/buttons/trashcan.png
new file mode 100644 (file)
index 0000000..cbd352d
Binary files /dev/null and b/assets/images/buttons/trashcan.png differ
index cb50a3a61accff44bd7c48abbd7a65e08874c47f..93ff646d6027b2335a99b7962638f07230172bd4 100644 (file)
-{"version": "220914",
- "name": "Basket ball",
- "instructions": "Goal: you must hit every domino piece\\n\\nkeep \\5mouse_l\\5 pressed to drag an item\\n\\nkeep \\5mouse_r\\5 pressed to rotate an item",
- "test_items": {
-     "pixel_space": [
-        {"id": "drag_start_0",
-         "position": [55, 50]}
-     ],
-     "world_space": [
-        {"id": "drag_stop_0",
-         "position": [-0.42, 1.03]},
-        {"id": "drag_stop_1",
-         "position": [-4.19, 4.66]}]},
- "start_items": [
-     {"class": "Basketball",
-      "count": 1}],
- "fixed_items": [
-     {"class": "Shelf",
-      "position": [-0.56, 0, 0.21]},
-     {"class": "Shelf",
-      "position": [1.67, 0, 0.21]},
-     {"class": "Shelf",
-      "position": [-0.56, 0, -1.45]},
-     {"class": "Shelf",
-      "position": [1.67, 0, -1.45]},
-     {"class": "Shelf",
-      "position": [-4.45, 0, -3.18],
-      "roll": 27,
-      "restitution": 1}],
- "scene_items": [
-     {"class": "Domino",
-      "position": [-0.61, 0, -0.89],
+{
+  "items": [
+    {
+      "class": "Shelf",
+      "position": [
+        -0.56,
+        0,
+        0.21
+      ],
+      "mass": 0
+    },
+    {
+      "class": "Shelf",
+      "position": [
+        1.67,
+        0,
+        0.21
+      ],
+      "mass": 0
+    },
+    {
+      "class": "Shelf",
+      "position": [
+        -0.56,
+        0,
+        -1.45
+      ],
+      "mass": 0
+    },
+    {
+      "class": "Shelf",
+      "position": [
+        1.67,
+        0,
+        -1.45
+      ],
+      "mass": 0
+    },
+    {
+      "class": "Shelf",
+      "position": [
+        -4.45,
+        0,
+        -3.18
+      ],
+      "mass": 0,
+      "restitution": 1,
+      "roll": 27
+    },
+    {
+      "class": "Domino",
+      "position": [
+        -0.61,
+        0,
+        -0.89
+      ],
+      "mass": 1,
       "strategy": "DownStrategy",
-      "strategy_args": [35]},
-     {"class": "Domino",
-      "position": [-0.06, 0, -0.89],
+      "strategy_args": [
+        35
+      ]
+    },
+    {
+      "class": "Domino",
+      "position": [
+        -0.06,
+        0,
+        -0.89
+      ],
+      "mass": 1,
       "strategy": "DownStrategy",
-      "strategy_args": [35]},
-     {"class": "Domino",
-      "position": [0.91, 0, -0.89],
+      "strategy_args": [
+        35
+      ]
+    },
+    {
+      "class": "Domino",
+      "position": [
+        0.91,
+        0,
+        -0.89
+      ],
+      "mass": 1,
       "strategy": "DownStrategy",
-      "strategy_args": [35]},
-     {"class": "Domino",
-      "position": [1.73, 0, -0.89],
+      "strategy_args": [
+        35
+      ]
+    },
+    {
+      "class": "Domino",
+      "position": [
+        1.73,
+        0,
+        -0.89
+      ],
+      "mass": 1,
       "strategy": "DownStrategy",
-      "strategy_args": [35]},
-     {"class": "Domino",
-      "position": [2.57, 0, -0.89],
+      "strategy_args": [
+        35
+      ]
+    },
+    {
+      "class": "Domino",
+      "position": [
+        2.57,
+        0,
+        -0.89
+      ],
+      "mass": 1,
       "strategy": "DownStrategy",
-      "strategy_args": [30]}]}
+      "strategy_args": [
+        30
+      ]
+    }
+  ],
+  "instructions": "Goal: you must hit every domino piece\n\nkeep \\5mouse_l\\5 pressed to drag an item\n\nkeep \\5mouse_r\\5 pressed to rotate an item",
+  "name": "Basket ball",
+  "start_items": [
+    {
+      "class": "Basketball",
+      "count": 1
+    }
+  ],
+  "test_items": {
+    "pixel_space": [
+      {
+        "id": "drag_start_0",
+        "position": [
+          55,
+          50
+        ]
+      }
+    ],
+    "world_space": [
+      {
+        "id": "drag_stop_0",
+        "position": [
+          -0.42,
+          1.03
+        ]
+      },
+      {
+        "id": "drag_stop_1",
+        "position": [
+          -4.19,
+          4.66
+        ]
+      }
+    ]
+  },
+  "version": "d6a06890225b"
+}
index 34bb6261d56e233d763dbbc211ab3f80fb0763a0..d3d82f6758f963a1d32ce5cc959a6ac04b804a33 100644 (file)
-{"version": "220914",
- "name": "Box",
- "instructions": "Goal: the left box must hit the right box\\n\\nkeep \\5mouse_l\\5 pressed to drag an item\\n\\nkeep \\5mouse_r\\5 pressed to rotate an item",
- "test_items": {
-     "pixel_space": [
-        {"id": "drag_start_0",
-         "position": [65, 60]}
-     ],
-     "world_space": [
-        {"id": "drag_stop_0",
-         "position": [0.42, -3.29]},
-        {"id": "drag_stop_1",
-         "position": [0.42, -2.18]},
-        {"id": "drag_stop_2",
-         "position": [0.35, -1.06]}
-     ]},
- "start_items": [
-     {"class": "Box",
-      "count": 3}],
- "fixed_items": [
-     {"class": "Shelf",
-      "position": [0.46, 0, -3.95]},
-     {"class": "Shelf",
-      "position": [4.43, 0, -3.95]},
-     {"class": "Shelf",
-      "position": [-1.29, 0, 0.26],
-      "roll": 28.45},
-     {"class": "Shelf",
-      "position": [2.15, 0, -1.49],
-      "roll": 28.45}],
- "scene_items": [
-     {"class": "Box",
-      "position": [-1.55, 0, 1.23],
+{
+  "instructions": "Goal: the left box must hit the right box\n\nkeep \\5mouse_l\\5 pressed to drag an item\n\nkeep \\5mouse_r\\5 pressed to rotate an item",
+  "items": [
+    {
+      "class": "Shelf",
+      "mass": 0,
+      "position": [
+        0.46,
+        0,
+        -3.95
+      ]
+    },
+    {
+      "class": "Shelf",
+      "mass": 0,
+      "position": [
+        4.43,
+        0,
+        -3.95
+      ]
+    },
+    {
+      "class": "Shelf",
+      "mass": 0,
+      "position": [
+        -1.29,
+        0,
+        0.26
+      ],
+      "roll": 28.45
+    },
+    {
+      "class": "Shelf",
+      "mass": 0,
+      "position": [
+        2.15,
+        0,
+        -1.49
+      ],
+      "roll": 28.45
+    },
+    {
+      "class": "Box",
       "friction": 0.4,
-      "id": "left_box"},
-     {"class": "Box",
-      "position": [4.38, 0, -3.35],
+      "id": "left_box",
+      "mass": 1,
+      "position": [
+        -1.5499999523162842,
+        0.0,
+        1.2300000190734863
+      ],
+      "roll": 0.0
+    },
+    {
+      "class": "Box",
+      "mass": 1,
+      "position": [
+        4.380000114440918,
+        0.0,
+        -3.3499999046325684
+      ],
+      "roll": 0.0,
       "strategy": "HitStrategy",
-      "strategy_args": ["left_box"]}]
-}
+      "strategy_args": [
+        "left_box"
+      ]
+    }
+  ],
+  "name": "Box",
+  "start_items": [
+    {
+      "class": "Box",
+      "count": 3
+    }
+  ],
+  "test_items": {
+    "pixel_space": [
+      {
+        "id": "drag_start_0",
+        "position": [
+          65,
+          60
+        ]
+      }
+    ],
+    "world_space": [
+      {
+        "id": "drag_stop_0",
+        "position": [
+          0.42,
+          -3.29
+        ]
+      },
+      {
+        "id": "drag_stop_1",
+        "position": [
+          0.42,
+          -2.18
+        ]
+      },
+      {
+        "id": "drag_stop_2",
+        "position": [
+          0.35,
+          -1.06
+        ]
+      }
+    ]
+  },
+  "version": "8062bd34519a"
+}
\ No newline at end of file
index d609796efd42c1cca76eb45035e8bfe2cf2de9c9..8f02ef478fafd0fbd2458024eb76603ebdc8d28e 100644 (file)
-{"version": "220914",
- "name": "Domino",
- "instructions": "Goal: every domino piece must fall\\n\\nkeep \\5mouse_l\\5 pressed to drag an item\\n\\nkeep \\5mouse_r\\5 pressed to rotate an item",
- "test_items": {
-     "pixel_space": [
-        {"id": "drag_start_0",
-         "position": [35, 60]}
-     ],
-     "world_space": [
-        {"id": "drag_stop_0",
-         "position": [-1.82, 0.06]},
-        {"id": "drag_stop_1",
-         "position": [0.49, 0.06]},
-        {"id": "drag_stop_2",
-         "position": [-1.54, 0.06]},
-        {"id": "drag_start_1",
-         "position": [-1.54, 0.4]},
-        {"id": "drag_stop_3",
-         "position": [-1.05, 0.4]}
-     ]
- },
- "start_items": [
-     {"class": "Domino",
-      "count": 2}],
- "fixed_items": [
-     {"class": "Shelf",
-      "position": [-1.2, 0, -0.6]},
-     {"class": "Shelf",
-      "position": [1.2, 0, -0.6]}],
- "scene_items": [
-     {"class": "Domino",
-      "position": [-1.14, 0, -0.04],
+{
+  "items": [
+    {
+      "class": "Shelf",
+      "position": [
+        -1.2,
+        0,
+        -0.6
+      ],
+      "mass": 0
+    },
+    {
+      "class": "Shelf",
+      "position": [
+        1.2,
+        0,
+        -0.6
+      ],
+      "mass": 0
+    },
+    {
+      "class": "Domino",
+      "position": [
+        -1.14,
+        0,
+        -0.04
+      ],
+      "mass": 1,
       "strategy": "DownStrategy",
-      "strategy_args": [60]},
-     {"class": "Domino",
-      "position": [-0.49, 0, -0.04],
+      "strategy_args": [
+        60
+      ]
+    },
+    {
+      "class": "Domino",
+      "position": [
+        -0.49,
+        0,
+        -0.04
+      ],
+      "mass": 1,
       "strategy": "DownStrategy",
-      "strategy_args": [60]},
-     {"class": "Domino",
-      "position": [0.94, 0, -0.04],
+      "strategy_args": [
+        60
+      ]
+    },
+    {
+      "class": "Domino",
+      "position": [
+        0.94,
+        0,
+        -0.04
+      ],
+      "mass": 1,
       "strategy": "DownStrategy",
-      "strategy_args": [60]},
-     {"class": "Domino",
-      "position": [1.55, 0, -0.04],
+      "strategy_args": [
+        60
+      ]
+    },
+    {
+      "class": "Domino",
+      "position": [
+        1.55,
+        0,
+        -0.04
+      ],
+      "mass": 1,
       "strategy": "DownStrategy",
-      "strategy_args": [60]},
-     {"class": "Domino",
-      "position": [2.09, 0, -0.04],
+      "strategy_args": [
+        60
+      ]
+    },
+    {
+      "class": "Domino",
+      "position": [
+        2.09,
+        0,
+        -0.04
+      ],
+      "mass": 1,
       "strategy": "DownStrategy",
-      "strategy_args": [88]}]
+      "strategy_args": [
+        88
+      ]
+    }
+  ],
+  "instructions": "Goal: every domino piece must fall\n\nkeep \\5mouse_l\\5 pressed to drag an item\n\nkeep \\5mouse_r\\5 pressed to rotate an item",
+  "name": "Domino",
+  "start_items": [
+    {
+      "class": "Domino",
+      "count": 2
+    }
+  ],
+  "test_items": {
+    "pixel_space": [
+      {
+        "id": "drag_start_0",
+        "position": [
+          35,
+          60
+        ]
+      }
+    ],
+    "world_space": [
+      {
+        "id": "drag_stop_0",
+        "position": [
+          -1.82,
+          0.06
+        ]
+      },
+      {
+        "id": "drag_stop_1",
+        "position": [
+          0.49,
+          0.06
+        ]
+      },
+      {
+        "id": "drag_stop_2",
+        "position": [
+          -1.54,
+          0.06
+        ]
+      },
+      {
+        "id": "drag_start_1",
+        "position": [
+          -1.54,
+          0.4
+        ]
+      },
+      {
+        "id": "drag_stop_3",
+        "position": [
+          -1.05,
+          0.4
+        ]
+      }
+    ]
+  },
+  "version": "fabe277a7cbd"
 }
index 132545723e84062ff2d9e5f72f47232fac37210e..87df60e67307387e86d2ca21a236d6263808b63d 100644 (file)
-{"version": "220914",
- "name": "Domino and box",
- "instructions": "Goal: only the last piece of each row must be up\\n\\nkeep \\5mouse_l\\5 pressed to drag an item\\n\\nkeep \\5mouse_r\\5 pressed to rotate an item",
- "test_items": {
-     "pixel_space": [
-        {"id": "drag_start_0",
-         "position": [65, 60]}
-     ],
-     "world_space": [
-        {"id": "drag_stop_0",
-         "position": [3.21, -0.78]},
-        {"id": "drag_stop_1",
-         "position": [3.21, 0.33]},
-        {"id": "drag_stop_2",
-         "position": [2.16, 1.87]}
-     ]},
- "start_items": [
-     {"class": "Box",
-      "count": 2,
-      "mass": 5}],
- "fixed_items": [
-     {"class": "Shelf",
-      "position": [-0.56, 0, 0.21]},
-     {"class": "Shelf",
-      "position": [1.67, 0, 0.21]},
-     {"class": "Shelf",
-      "position": [-0.56, 0, -1.45]},
-     {"class": "Shelf",
-      "position": [1.67, 0, -1.45]},
-     {"class": "Shelf",
-      "position": [3.78, 0, -1.45]}],
- "scene_items": [
-     {"class": "Domino",
-      "position": [-0.61, 0, -0.94],
+{
+  "items": [
+    {
+      "class": "Shelf",
+      "position": [
+        -0.56,
+        0,
+        0.21
+      ],
+      "mass": 0
+    },
+    {
+      "class": "Shelf",
+      "position": [
+        1.67,
+        0,
+        0.21
+      ],
+      "mass": 0
+    },
+    {
+      "class": "Shelf",
+      "position": [
+        -0.56,
+        0,
+        -1.45
+      ],
+      "mass": 0
+    },
+    {
+      "class": "Shelf",
+      "position": [
+        1.67,
+        0,
+        -1.45
+      ],
+      "mass": 0
+    },
+    {
+      "class": "Shelf",
+      "position": [
+        3.78,
+        0,
+        -1.45
+      ],
+      "mass": 0
+    },
+    {
+      "class": "Domino",
+      "position": [
+        -0.61,
+        0,
+        -0.94
+      ],
+      "mass": 1,
       "roll": 37,
       "strategy": "DownStrategy",
-      "strategy_args": [35]},
-     {"class": "Domino",
-      "position": [-0.06, 0, -0.89],
+      "strategy_args": [
+        35
+      ]
+    },
+    {
+      "class": "Domino",
+      "position": [
+        -0.06,
+        0,
+        -0.89
+      ],
+      "mass": 1,
       "strategy": "DownStrategy",
-      "strategy_args": [35]},
-     {"class": "Domino",
-      "position": [0.91, 0, -0.89],
+      "strategy_args": [
+        35
+      ]
+    },
+    {
+      "class": "Domino",
+      "position": [
+        0.91,
+        0,
+        -0.89
+      ],
+      "mass": 1,
       "strategy": "DownStrategy",
-      "strategy_args": [35]},
-     {"class": "Domino",
-      "position": [1.73, 0, -0.89],
+      "strategy_args": [
+        35
+      ]
+    },
+    {
+      "class": "Domino",
+      "position": [
+        1.73,
+        0,
+        -0.89
+      ],
+      "mass": 1,
       "strategy": "DownStrategy",
-      "strategy_args": [35]},
-     {"class": "Domino",
-      "position": [2.57, 0, -0.89],
+      "strategy_args": [
+        35
+      ]
+    },
+    {
+      "class": "Domino",
+      "position": [
+        2.57,
+        0,
+        -0.89
+      ],
+      "mass": 1,
       "strategy": "UpStrategy",
-      "strategy_args": [30]},
-     {"class": "Domino",
-      "position": [-0.61, 0, 0.73],
+      "strategy_args": [
+        30
+      ]
+    },
+    {
+      "class": "Domino",
+      "position": [
+        -0.61,
+        0,
+        0.73
+      ],
+      "mass": 1,
       "roll": 37,
       "strategy": "DownStrategy",
-      "strategy_args": [35]},
-     {"class": "Domino",
-      "position": [-0.06, 0, 0.78],
+      "strategy_args": [
+        35
+      ]
+    },
+    {
+      "class": "Domino",
+      "position": [
+        -0.06,
+        0,
+        0.78
+      ],
+      "mass": 1,
       "strategy": "DownStrategy",
-      "strategy_args": [35]},
-     {"class": "Domino",
-      "position": [0.91, 0, 0.78],
+      "strategy_args": [
+        35
+      ]
+    },
+    {
+      "class": "Domino",
+      "position": [
+        0.91,
+        0,
+        0.78
+      ],
+      "mass": 1,
       "strategy": "DownStrategy",
-      "strategy_args": [35]},
-     {"class": "Domino",
-      "position": [1.73, 0, 0.78],
+      "strategy_args": [
+        35
+      ]
+    },
+    {
+      "class": "Domino",
+      "position": [
+        1.73,
+        0,
+        0.78
+      ],
+      "mass": 1,
       "strategy": "UpStrategy",
-      "strategy_args": [30]},
-     {"class": "Domino",
-      "position": [2.57, 0, 0.78],
+      "strategy_args": [
+        30
+      ]
+    },
+    {
+      "class": "Domino",
+      "position": [
+        2.57,
+        0,
+        0.78
+      ],
+      "mass": 1,
       "strategy": "UpStrategy",
-      "strategy_args": [30]}]}
+      "strategy_args": [
+        30
+      ]
+    }
+  ],
+  "instructions": "Goal: only the last piece of each row must be up\n\nkeep \\5mouse_l\\5 pressed to drag an item\n\nkeep \\5mouse_r\\5 pressed to rotate an item",
+  "name": "Domino and box",
+  "start_items": [
+    {
+      "class": "Box",
+      "count": 2,
+      "mass": 5
+    }
+  ],
+  "test_items": {
+    "pixel_space": [
+      {
+        "id": "drag_start_0",
+        "position": [
+          65,
+          60
+        ]
+      }
+    ],
+    "world_space": [
+      {
+        "id": "drag_stop_0",
+        "position": [
+          3.21,
+          -0.78
+        ]
+      },
+      {
+        "id": "drag_stop_1",
+        "position": [
+          3.21,
+          0.33
+        ]
+      },
+      {
+        "id": "drag_stop_2",
+        "position": [
+          2.16,
+          1.87
+        ]
+      }
+    ]
+  },
+  "version": "621f7e5cc76e"
+}
index 0ac0a30c250dbf65cc354d8bb0da998560a81378..6543fb73ac60327f1f8f2bb2b4a05e4665694291 100644 (file)
-{"version": "220914",
- "name": "Domino, box and basket ball",
- "instructions": "Goal: every domino piece must be hit\\n\\nkeep \\5mouse_l\\5 pressed to drag an item\\n\\nkeep \\5mouse_r\\5 pressed to rotate an item",
- "test_items": {
-     "pixel_space": [
-        {"id": "drag_start_0",
-         "position": [65, 60]},
-        {"id": "drag_start_1",
-         "position": [30, 60]}
-     ],
-     "world_space": [
-        {"id": "drag_stop_0",
-         "position": [-1.4, -0.78]},
-        {"id": "drag_stop_1",
-         "position": [-1.26, 0.2]},
-        {"id": "drag_stop_2",
-         "position": [-0.28, -0.78]},
-        {"id": "drag_start_2",
-         "position": [-0.28, -0.57]},
-        {"id": "drag_stop_3",
-         "position": [-0.77, -0.57]},
-        {"id": "drag_start_3",
-         "position": [-0.28, -0.85]},
-        {"id": "drag_stop_4",
-         "position": [-0.42, -0.85]}
-     ]},
- "start_items": [
-     {"class": "Box",
-      "count": 1,
-      "mass": 5},
-     {"class": "Domino",
-      "count": 1}],
- "fixed_items": [
-     {"class": "Shelf",
-      "position": [-0.56, 0, -1.45]},
-     {"class": "Shelf",
-      "position": [1.67, 0, -1.45]},
-     {"class": "Shelf",
-      "position": [3.78, 0, -1.45]},
-     {"class": "Shelf",
-      "position": [1.48, 0, 0.38],
-      "roll": -90},
-     {"class": "Shelf",
-      "position": [2.62, 0, 0.05]},
-     {"class": "Shelf",
-      "position": [4.88, 0, 0.05]}],
- "scene_items": [
-     {"class": "Basketball",
-      "position": [-0.3, 1, 2.5]},
-     {"class": "Domino",
-      "position": [1.68, 0, -0.89],
+{
+  "items": [
+    {
+      "class": "Shelf",
+      "position": [
+        -0.56,
+        0,
+        -1.45
+      ],
+      "mass": 0
+    },
+    {
+      "class": "Shelf",
+      "position": [
+        1.67,
+        0,
+        -1.45
+      ],
+      "mass": 0
+    },
+    {
+      "class": "Shelf",
+      "position": [
+        3.78,
+        0,
+        -1.45
+      ],
+      "mass": 0
+    },
+    {
+      "class": "Shelf",
+      "position": [
+        1.48,
+        0,
+        0.38
+      ],
+      "mass": 0,
+      "roll": -90
+    },
+    {
+      "class": "Shelf",
+      "position": [
+        2.62,
+        0,
+        0.05
+      ],
+      "mass": 0
+    },
+    {
+      "class": "Shelf",
+      "position": [
+        4.88,
+        0,
+        0.05
+      ],
+      "mass": 0
+    },
+    {
+      "class": "Basketball",
+      "position": [
+        -0.3,
+        1,
+        2.5
+      ],
+      "mass": 1
+    },
+    {
+      "class": "Domino",
+      "position": [
+        1.68,
+        0,
+        -0.89
+      ],
+      "mass": 1,
       "strategy": "DownStrategy",
-      "strategy_args": [35]},
-     {"class": "Domino",
-      "position": [2.35, 0, -0.89],
+      "strategy_args": [
+        35
+      ]
+    },
+    {
+      "class": "Domino",
+      "position": [
+        2.35,
+        0,
+        -0.89
+      ],
+      "mass": 1,
       "strategy": "DownStrategy",
-      "strategy_args": [35]},
-     {"class": "Domino",
-      "position": [3.08, 0, -0.89],
+      "strategy_args": [
+        35
+      ]
+    },
+    {
+      "class": "Domino",
+      "position": [
+        3.08,
+        0,
+        -0.89
+      ],
+      "mass": 1,
       "strategy": "DownStrategy",
-      "strategy_args": [35]},
-     {"class": "Domino",
-      "position": [3.78, 0, -0.89],
+      "strategy_args": [
+        35
+      ]
+    },
+    {
+      "class": "Domino",
+      "position": [
+        3.78,
+        0,
+        -0.89
+      ],
+      "mass": 1,
       "strategy": "DownStrategy",
-      "strategy_args": [35]},
-     {"class": "Domino",
-      "position": [4.53, 0, -0.89],
+      "strategy_args": [
+        35
+      ]
+    },
+    {
+      "class": "Domino",
+      "position": [
+        4.53,
+        0,
+        -0.89
+      ],
+      "mass": 1,
       "strategy": "DownStrategy",
-      "strategy_args": [35]}]
- }
+      "strategy_args": [
+        35
+      ]
+    }
+  ],
+  "instructions": "Goal: every domino piece must be hit\n\nkeep \\5mouse_l\\5 pressed to drag an item\n\nkeep \\5mouse_r\\5 pressed to rotate an item",
+  "name": "Domino, box and basket ball",
+  "start_items": [
+    {
+      "class": "Box",
+      "count": 1,
+      "mass": 5
+    },
+    {
+      "class": "Domino",
+      "count": 1
+    }
+  ],
+  "test_items": {
+    "pixel_space": [
+      {
+        "id": "drag_start_0",
+        "position": [
+          65,
+          60
+        ]
+      },
+      {
+        "id": "drag_start_1",
+        "position": [
+          30,
+          60
+        ]
+      }
+    ],
+    "world_space": [
+      {
+        "id": "drag_stop_0",
+        "position": [
+          -1.4,
+          -0.78
+        ]
+      },
+      {
+        "id": "drag_stop_1",
+        "position": [
+          -1.26,
+          0.2
+        ]
+      },
+      {
+        "id": "drag_stop_2",
+        "position": [
+          -0.28,
+          -0.78
+        ]
+      },
+      {
+        "id": "drag_start_2",
+        "position": [
+          -0.28,
+          -0.57
+        ]
+      },
+      {
+        "id": "drag_stop_3",
+        "position": [
+          -0.77,
+          -0.57
+        ]
+      },
+      {
+        "id": "drag_start_3",
+        "position": [
+          -0.28,
+          -0.85
+        ]
+      },
+      {
+        "id": "drag_stop_4",
+        "position": [
+          -0.42,
+          -0.85
+        ]
+      }
+    ]
+  },
+  "version": "ecb8be6d8330"
+}
index eca7bdcefb1b099dd479f213bae383a8d10401aa..5159a2807dada89b7f21007ed7b06afdbc664aff 100644 (file)
-{"version": "220914",
- "name": "Teeter tooter, domino, box and basket ball",
- "instructions": "Goal: every domino piece must be hit\\n\\nkeep \\5mouse_l\\5 pressed to drag an item\\n\\nkeep \\5mouse_r\\5 pressed to rotate an item",
- "test_items": {
-     "pixel_space": [
-        {"id": "drag_start_0",
-         "position": [60, 60]}
-     ],
-     "world_space": [
-        {"id": "drag_stop_0",
-         "position": [-7.33, 4.24]},
-        {"id": "drag_stop_1",
-         "position": [-7.12, 4.24]},
-        {"id": "drag_start_1",
-         "position": [-6.77, 4.66]},
-        {"id": "drag_stop_2",
-         "position": [-6.77, 4.24]}
-     ]},
- "start_items": [
-     {"class": "Box",
-      "count": 2,
-      "mass": 3,
-      "friction": 1}],
- "fixed_items": [
-     {"class": "Shelf",
-      "position": [-6.24, 0, -1.45]},
-     {"class": "TeeterTooter",
-      "position": [-6.24, 0, -1.20]},
-     {"class": "Shelf",
-      "position": [5.37, 0, -0.78]},
-     {"class": "Shelf",
-      "position": [7.48, 0, -0.78]},
-     {"class": "Shelf",
-      "position": [4.74, 0, -1.95]},
-     {"class": "Shelf",
-      "position": [6.88, 0, -1.95]},
-     {"class": "Shelf",
-      "position": [0.53, 0, -1.95],
-      "restitution": 0.95},
-     {"class": "Shelf",
-      "position": [2.63, 0, -1.95],
-      "restitution": 0.95},
-     {"class": "Shelf",
-      "position": [-3.65, 0, 1.05],
-      "roll": 28,
-      "friction": 0},
-     {"class": "Shelf",
-      "position": [-1.27, 0, 1.72],
-      "restitution": 0.95},
-     {"class": "Shelf",
-      "position": [0.88, 0, 1.72],
-      "restitution": 0.95},
-     {"class": "Shelf",
-      "position": [-1.67, 0, 0.55],
-      "restitution": 0.95},
-     {"class": "Shelf",
-      "position": [0.52, 0, 0.55],
-      "restitution": 0.95}],
- "scene_items": [
-     {"class": "Basketball",
-      "position": [0.98, 1, 1.02]},
-     {"class": "Shelf",
-      "position": [-6.15, 0, -0.93],
+{
+  "items": [
+    {
+      "class": "Shelf",
+      "position": [
+        -6.24,
+        0,
+        -1.45
+      ],
+      "mass": 0
+    },
+    {
+      "class": "TeeterTooter",
+      "position": [
+        -6.24,
+        0,
+        -1.2
+      ],
+      "mass": 0
+    },
+    {
+      "class": "Shelf",
+      "position": [
+        5.37,
+        0,
+        -0.78
+      ],
+      "mass": 0
+    },
+    {
+      "class": "Shelf",
+      "position": [
+        7.48,
+        0,
+        -0.78
+      ],
+      "mass": 0
+    },
+    {
+      "class": "Shelf",
+      "position": [
+        4.74,
+        0,
+        -1.95
+      ],
+      "mass": 0
+    },
+    {
+      "class": "Shelf",
+      "position": [
+        6.88,
+        0,
+        -1.95
+      ],
+      "mass": 0
+    },
+    {
+      "class": "Shelf",
+      "position": [
+        0.53,
+        0,
+        -1.95
+      ],
+      "mass": 0,
+      "restitution": 0.95
+    },
+    {
+      "class": "Shelf",
+      "position": [
+        2.63,
+        0,
+        -1.95
+      ],
+      "mass": 0,
+      "restitution": 0.95
+    },
+    {
+      "class": "Shelf",
+      "friction": 0,
+      "position": [
+        -3.65,
+        0,
+        1.05
+      ],
+      "mass": 0,
+      "roll": 28
+    },
+    {
+      "class": "Shelf",
+      "position": [
+        -1.27,
+        0,
+        1.72
+      ],
+      "mass": 0,
+      "restitution": 0.95
+    },
+    {
+      "class": "Shelf",
+      "position": [
+        0.88,
+        0,
+        1.72
+      ],
+      "mass": 0,
+      "restitution": 0.95
+    },
+    {
+      "class": "Shelf",
+      "position": [
+        -1.67,
+        0,
+        0.55
+      ],
+      "mass": 0,
+      "restitution": 0.95
+    },
+    {
+      "class": "Shelf",
+      "position": [
+        0.52,
+        0,
+        0.55
+      ],
+      "mass": 0,
+      "restitution": 0.95
+    },
+    {
+      "class": "Basketball",
+      "position": [
+        0.98,
+        1,
+        1.02
+      ],
+      "mass": 1
+    },
+    {
+      "class": "Shelf",
+      "friction": 1,
       "mass": 1,
-      "roll": 24.60,
-      "friction": 1},
-     {"class": "Box",
-      "position": [-5.38, 0, -0.93],
-      "mass": 0.3,
+      "position": [
+        -6.15,
+        0,
+        -0.93
+      ],
+      "roll": 24.6
+    },
+    {
+      "class": "Box",
       "friction": 1,
-      "roll": 24.60,
-      "model_scale": 0.5},
-     {"class": "Domino",
-      "position": [4.83, 0, -1.39],
+      "mass": 0.3,
+      "model_scale": 0.5,
+      "position": [
+        -5.38,
+        0,
+        -0.93
+      ],
+      "roll": 24.6
+    },
+    {
+      "class": "Domino",
+      "position": [
+        4.83,
+        0,
+        -1.39
+      ],
+      "mass": 1,
       "strategy": "DownStrategy",
-      "strategy_args": [35]},
-     {"class": "Domino",
-      "position": [5.67, 0, -1.39],
+      "strategy_args": [
+        35
+      ]
+    },
+    {
+      "class": "Domino",
+      "position": [
+        5.67,
+        0,
+        -1.39
+      ],
+      "mass": 1,
       "strategy": "DownStrategy",
-      "strategy_args": [35]},
-     {"class": "Domino",
-      "position": [6.59, 0, -1.39],
+      "strategy_args": [
+        35
+      ]
+    },
+    {
+      "class": "Domino",
+      "position": [
+        6.59,
+        0,
+        -1.39
+      ],
+      "mass": 1,
       "strategy": "DownStrategy",
-      "strategy_args": [35]},
-     {"class": "Domino",
-      "position": [-1.73, 0, 1.11],
+      "strategy_args": [
+        35
+      ]
+    },
+    {
+      "class": "Domino",
+      "position": [
+        -1.73,
+        0,
+        1.11
+      ],
+      "mass": 1,
       "strategy": "DownStrategy",
-      "strategy_args": [35]},
-     {"class": "Domino",
-      "position": [-0.97, 0, 1.11],
+      "strategy_args": [
+        35
+      ]
+    },
+    {
+      "class": "Domino",
+      "position": [
+        -0.97,
+        0,
+        1.11
+      ],
+      "mass": 1,
       "strategy": "DownStrategy",
-      "strategy_args": [35]},
-     {"class": "Domino",
-      "position": [-0.1, 0, 1.11],
+      "strategy_args": [
+        35
+      ]
+    },
+    {
+      "class": "Domino",
+      "position": [
+        -0.1,
+        0,
+        1.11
+      ],
+      "mass": 1,
       "strategy": "DownStrategy",
-      "strategy_args": [35]}]}
+      "strategy_args": [
+        35
+      ]
+    }
+  ],
+  "instructions": "Goal: every domino piece must be hit\n\nkeep \\5mouse_l\\5 pressed to drag an item\n\nkeep \\5mouse_r\\5 pressed to rotate an item",
+  "name": "Teeter tooter, domino, box and basket ball",
+  "start_items": [
+    {
+      "class": "Box",
+      "count": 2,
+      "friction": 1,
+      "mass": 3
+    }
+  ],
+  "test_items": {
+    "pixel_space": [
+      {
+        "id": "drag_start_0",
+        "position": [
+          60,
+          60
+        ]
+      }
+    ],
+    "world_space": [
+      {
+        "id": "drag_stop_0",
+        "position": [
+          -7.33,
+          4.24
+        ]
+      },
+      {
+        "id": "drag_stop_1",
+        "position": [
+          -7.12,
+          4.24
+        ]
+      },
+      {
+        "id": "drag_start_1",
+        "position": [
+          -6.77,
+          4.66
+        ]
+      },
+      {
+        "id": "drag_stop_2",
+        "position": [
+          -6.77,
+          4.24
+        ]
+      }
+    ]
+  },
+  "version": "3796993dea9b"
+}
index 12d25aca6fde0d1be75c2cfc561bdcf6df811338..63de0316391bba5e5216d96092a449f1e26438c8 100644 (file)
-{"version": "220914",
- "name": "Teeter tooter",
- "instructions": "Goal: you must hit every domino piece\\n\\nkeep \\5mouse_l\\5 pressed to drag an item\\n\\nkeep \\5mouse_r\\5 pressed to rotate an item",
- "test_items": {
-     "pixel_space": [
-        {"id": "drag_start_0",
-         "position": [60, 60]}
-     ],
-     "world_space": [
-        {"id": "drag_stop_0",
-         "position": [-2.65, 1.18]},
-        {"id": "drag_stop_1",
-         "position": [-2.65, 3.27]},
-        {"id": "drag_start_1",
-         "position": [-2.3, 3.75]},
-        {"id": "drag_stop_2",
-         "position": [-2.5, 3.66]}
-     ]},
- "start_items": [
-     {"class": "Box",
-      "count": 1,
-      "mass": 3,
-      "friction": 1}],
- "fixed_items": [
-     {"class": "Shelf",
-      "position": [-2.76, 0, -1.45]},
-     {"class": "Shelf",
-      "position": [-0.56, 0, -1.45]},
-     {"class": "Shelf",
-      "position": [2.27, 0, -0.28]},
-     {"class": "Shelf",
-      "position": [4.38, 0, -0.28]},
-     {"class": "Shelf",
-      "position": [1.67, 0, -1.45]},
-     {"class": "Shelf",
-      "position": [3.78, 0, -1.45]},
-     {"class": "TeeterTooter",
-      "position": [-2.74, 0, -1.20]},
-     {"class": "Shelf",
-      "position": [-0.25, 0, -0.57],
-      "roll": 52}],
- "scene_items": [
-     {"class": "Shelf",
-      "position": [-2.78, 0, -0.93],
-      "roll": -25.30,
+{
+  "items": [
+    {
+      "class": "Shelf",
+      "position": [
+        -2.76,
+        0,
+        -1.45
+      ],
+      "mass": 0
+    },
+    {
+      "class": "Shelf",
+      "position": [
+        -0.56,
+        0,
+        -1.45
+      ],
+      "mass": 0
+    },
+    {
+      "class": "Shelf",
+      "position": [
+        2.27,
+        0,
+        -0.28
+      ],
+      "mass": 0
+    },
+    {
+      "class": "Shelf",
+      "position": [
+        4.38,
+        0,
+        -0.28
+      ],
+      "mass": 0
+    },
+    {
+      "class": "Shelf",
+      "position": [
+        1.67,
+        0,
+        -1.45
+      ],
+      "mass": 0
+    },
+    {
+      "class": "Shelf",
+      "position": [
+        3.78,
+        0,
+        -1.45
+      ],
+      "mass": 0
+    },
+    {
+      "class": "TeeterTooter",
+      "position": [
+        -2.74,
+        0,
+        -1.2
+      ],
+      "mass": 0
+    },
+    {
+      "class": "Shelf",
+      "position": [
+        -0.25,
+        0,
+        -0.57
+      ],
+      "mass": 0,
+      "roll": 52
+    },
+    {
+      "class": "Shelf",
+      "friction": 1,
       "mass": 1,
-      "friction": 1},
-     {"class": "Box",
-      "position": [-3.61, 0, -0.99],
-      "roll": -25.30,
-      "mass": 0.2,
+      "position": [
+        -2.78,
+        0,
+        -0.93
+      ],
+      "roll": -25.3
+    },
+    {
+      "class": "Box",
       "friction": 1,
-      "model_scale": 0.5},
-     {"class": "Domino",
-      "position": [1.73, 0, -0.89],
+      "mass": 0.2,
+      "model_scale": 0.5,
+      "position": [
+        -3.61,
+        0,
+        -0.99
+      ],
+      "roll": -25.3
+    },
+    {
+      "class": "Domino",
+      "position": [
+        1.73,
+        0,
+        -0.89
+      ],
+      "mass": 1,
       "strategy": "DownStrategy",
-      "strategy_args": [35]},
-     {"class": "Domino",
-      "position": [2.57, 0, -0.89],
+      "strategy_args": [
+        35
+      ]
+    },
+    {
+      "class": "Domino",
+      "position": [
+        2.57,
+        0,
+        -0.89
+      ],
+      "mass": 1,
       "strategy": "DownStrategy",
-      "strategy_args": [35]},
-     {"class": "Domino",
-      "position": [3.50, 0, -0.89],
+      "strategy_args": [
+        35
+      ]
+    },
+    {
+      "class": "Domino",
+      "position": [
+        3.5,
+        0,
+        -0.89
+      ],
+      "mass": 1,
       "strategy": "DownStrategy",
-      "strategy_args": [35]}]}
+      "strategy_args": [
+        35
+      ]
+    }
+  ],
+  "instructions": "Goal: you must hit every domino piece\n\nkeep \\5mouse_l\\5 pressed to drag an item\n\nkeep \\5mouse_r\\5 pressed to rotate an item",
+  "name": "Teeter tooter",
+  "start_items": [
+    {
+      "class": "Box",
+      "count": 1,
+      "friction": 1,
+      "mass": 3
+    }
+  ],
+  "test_items": {
+    "pixel_space": [
+      {
+        "id": "drag_start_0",
+        "position": [
+          60,
+          60
+        ]
+      }
+    ],
+    "world_space": [
+      {
+        "id": "drag_stop_0",
+        "position": [
+          -2.65,
+          1.18
+        ]
+      },
+      {
+        "id": "drag_stop_1",
+        "position": [
+          -2.65,
+          3.27
+        ]
+      },
+      {
+        "id": "drag_start_1",
+        "position": [
+          -2.3,
+          3.75
+        ]
+      },
+      {
+        "id": "drag_stop_2",
+        "position": [
+          -2.5,
+          3.66
+        ]
+      }
+    ]
+  },
+  "version": "5efa110617cc"
+}
index b61ac20ce8c453ff3e8c845952c91fe40b768db6..2d8098847496218d48dc2e34eef42743dc4dadc0 100755 (executable)
@@ -98,7 +98,7 @@ class Pmachines:
     def start(self):
         if self._args.screenshot:
             #cls = [cls for cls in self.scenes if cls.__name__ == self._args.screenshot][0]
-            scene = Scene(BulletWorld(), None, True, False, lambda: None, self.scenes(), self._pos_mgr, None, None, None, self._args.screenshot)
+            scene = Scene(BulletWorld(), None, True, False, lambda: None, self.scenes(), self._pos_mgr, None, None, None, self._args.screenshot, None, None)
             scene.screenshot()
             scene.destroy()
             exit()
index fb1aeb65ab98a074f7bfb38af68c0ea46b5bdbc6..b5440a0cb9be91fab04d8ba23b13af88ec10c67a 100644 (file)
@@ -1,17 +1,25 @@
 from collections import namedtuple
+from glob import glob
+from importlib import import_module
+from os.path import basename
+from inspect import isclass
 from panda3d.core import Texture, TextNode
 from direct.gui.OnscreenImage import OnscreenImage
-from direct.gui.DirectGui import DirectButton, DirectFrame, DirectEntry
+from direct.gui.DirectGui import DirectButton, DirectFrame, DirectEntry, DirectOptionMenu, OkDialog
 from direct.gui.DirectGuiGlobals import FLAT, NORMAL
 from direct.gui.OnscreenText import OnscreenText
 from direct.showbase.DirectObject import DirectObject
+from pmachines.items.item import ItemStrategy, FixedStrategy, StillStrategy
+from pmachines.items.box import HitStrategy
+from pmachines.items.domino import DownStrategy, UpStrategy
 
 
 class Inspector(DirectObject):
 
-    def __init__(self, item):
+    def __init__(self, item, all_items):
         super().__init__()
         self.__item = item
+        self.__all_items = all_items
         self._font = base.loader.load_font(
             'assets/fonts/Hanken-Book.ttf')
         self._font.clear()
@@ -28,7 +36,7 @@ class Inspector(DirectObject):
                 'assets/audio/sfx/rollover.ogg'),
             'clickSound': loader.load_sfx(
                 'assets/audio/sfx/click.ogg')}
-        w, h = .8, .76
+        w, h = .8, 1.04
         self._frm = DirectFrame(frameColor=(.4, .4, .4, .06),
                                 frameSize=(0, w, -h, 0),
                                 parent=base.a2dTopRight,
@@ -40,15 +48,27 @@ class Inspector(DirectObject):
         m = self.__item._mass
         restitution = self.__item._restitution
         f = self.__item._friction
+        _id = ''
+        if 'id' in self.__item.json:
+            _id = self.__item.json['id']
+        _strategy = ''
+        if 'strategy' in self.__item.json:
+            _strategy = self.__item.json['strategy']
+        _strategy_args = ''
+        if 'strategy_args' in self.__item.json:
+            _strategy_args = ' '.join(self.__item.json['strategy_args'])
         t, pos_entry = self.__add_row(_('position'), f'{round(p.x, 3)}, {round(p.z, 3)}', self.on_edit_position)
         t, rot_entry = self.__add_row(_('roll'), f'{round(r, 3)}', self.on_edit_roll)
         t, scale_entry = self.__add_row(_('scale'), f'{round(s, 3)}', self.on_edit_scale)
         t, mass_entry = self.__add_row(_('mass'), f'{round(m, 3)}', self.on_edit_mass)
         t, restitution_entry = self.__add_row(_('restitution'), f'{round(restitution, 3)}', self.on_edit_restitution)
         t, friction_entry = self.__add_row(_('friction'), f'{round(f, 3)}', self.on_edit_friction)
-        fields = ['position', 'roll', 'scale', 'mass', 'restitution', 'friction']
+        t, id_entry = self.__add_row(_('id'), _id, self.on_edit_id)
+        t, strategy_entry = self.__add_row_option(_('strategy'), _strategy, self.on_edit_strategy)
+        t, strategy_args_entry = self.__add_row(_('strategy_args'), _strategy_args, self.on_edit_strategy_args)
+        fields = ['position', 'roll', 'scale', 'mass', 'restitution', 'friction', 'id', 'strategy', 'strategy_args']
         Entries = namedtuple('Entries', fields)
-        self.__entries = Entries(pos_entry, rot_entry, scale_entry, mass_entry, restitution_entry, friction_entry)
+        self.__entries = Entries(pos_entry, rot_entry, scale_entry, mass_entry, restitution_entry, friction_entry, id_entry, strategy_entry, strategy_args_entry)
         def load_images_btn(path, col):
             colors = {
                 'gray': [
@@ -71,6 +91,13 @@ class Inspector(DirectObject):
             rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
             clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
         self.accept('item-rototranslated', self.__on_item_rototranslated)
+        DirectButton(
+            image=load_images_btn('trashcan', 'gray'), scale=.05,
+            pos=(.18, 1, -h + .06),
+            parent=self._frm, command=self.__delete_item, state=NORMAL, relief=FLAT,
+            frameColor=fcols[0],
+            rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
+            clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
 
     def __add_row(self, label, text, callback):
         tw = 10
@@ -95,6 +122,47 @@ class Inspector(DirectObject):
         self.__z -= .1
         return t, e
 
+    def __add_row_option(self, label, text, callback):
+        item_modules = glob('pmachines/items/*.py')
+        item_modules = [basename(i)[:-3] for i in item_modules]
+        new_items = ['']
+        for item_module in item_modules:
+            mod_name = 'pmachines.items.' + item_module
+            for member in import_module(mod_name).__dict__.values():
+                if isclass(member) and issubclass(member, ItemStrategy) and \
+                        member != ItemStrategy:
+                    new_items = list(set(new_items + [member.__name__]))
+        t = OnscreenText(
+            label,
+            pos=(.03, self.__z), parent=self._frm,
+            font=self._common['text_font'],
+            scale=self._common['scale'],
+            fg=self._common['text_fg'],
+            wordwrap=20, align=TextNode.ALeft)
+        e = DirectOptionMenu(
+            scale=self._common['scale'],
+            initialitem=text,
+            pos=(.30, 1, self.__z),
+            items=new_items,
+            parent=self._frm,
+            command=callback,
+            state=NORMAL,
+            relief=FLAT,
+            item_relief=FLAT,
+            frameColor=self._common['frameColor'],
+            item_frameColor=self._common['frameColor'],
+            popupMenu_frameColor=self._common['frameColor'],
+            popupMarker_frameColor=self._common['frameColor'],
+            text_font=self._font,
+            text_fg=self._common['text_fg'],
+            highlightColor=(.9, .9, .9, .9),
+            item_text_font=self._font,
+            item_text_fg=self._common['text_fg'],
+            rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
+            clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
+        self.__z -= .1
+        return t, e
+
     def __load_img_btn(self, path, col):
         img = OnscreenImage('assets/images/buttons/%s.dds' % path)
         img.set_transparency(True)
@@ -107,6 +175,12 @@ class Inspector(DirectObject):
         r = np.get_r()
         self.__entries.position.set('%s %s' % (str(round(pos.x, 3)), str(round(pos.z, 3))))
         self.__entries.roll.set('%s' % str(round(r, 3)))
+        self.__item.json['position'] = list(pos)
+        self.__item.json['roll'] = round(r, 3)
+
+    def __delete_item(self):
+        messenger.send('editor-inspector-delete', [self.__item])
+        self.destroy()
 
     @property
     def item(self):
@@ -131,6 +205,67 @@ class Inspector(DirectObject):
     def on_edit_friction(self, txt):
         self.__item.friction = float(txt)
 
+    def on_edit_id(self, txt):
+        self.__item.id = txt
+
+    def on_edit_strategy(self, txt):
+        if not txt:
+            self.__entries.strategy_args.set('')
+            return
+        name2class = {
+            'StillStrategy': StillStrategy,
+            'UpStrategy': UpStrategy,
+            'HitStrategy': HitStrategy,
+            'DownStrategy': DownStrategy,
+            'FixedStrategy': FixedStrategy}
+        class_ = name2class[txt]
+        args = []
+        error = False
+        if txt == 'StillStrategy':
+            args += [self.__item._np]
+        if txt in ['UpStrategy', 'DownStrategy']:
+            args += [self.__item._np]
+            try:
+                args += [float(self.__entries.strategy_args.get())]
+            except ValueError:
+                error = True
+        if txt == 'HitStrategy':
+            for item in self.__all_items:
+                if item.id == self.__entries.strategy_args.get():
+                    args += [item]
+            args += [self.__item.node]
+            args += [self.__item._world]
+        if not error:
+            self.__item.strategy = class_(*args)
+            self.__item.strategy_json = txt
+        else:
+            self.__show_error_popup()
+
+    def on_edit_strategy_args(self, txt):
+        self.__item.strategy_args_json = txt
+
+    def __show_error_popup(self):
+            self.__dialog = OkDialog(dialogName='Strategy args errors',
+                                        text=_('There are errors in the strategy args.'),
+                                        command=self.__actually_close)
+            self.__dialog['frameColor'] = (.4, .4, .4, .14)
+            self.__dialog['relief'] = FLAT
+            self.__dialog.component('text0')['fg'] = (.9, .9, .9, 1)
+            self.__dialog.component('text0')['font'] = self._font
+            for b in self.__dialog.buttonList:
+                b['frameColor'] = (.4, .4, .4, .14)
+                b.component('text0')['fg'] = (.9, .9, .9, 1)
+                b.component('text0')['font'] = self._font
+                b.component('text1')['fg'] = (.9, .1, .1, 1)
+                b.component('text1')['font'] = self._font
+                b.component('text2')['fg'] = (.9, .9, .1, 1)
+                b.component('text2')['font'] = self._font
+
+    def __actually_close(self, arg):
+        self.__entries.strategy.set('')
+        self.__entries.strategy_args.set('')
+        self.__dialog.cleanup()
+
     def destroy(self):
         self._frm.destroy()
         self.ignore('item-rototranslated')
index 4a5a1d9ffd07970e808b8e7f753744ce661c793f..7569113b1b30e3b0a8ae9be81e36849bfe7dee8e 100644 (file)
@@ -1,23 +1,33 @@
 from copy import deepcopy
 from json import dumps
+from importlib import import_module
+from inspect import isclass
+from glob import glob
+from os.path import basename
+from logging import info
 import hashlib
 from panda3d.core import Texture, TextNode
 from direct.gui.OnscreenImage import OnscreenImage
-from direct.gui.DirectGui import DirectButton, DirectFrame, DirectEntry, YesNoDialog
+from direct.gui.DirectGui import DirectButton, DirectFrame, DirectEntry, \
+    YesNoDialog, DirectOptionMenu
 from direct.gui.DirectGuiGlobals import FLAT, NORMAL
 from direct.gui.OnscreenText import OnscreenText
 from direct.showbase.DirectObject import DirectObject
+from pmachines.items.item import Item
 from pmachines.editor.scene_list import SceneList
 from pmachines.editor.inspector import Inspector
 
 
 class SceneEditor(DirectObject):
 
-    def __init__(self, json, json_name):
+    def __init__(self, json, json_name, context, add_item, items):
         super().__init__()
+        self.__items = items
         self.__json = json
         self.__json_name = json_name
         self.__inspector = None
+        self.__context = context
+        self.__add_item = add_item
         self._font = base.loader.load_font(
             'assets/fonts/Hanken-Book.ttf')
         self._font.clear()
@@ -113,8 +123,36 @@ class SceneEditor(DirectObject):
             frameColor=fcols[0],
             rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
             clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
+        item_modules = glob('pmachines/items/*.py')
+        item_modules = [basename(i)[:-3] for i in item_modules]
+        self.__new_items = {}
+        for item_module in item_modules:
+            mod_name = 'pmachines.items.' + item_module
+            for member in import_module(mod_name).__dict__.values():
+                if isclass(member) and issubclass(member, Item) and \
+                        member != Item:
+                    self.__new_items[member.__name__] = member
+        OnscreenText(
+            _('new item'), pos=(.02, .46), parent=self._frm,
+            font=self._common['text_font'],
+            scale=self._common['scale'],
+            fg=self._common['text_fg'],
+            align=TextNode.A_left)
+        DirectOptionMenu(
+            scale=.05,
+            text=_('new item'), pos=(.02, 1, .4), items=list(self.__new_items.keys()),
+            parent=self._frm, command=self.__on_new_item, state=NORMAL,
+            relief=FLAT, item_relief=FLAT,
+            frameColor=fcols[0], item_frameColor=fcols[0],
+            popupMenu_frameColor=fcols[0],
+            popupMarker_frameColor=fcols[0],
+            text_font=self._font, text_fg=(.9, .9, .9, 1),
+            highlightColor=(.9, .9, .9, .9),
+            item_text_font=self._font, item_text_fg=(.9, .9, .9, 1),
+            rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
+            clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
         messenger.send('editor-start')
-        self.accept('editor-item-click-l', self.__on_item_click_l)
+        self.accept('editor-item-click', self.__on_item_click)
         self.accept('editor-inspector-destroy', self.__on_inspector_destroy)
 
     def __on_close(self):
@@ -139,6 +177,22 @@ class SceneEditor(DirectObject):
                 b.component('text2')['fg'] = (.9, .9, .1, 1)
                 b.component('text2')['font'] = self._font
 
+    def __on_new_item(self, item):
+        info(f'new {item}')
+        item_json = {}
+        _item = self.__new_items[item](
+            self.__context.world,
+            self.__context.plane_node,
+            self.__context.cb_inst,
+            self.__context.curr_bottom,
+            self.__context.repos,
+            item_json)
+        _item._Item__editing = True
+        self.__add_item(_item)
+        item_json['class'] = _item.__class__.__name__
+        item_json['position'] = list(_item._np.get_pos())
+        self.__json['items'] += [item_json]
+
     def __actually_close(self, arg):
         if arg:
             self._frm.destroy()
@@ -170,11 +224,11 @@ class SceneEditor(DirectObject):
         h.update(new_dict_str.encode())
         return h.hexdigest()[:12]
 
-    def __on_item_click_l(self, item):
+    def __on_item_click(self, item):
         if self.__inspector and self.__inspector.item == item: return
         if self.__inspector:
             self.__inspector.destroy()
-        self.__inspector = Inspector(item)
+        self.__inspector = Inspector(item, self.__items)
 
     def __on_inspector_destroy(self):
         self.__inspector = None
index dbd1e1819cb478c86892bf9d85582e14a58f9d13..e33c2dc8fed97292a3319f1df43ab41a0c427e17 100644 (file)
@@ -1,5 +1,5 @@
 from panda3d.bullet import BulletBoxShape
-from pmachines.items.item import Item
+from pmachines.items.item import Item, ItemStrategy
 
 
 class Box(Item):
@@ -11,7 +11,7 @@ class Box(Item):
         self.node.add_shape(BulletBoxShape((.5, .5, .5)))
 
 
-class HitStrategy:
+class HitStrategy(ItemStrategy):
 
     def __init__(self, hit_by, node, world):
         self._hit_by = hit_by
index 37e653268c9674703a809dbe542447ae1b16bfb6..3519801a410dde290d1a0b0d27c5510559af1684 100644 (file)
@@ -13,13 +13,16 @@ class Command:
         self.rot = rot
 
 
-class FixedStrategy:
+class ItemStrategy: pass
+
+
+class FixedStrategy(ItemStrategy):
 
     def win_condition(self):
         return True
 
 
-class StillStrategy:
+class StillStrategy(ItemStrategy):
 
     def __init__(self, np):
         self._np = np
@@ -218,7 +221,7 @@ class Item(DirectObject):
     def on_click_l(self, pos):
         if self._paused: return
         if self.__editing:
-            messenger.send('editor-item-click-l', [self])
+            messenger.send('editor-item-click', [self])
         self._start_drag_pos = pos, self._np.get_pos()
         loader.load_sfx('assets/audio/sfx/grab.ogg').play()
         if not self._instantiated:
@@ -245,6 +248,8 @@ class Item(DirectObject):
 
     def on_click_r(self, pos):
         if self._paused or not self._instantiated: return
+        if self.__editing:
+            messenger.send('editor-item-click', [self])
         self._prev_rot_info = pos, self._np.get_pos(), self._np.get_r()
         loader.load_sfx('assets/audio/sfx/grab.ogg').play()
 
@@ -374,7 +379,7 @@ class Item(DirectObject):
 
     @property
     def position(self):
-        return self._
+        return self._np.get_pos()
 
     @position.setter
     def position(self, val):
@@ -399,6 +404,32 @@ class Item(DirectObject):
         self._np.set_scale(val)
         self.json['model_scale'] = val
 
+    @property
+    def id(self):
+        if 'id' in self.json:
+            return self.json['id']
+        return None
+
+    @id.setter
+    def id(self, val):
+        self.json['id'] = val
+
+    @property
+    def strategy_json(self):
+        return self.json['strategy']
+
+    @strategy_json.setter
+    def strategy_json(self, val):
+        self.json['strategy'] = val
+
+    @property
+    def strategy_args_json(self):
+        return self.json['strategy_args']
+
+    @strategy_args_json.setter
+    def strategy_args_json(self, val):
+        self.json['strategy_args'] = val.split(' ')
+
     def destroy(self):
         self._np.remove_node()
         taskMgr.remove(self._box_tsk)
index 035ea0e80b27014676a4ca62e1ac0bf61a6d0750..612ddde590bef390ba682db700cfca1835faa281 100644 (file)
@@ -2,6 +2,7 @@ from os.path import exists
 from os import makedirs
 from logging import info
 from json import loads
+from collections import namedtuple
 from panda3d.core import AmbientLight, Texture, TextPropertiesManager, \
     TextNode, Spotlight, PerspectiveLens, BitMask32, NodePath
 from panda3d.bullet import BulletPlaneShape, BulletGhostNode
@@ -73,6 +74,7 @@ class Scene(DirectObject):
         self._scene_tsk = taskMgr.add(self.on_frame, 'on_frame')
         if auto_start_editor:
             self._set_editor()
+        self.accept('editor-inspector-delete', self.__on_inspector_delete)
 
     @classmethod
     def filename(cls, scene_name):
@@ -126,24 +128,7 @@ class Scene(DirectObject):
             if 'friction' in item:
                 args['friction'] = item['friction']
             self.items += [self.__code2class(item['class'])(**args)]
-        for item in self.json['fixed_items']:
-            args = {
-                'world': self._world,
-                'plane_node': self._mouse_plane_node,
-                'cb_inst': self.cb_inst,
-                'curr_bottom': self.current_bottom,
-                'repos': self.repos,
-                'json': item,
-                'mass': 0}
-            args['pos'] = tuple(item['position'])
-            if 'roll' in item:
-                args['r'] = item['roll']
-            if 'restitution' in item:
-                args['restitution'] = item['restitution']
-            if 'friction' in item:
-                args['friction'] = item['friction']
-            self.items += [self.__code2class(item['class'])(**args)]
-        for item in self.json['scene_items']:
+        for item in self.json['items']:
             args = {
                 'world': self._world,
                 'plane_node': self._mouse_plane_node,
@@ -160,6 +145,10 @@ class Scene(DirectObject):
                 args['r'] = item['roll']
             if 'model_scale' in item:
                 args['model_scale'] = item['model_scale']
+            if 'restitution' in item:
+                args['restitution'] = item['restitution']
+            if 'friction' in item:
+                args['friction'] = item['friction']
             self.items += [self.__code2class(item['class'])(**args)]
             if 'strategy' in item:
                 match item['strategy']:
@@ -794,5 +783,22 @@ class Scene(DirectObject):
         self._test_items += [NodePath(name)]
         self._test_items[-1].set_pos(pos[0], 0, pos[1])
 
+    def add_item(self, item):
+        self.items += [item]
+
     def _set_editor(self):
-        self.__scene_editor = SceneEditor(self.json, self.__json_name)
+        fields = ['world', 'plane_node', 'cb_inst', 'curr_bottom', 'repos', 'json']
+        SceneContext = namedtuple('SceneContext', fields)
+        context = SceneContext(
+            self._world,
+            self._mouse_plane_node,
+            self.cb_inst,
+            self.current_bottom,
+            self.repos,
+            {})
+        self.__scene_editor = SceneEditor(self.json, self.__json_name, context, self.add_item, self.items)
+
+    def __on_inspector_delete(self, item):
+        self.items.remove(item)
+        self.json['items'].remove(item.json)
+        item.destroy()
diff --git a/prj.org b/prj.org
index 4137669d08f928ea46642b8b8a3a29f5a1c8b002..d2734f55c4d81c636172c6113cd1fbeb214b1388 100644 (file)
--- a/prj.org
+++ b/prj.org
   - [X] friction (default: .5)
   - [X] expected number of contacts (default: 1)
   - [X] save modifications in the json file
-- [ ] new item
+- [X] new item
+  - [X] create the item
+  - [X] refactor: single list of items in the json
+  - [X] save the new item in the json
+  - [X] delete item
+  - [X] id
+  - [X] strategy and strategy_args
+  - [X] pop up if errors with arguments in strategy_args
 - [ ] new scene
 - [ ] start items
 - [ ] editing of test_items in the editor for functional tests