def test_set_get_custom(self, client_type): """ Spawn two objects and modify their custom fields, as well as set/query the custom field of a non-existing object. """ # Get the client for this test. client = self.clients[client_type] # Spawn two objects. id_1, id_2 = 1, 2 init = {'templateID': '_templateSphere'} assert client.spawn([init, init]) == (True, None, [id_1, id_2]) # Update the custom data for an existing- and a non-existing object. assert client.setCustomData({id_1: 'foo', 10: 'bar'}) == (True, None, [10]) # Query two existing- and one non-existing object. ret = client.getCustomData([id_1, id_2, 10]) assert ret.ok assert ret.data == ({id_1: 'foo', id_2: '', 10: None}) # Query all at once. assert client.getCustomData(None) == client.getCustomData([id_1, id_2])
def placeTarget(host, numTargets=1): """ Spawn ``numTargets`` in the scene. The targets visually oscillate in size. They also have no collision shapes and are thus unaffected by physics (ie they cannot collide with anything). """ # Connect to Azrael. client = azrael.client.Client(ip=host) # Spawn the target object from the 'BoosterCube_1' template (defined in # 'demo_boostercube' that must already be running at this point). init = [] for ii in range(numTargets): tmp = { 'templateID': 'BoosterCube_1', 'rbs': {'imass': 0, 'position': (0, 0, 3 * ii)} } init.append(tmp) ret = client.spawn(init) # Check for errors and abort if there are any. if not ret.ok: print(ret) sys.exit(1) # Extract the IDs of the spawned target objects. targetIDs = ret.data print('Spawned {} targets'.format(len(targetIDs))) del init, ret # Replace the collision shape with an empty one to disable the physics for # those targets. cs = types.CollShapeEmpty() cs = types.CollShapeMeta('empty', (0, 0, 0), (0, 0, 0, 1), cs) cmd = {targetID: {'cshapes': {'cssphere': cs}} for targetID in targetIDs} assert client.setRigidBodies(cmd).ok del cs # Tag the object with target. This is necessary because the # `PyConBrisbaneClient.selectNewTarget` method will use to distinguish # targets from other objects. cmd = {targetID: 'Target' for targetID in targetIDs} assert client.setCustomData(cmd) # Create a random phase offset in the oscillation pattern (pure eye candy # to avoid all targets scale synchronously). phi = 2 * np.pi * np.random.rand(len(targetIDs)) # Modify the scale of the target every 100ms. cnt = 0 while True: time.sleep(0.1) # Compile the payload for the update command, then send it to Azrael. # The fragment names (eg 'frag_1') are hard coded in the Template # (don't worry about them, just accept that they exist). cmd = {} for idx, targetID in enumerate(targetIDs): # Compute the new scale value. scale = 1 + np.sin(2 * np.pi * 0.1 * cnt + phi[idx]) scale *= 0.1 tmp = { 'frag_1': {'scale': scale}, 'frag_2': {'scale': scale}, } cmd[targetID] = tmp assert client.setFragments(cmd).ok # Randomly update the target's position every 10s. if (cnt % 100) == 0: cmd = {} for targetID in targetIDs: pos = 15 * np.random.rand(3) - 10 cmd[targetID] = {'position': pos.tolist()} assert client.setRigidBodies(cmd).ok cnt += 1
def spawnCubes(numCols, numRows, numLayers, center=(0, 0, 0)): """ Spawn multiple cubes in a regular grid. The number of cubes equals ``numCols`` * ``numRows`` * ``numLayers``. The center of this "prism" is at ``center``. Every cube has two boosters and two factories. The factories can themselves spawn more (purely passive) cubes. """ tID_cube = addTexturedCubeTemplates(numCols, numRows, numLayers) # Get a Client instance. client = azrael.client.Client() # ---------------------------------------------------------------------- # Spawn the differently textured cubes in a regular grid. # ---------------------------------------------------------------------- allObjs = [] cube_idx = 0 cube_spacing = 0.1 # Determine the template and position for every cube. The cubes are *not* # spawned in this loop, but afterwards. print("Compiling scene: ", end="", flush=True) t0 = time.time() for row in range(numRows): for col in range(numCols): for lay in range(numLayers): # Base position of cube. pos = np.array([col, row, lay], np.float64) # Add space in between cubes. pos *= -(2 + cube_spacing) # Correct the cube's position to ensure the center of the # grid coincides with the origin. pos[0] += (numCols // 2) * (1 + cube_spacing) pos[1] += (numRows // 2) * (1 + cube_spacing) pos[2] += (numLayers // 2) * (1 + cube_spacing) # Move the grid to position ``center``. pos += np.array(center) # Store the position and template for this cube. allObjs.append({"templateID": tID_cube[cube_idx], "rbs": {"position": pos.tolist()}}) cube_idx += 1 del pos print("{:,} objects ({:.1f}s)".format(len(allObjs), time.time() - t0)) del cube_idx, cube_spacing, row, col, lay # Spawn the cubes from the templates at the just determined positions. print("Spawning {} objects: ".format(len(allObjs)), end="", flush=True) t0 = time.time() ret = client.spawn(allObjs) if not ret.ok: print("** Error:") print(ret) assert False print(" {:.1f}s".format(time.time() - t0)) # Make 'frag_2' invisible by setting its scale to zero. for objID in ret.data: assert client.setFragments({objID: {"frag_2": {"scale": 0}}}).ok assert client.setCustomData({objID: "asteroid"}).ok