Пример #1
0
rects::ltrb<float> item_button::iterate_children_attachments(bool draw, std::vector<vertex_triangle>* target, augs::rgba border_col) {
	auto item_sprite = item->get<components::sprite>();

	const auto& gui_def = resource_manager.find(item_sprite.tex)->gui_sprite_def;

	item_sprite.flip_horizontally = gui_def.flip_horizontally;
	item_sprite.flip_vertically = gui_def.flip_vertically;
	item_sprite.rotation_offset = gui_def.rotation_offset;

	item_sprite.color.a = border_col.a;

	shared::state_for_drawing_renderable state;
	state.screen_space_mode = true;
	state.overridden_target_buffer = target;
	
	auto expanded_size = rc.get_size() - with_attachments_bbox.get_size();

	state.renderable_transform.pos = get_absolute_xy() - with_attachments_bbox.get_position() + expanded_size/2 + vec2(1, 1);

	rects::ltrb<float> button_bbox = item_sprite.get_aabb(components::transform(), true);

	if (!is_container_open) {
		for_each_descendant(item, [this, draw, &item_sprite, &state, &button_bbox](augs::entity_id desc) {
			if (desc == item)
				return;

			auto parent_slot = desc->get<components::item>().current_slot;

			if (parent_slot.should_item_inside_keep_physical_body(item)) {
				auto attachment_sprite = desc->get<components::sprite>();

				attachment_sprite.flip_horizontally = item_sprite.flip_horizontally;
				attachment_sprite.flip_vertically = item_sprite.flip_vertically;
				attachment_sprite.rotation_offset = item_sprite.rotation_offset;

				attachment_sprite.color.a = item_sprite.color.a;
				shared::state_for_drawing_renderable attachment_state = state;
				auto offset = parent_slot.sum_attachment_offsets_of_parents(desc) - item->get<components::item>().current_slot.sum_attachment_offsets_of_parents(item);
				
				if (attachment_sprite.flip_horizontally) {
					offset.pos.x = -offset.pos.x;
					offset.flip_rotation();
				}

				if (attachment_sprite.flip_vertically) {
					offset.pos.y = -offset.pos.y;
					offset.flip_rotation();
				}

				offset += item_sprite.size / 2;
				offset += -attachment_sprite.size / 2;

				attachment_state.renderable_transform += offset;

				if (draw)
					attachment_sprite.draw(attachment_state);

				rects::ltrb<float> attachment_bbox = attachment_sprite.get_aabb(offset, true);
				button_bbox.contain(attachment_bbox);
			}
		});
	}

	if(draw)
		item_sprite.draw(state);

	return button_bbox;
}
Пример #2
0
void perform_transfer(const item_slot_transfer_request r, logic_step& step) {
	auto& cosmos = r.get_item().get_cosmos();
	auto& item = r.get_item().get<components::item>();
	const auto previous_slot_id = item.current_slot;
	const auto previous_slot = cosmos[previous_slot_id];

	const auto result = query_transfer_result(r);

	const bool is_pickup_or_transfer = result.result == item_transfer_result_type::SUCCESSFUL_TRANSFER;
	const bool is_drop_request = result.result == item_transfer_result_type::SUCCESSFUL_DROP;

	if (result.result == item_transfer_result_type::UNMOUNT_BEFOREHAND) {
		ensure(false);
		ensure(previous_slot.alive());

		//item.request_unmount(r.get_target_slot());
		//item.mark_parent_enclosing_containers_for_unmount();

		return;
	}
	else if (is_pickup_or_transfer || is_drop_request) {
		components::transform previous_container_transform;

		entity_id target_item_to_stack_with;

		if (is_pickup_or_transfer) {
			for (auto& i : cosmos.get_handle(r.get_target_slot())->items_inside) {
				if (can_stack_entities(r.get_item(), cosmos[i])) {
					target_item_to_stack_with = i;
				}
			}
		}

		const bool whole_item_grabbed = item.charges == result.transferred_charges;

		if (previous_slot.alive()) {
			previous_container_transform = previous_slot.get_container().logic_transform();

			if (whole_item_grabbed) {
				remove_item(previous_slot, r.get_item());
			}

			if (previous_slot.is_input_enabling_slot()) {
				unset_input_flags_of_orphaned_entity(r.get_item());
			}
		}

		if (cosmos[target_item_to_stack_with].alive()) {
			if (whole_item_grabbed) {
				step.transient.messages.post(messages::queue_destruction(r.get_item()));
			}
			else {
				item.charges -= result.transferred_charges;
			}

			cosmos[target_item_to_stack_with].get<components::item>().charges += result.transferred_charges;

			return;
		}

		entity_id grabbed_item_part;

		if (whole_item_grabbed) {
			grabbed_item_part = r.get_item();
		}
		else {
			grabbed_item_part = cosmos.clone_entity(r.get_item());
			item.charges -= result.transferred_charges;
			cosmos[grabbed_item_part].get<components::item>().charges = result.transferred_charges;
		}

		const auto grabbed_item_part_handle = cosmos[grabbed_item_part];

		if (is_pickup_or_transfer) {
			add_item(r.get_target_slot(), grabbed_item_part_handle);
		}

		auto physics_updater = [previous_container_transform](const entity_handle descendant, ...) {
			const auto& cosmos = descendant.get_cosmos();

			const auto parent_slot = cosmos[descendant.get<components::item>().current_slot];
			auto def = descendant.get<components::fixtures>().get_data();
			entity_id owner_body;

			if (parent_slot.alive()) {
				def.activated = parent_slot.should_item_inside_keep_physical_body();
				
				if (def.activated) {
					owner_body = parent_slot.get_root_container();
					
					def.offsets_for_created_shapes[colliders_offset_type::ITEM_ATTACHMENT_DISPLACEMENT]
						= sum_attachment_offsets(cosmos, descendant.get_address_from_root());
				}
				else {
					owner_body = descendant;
				}

				def.offsets_for_created_shapes[colliders_offset_type::SPECIAL_MOVE_DISPLACEMENT].reset();
			}
			else {
				def.activated = true;
				owner_body = descendant;
				def.offsets_for_created_shapes[colliders_offset_type::ITEM_ATTACHMENT_DISPLACEMENT].reset();
				def.offsets_for_created_shapes[colliders_offset_type::SPECIAL_MOVE_DISPLACEMENT].reset();
			}

			descendant.get<components::fixtures>() = def;
			descendant.get<components::fixtures>().set_owner_body(owner_body);
			
			if (descendant.has<components::physics>()) {
				descendant.get<components::physics>().set_transform(previous_container_transform);

				if (descendant.has<components::interpolation>()) {
					descendant.get<components::interpolation>().place_of_birth = descendant.logic_transform();
				}
			}
		};

		physics_updater(grabbed_item_part_handle);
		grabbed_item_part_handle.for_each_contained_item_recursive(physics_updater);

		if (is_pickup_or_transfer) {
			initialize_item_button_for_new_gui_owner(grabbed_item_part_handle, inventory_traversal());
			grabbed_item_part_handle.for_each_contained_slot_and_item_recursive(initialize_slot_button_for_new_gui_owner, initialize_item_button_for_new_gui_owner);
		}

		const auto previous_capability = previous_slot.get_container().get_owning_transfer_capability();
		const auto target_capability = r.get_target_slot().get_container().get_owning_transfer_capability();

		if (target_capability.alive() && target_capability != previous_capability) {
			if (target_capability.has<components::gui_element>()) {
				components::gui_element::assign_item_to_first_free_hotbar_button(target_capability, grabbed_item_part_handle);
			}
		}
		
		auto& grabbed_item = grabbed_item_part_handle.get<components::item>();

		if (is_pickup_or_transfer) {
			if (r.get_target_slot()->items_need_mounting) {
				grabbed_item.intended_mounting = components::item::MOUNTED;

				if (r.force_immediate_mount) {
					grabbed_item.current_mounting = components::item::MOUNTED;
				}
			}
		}

		if (is_drop_request) {
			const auto force = vec2().set_from_degrees(previous_container_transform.rotation).set_length(60);
			const auto offset = vec2().random_on_circle(20, cosmos.get_rng_for(r.get_item()));

			auto& physics = grabbed_item_part_handle.get<components::physics>();
			physics.apply_force(force, offset, true);
			auto& special_physics = grabbed_item_part_handle.get<components::special_physics>();
			special_physics.since_dropped.set(200, cosmos.get_timestamp());
		}
	}
}