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": "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": "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": "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": "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": "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,
       "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": "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": "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": "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": "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": "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": "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",
       "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": "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": "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": "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": "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",
       "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": "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": "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": "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": "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": "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": "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": "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": "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": "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,
       "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,
       "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": "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": "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": "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": "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": "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": "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,
       "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,
       "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": "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": "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": "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]
     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()
             scene.screenshot()
             scene.destroy()
             exit()
index fb1aeb65ab98a074f7bfb38af68c0ea46b5bdbc6..b5440a0cb9be91fab04d8ba23b13af88ec10c67a 100644 (file)
@@ -1,17 +1,25 @@
 from collections import namedtuple
 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 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 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):
 
 
 
 class Inspector(DirectObject):
 
-    def __init__(self, item):
+    def __init__(self, item, all_items):
         super().__init__()
         self.__item = item
         super().__init__()
         self.__item = item
+        self.__all_items = all_items
         self._font = base.loader.load_font(
             'assets/fonts/Hanken-Book.ttf')
         self._font.clear()
         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')}
                 '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,
         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
         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)
         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)
         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': [
         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)
             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
 
     def __add_row(self, label, text, callback):
         tw = 10
@@ -95,6 +122,47 @@ class Inspector(DirectObject):
         self.__z -= .1
         return t, e
 
         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)
     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)))
         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):
 
     @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_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')
     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 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
 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 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):
 
 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__()
         super().__init__()
+        self.__items = items
         self.__json = json
         self.__json_name = json_name
         self.__inspector = None
         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()
         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'))
             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')
         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):
         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
 
                 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()
     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]
 
         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()
         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
 
     def __on_inspector_destroy(self):
         self.__inspector = None
index dbd1e1819cb478c86892bf9d85582e14a58f9d13..e33c2dc8fed97292a3319f1df43ab41a0c427e17 100644 (file)
@@ -1,5 +1,5 @@
 from panda3d.bullet import BulletBoxShape
 from panda3d.bullet import BulletBoxShape
-from pmachines.items.item import Item
+from pmachines.items.item import Item, ItemStrategy
 
 
 class Box(Item):
 
 
 class Box(Item):
@@ -11,7 +11,7 @@ class Box(Item):
         self.node.add_shape(BulletBoxShape((.5, .5, .5)))
 
 
         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
 
     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
 
 
         self.rot = rot
 
 
-class FixedStrategy:
+class ItemStrategy: pass
+
+
+class FixedStrategy(ItemStrategy):
 
     def win_condition(self):
         return True
 
 
 
     def win_condition(self):
         return True
 
 
-class StillStrategy:
+class StillStrategy(ItemStrategy):
 
     def __init__(self, np):
         self._np = np
 
     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:
     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:
         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
 
     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()
 
         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):
 
     @property
     def position(self):
-        return self._
+        return self._np.get_pos()
 
     @position.setter
     def position(self, val):
 
     @position.setter
     def position(self, val):
@@ -399,6 +404,32 @@ class Item(DirectObject):
         self._np.set_scale(val)
         self.json['model_scale'] = val
 
         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)
     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 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
 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._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):
 
     @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)]
             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,
             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']
                 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']:
             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])
 
         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):
     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
   - [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
 - [ ] new scene
 - [ ] start items
 - [ ] editing of test_items in the editor for functional tests