def select_unclick(self): # clicks on UI are consumed and flag world to not accept unclicks # (keeps unclicks after dialog dismiss from deselecting objects) if self.last_click_on_ui: self.last_click_on_ui = False return # if we're clicking to spawn something, don't drag/select if self.classname_to_spawn: return x, y, z = vector.screen_to_world(self.app, self.app.mouse_x, self.app.mouse_y) # remember selected objects now, they might be deselected but still # need to have their collision turned back on. selected_objects = self.selected_objects[:] if len(self.selected_objects) > 0 and not self.app.il.shift_pressed: # if mouse has traveled much since click, deselect all objects # except one mouse is over. dx = self.last_mouse_click_x - x dy = self.last_mouse_click_y - y if math.sqrt(dx**2 + dy**2) < 1.5: for obj in self.get_objects_at(x, y): if obj in self.selected_objects: self.deselect_all() self.select_object(obj) break # end drag, forget drag object offsets self.drag_objects.clear() for obj in selected_objects: obj.enable_collision() if obj.collision_shape_type == collision.CST_TILE: obj.collision.create_shapes() obj.collision.update()
def mouse_wheeled(self, wheel_y): x, y, z = vector.screen_to_world(self.app, self.app.mouse_x, self.app.mouse_y) objects = self.get_objects_at(x, y, allow_locked=True) for obj in objects: if obj.handle_mouse_events and \ (not obj.locked or not self.app.can_edit): obj.mouse_wheeled(wheel_y) if obj.consume_mouse_events: break
def unclicked(self, button): if self.app.ui.is_game_edit_ui_visible(): if button == sdl2.SDL_BUTTON_LEFT: self.select_unclick() else: x, y, z = vector.screen_to_world(self.app, self.app.mouse_x, self.app.mouse_y) objects = self.get_objects_at(x, y) for obj in objects: if obj.handle_mouse_events: obj.unclicked(button, x, y)
def clicked(self, button): # if edit UI is up, select stuff if self.app.ui.is_game_edit_ui_visible(): if button == sdl2.SDL_BUTTON_LEFT: self.select_click() # else pass clicks to any objects under mouse else: x, y, z = vector.screen_to_world(self.app, self.app.mouse_x, self.app.mouse_y) # 'locked" only relevant to edit mode, ignore it if in play mode objects = self.get_objects_at(x, y, allow_locked=True) for obj in objects: if obj.handle_mouse_events and \ (not obj.locked or not self.app.can_edit): obj.clicked(button, x, y) if obj.consume_mouse_events: break
def check_hovers(self): "Update objects on their mouse hover status" x, y, z = vector.screen_to_world(self.app, self.app.mouse_x, self.app.mouse_y) new_hovers = self.get_objects_at(x, y) # if this object will be selected on left click; draw bounds & label if self.app.ui.is_game_edit_ui_visible(): next_obj = self.pick_next_object_at(x, y) self.hovered_focus_object = next_obj # if in play mode, notify objects who have begun to be hovered else: for obj in new_hovers: if obj.handle_mouse_events and not obj in self.hovered_objects: obj.hovered(x, y) # check for objects un-hovered by this move for obj in self.hovered_objects: if obj.handle_mouse_events and not obj in new_hovers: obj.unhovered(x, y) self.hovered_objects = new_hovers
def mouse_moved(self, dx, dy): if self.app.ui.active_dialog: return # bail if mouse didn't move (in world space - include camera) last input if self.app.mouse_dx == 0 and self.app.mouse_dy == 0 and \ not self.camera.moved_this_frame: return # if last onclick was a UI element, don't drag if self.last_click_on_ui: return self.check_hovers() # not dragging anything? if len(self.selected_objects) == 0: return # 0-length drags cause unwanted snapping if dx == 0 and dy == 0: return # set dragged objects to mouse + offset from mouse when drag started x, y, z = vector.screen_to_world(self.app, self.app.mouse_x, self.app.mouse_y) for obj_name, offset in self.drag_objects.items(): obj = self.objects[obj_name] if obj.locked: continue obj.disable_collision() obj.x = x + offset[0] obj.y = y + offset[1] obj.z = z + offset[2] if self.object_grid_snap: obj.x = round(obj.x) obj.y = round(obj.y) # if odd width/height, origin will be between quads and # edges will be off-grid; nudge so that edges are on-grid if obj.art.width % 2 != 0: obj.x += obj.art.quad_width / 2 if obj.art.height % 2 != 0: obj.y += obj.art.quad_height / 2
def select_click(self): x, y, z = vector.screen_to_world(self.app, self.app.mouse_x, self.app.mouse_y) # remember last place we clicked self.last_mouse_click_x, self.last_mouse_click_y = x, y if self.classname_to_spawn: new_obj = self.spawn_object_of_class(self.classname_to_spawn, x, y) if self.current_room: self.current_room.add_object(new_obj) self.app.ui.message_line.post_line('Spawned %s' % new_obj.name) return objects = self.get_objects_at(x, y) next_obj = self.pick_next_object_at(x, y) if len(objects) == 0: self.deselect_all() # ctrl: unselect first selected object found under mouse elif self.app.il.ctrl_pressed: for obj in self.selected_objects: if obj in objects: self.deselect_object(obj) break # shift: add to current selection elif self.app.il.shift_pressed: self.select_object(next_obj) # no mod keys: select only object under cursor, deselect all if none elif not next_obj and len(objects) == 0: self.deselect_all() # special case: must use shift-click for objects # beneath (lower Z) topmost elif next_obj is not objects[0]: pass else: self.select_object(next_obj) # remember object offsets from cursor for dragging for obj in self.selected_objects: self.drag_objects[obj.name] = (obj.x - x, obj.y - y, obj.z - z)
def reposition_from_mouse(self): self.x, self.y, _ = vector.screen_to_world(self.app, self.app.mouse_x, self.app.mouse_y)