<commit_before>#include "stdafx.h"
#include "camera_system.h"

#include <gl\GL.h>
#include "entity_system/entity.h"
#include "../components/physics_component.h"
#include "../messages/intent_message.h"
#include "../resources/render_info.h"

void camera_system::consume_events(world& owner) {
	auto events = owner.get_message_queue<messages::intent_message>();

	for (auto it : events) {
		if (it.intent == messages::intent_message::intent_type::SWITCH_LOOK && it.state_flag) {
			auto& mode = it.subject->get<components::camera>().orbit_mode;
			if (mode == components::camera::LOOK)
				mode = components::camera::ANGLED;
			else mode = components::camera::LOOK;
		}
	}
}

void camera_system::process_entities(world& owner) {
	double delta = smooth_timer.extract<std::chrono::seconds>();

	/* we sort layers in reverse order to keep layer 0 as topmost and last layer on the bottom */
	std::sort(targets.begin(), targets.end(), [](entity* a, entity* b) {
		return a->get<components::camera>().layer > b->get<components::camera>().layer;
	});

	for (auto e : targets) {
		auto& camera = e->get<components::camera>();

		if (camera.enabled) {
			/* we obtain transform as a copy because we'll be now offsetting it by crosshair position */
			auto transform = e->get<components::transform>().current;

			/* if we set player and crosshair entity targets */
			if (camera.player && camera.crosshair) {
				/* skip calculations if no orbit_mode is specified */
				if (camera.orbit_mode != camera.NONE) {
					/* shortcuts */
					vec2<>& crosshair_pos = camera.crosshair->get<components::transform>().current.pos;
					vec2<> player_pos = camera.player->get<components::transform>().current.pos;
					vec2<> dir = (crosshair_pos - player_pos);

					dir.rotate(transform.rotation, vec2<>());

					if (camera.orbit_mode == camera.ANGLED) {
						vec2<> bound = camera.size / 2.f;
						/* save by copy */
						vec2<> normalized = dir.clamp(bound);
						transform.pos += normalized.normalize() * camera.angled_look_length;
					}

					if (camera.orbit_mode == camera.LOOK) {
						vec2<> bound = camera.max_look_expand + camera.size / 2.f;

						/* simple proportion in local frame of reference */
						vec2<> camera_offset = (dir.clamp(bound) / bound) * camera.max_look_expand;
						
						transform.pos += camera_offset.rotate(-transform.rotation, vec2<>());
					}
					
					/* rotate dir back */
					dir.rotate(-transform.rotation, vec2<>());
					/* update crosshair so it is snapped to visible area */
					crosshair_pos = player_pos + dir;
				}
			}

			auto drawn_transform = transform;
			auto drawn_size = camera.size;

			if (camera.enable_smoothing) {
				/* variable time step camera smoothing by averaging last position with the current */
				float averaging_constant = static_cast<float>(
					pow(camera.smoothing_average_factor, camera.averages_per_sec * delta)
					);
				
				if (camera.dont_smooth_once)
					averaging_constant = 0.f;

				//if ((transform.pos - camera.last_interpolant).length() < 2.0) camera.last_interpolant = transform.current.pos;
				//else
				camera.last_interpolant.pos = camera.last_interpolant.pos * averaging_constant + transform.pos * (1.0f - averaging_constant);
				camera.last_interpolant.rotation = camera.last_interpolant.rotation * averaging_constant + transform.rotation * (1.0f - averaging_constant);
					
				auto interp = [](float& a, float& b, float averaging_constant){
					a = static_cast<float>(a * averaging_constant + b * (1.0f - averaging_constant));
				};

				interp(camera.last_ortho_interpolant.x, camera.size.x, averaging_constant);
				interp(camera.last_ortho_interpolant.y, camera.size.y, averaging_constant);

				/* save smoothing result */
				//if ((drawn_transform.pos - camera.last_interpolant.pos).length() > 5)
				drawn_transform = camera.last_interpolant;
				
				drawn_size = camera.last_ortho_interpolant;

				if (camera.crosshair_follows_interpolant) {
					camera.crosshair->get<components::transform>().current.pos -= transform.pos - camera.last_interpolant.pos;
				}
			}
			
			camera.dont_smooth_once = false;

			/* save the final smoothing results in previous transform state and component, we'll use them later in the rendering pass */
			e->get<components::transform>().previous = drawn_transform;
			camera.rendered_size = drawn_size;
			camera.target_transform = transform;
		}
	}
}

void camera_system::process_rendering(world& owner) {
	render_system& raw_renderer = owner.get_system<render_system>();

	for (auto e : targets) {
		auto& camera = e->get<components::camera>();

		if (camera.enabled) {
			glViewport(camera.screen_rect.x, camera.screen_rect.y, camera.screen_rect.w, camera.screen_rect.h);
			
			auto drawn_transform = e->get<components::transform>().previous;

			resources::renderable::draw_input in;
			in.rotated_camera_aabb =
				rects::ltrb<float>::get_aabb_rotated(camera.rendered_size, drawn_transform.rotation) + drawn_transform.pos - camera.rendered_size / 2;
			in.camera_transform = drawn_transform;
			in.output = &raw_renderer;
			in.visible_area = camera.rendered_size;

			if (camera.drawing_callback) {
				try {
					/* arguments: subject, renderer, visible_area, target_transform, mask */<commit_msg>improved stability of everything rendered<commit_after>#include "stdafx.h"
#include "camera_system.h"

#include <gl\GL.h>
#include "entity_system/entity.h"
#include "../components/physics_component.h"
#include "../messages/intent_message.h"
#include "../resources/render_info.h"

void camera_system::consume_events(world& owner) {
	auto events = owner.get_message_queue<messages::intent_message>();

	for (auto it : events) {
		if (it.intent == messages::intent_message::intent_type::SWITCH_LOOK && it.state_flag) {
			auto& mode = it.subject->get<components::camera>().orbit_mode;
			if (mode == components::camera::LOOK)
				mode = components::camera::ANGLED;
			else mode = components::camera::LOOK;
		}
	}
}

void camera_system::process_entities(world& owner) {
	double delta = smooth_timer.extract<std::chrono::seconds>();

	/* we sort layers in reverse order to keep layer 0 as topmost and last layer on the bottom */
	std::sort(targets.begin(), targets.end(), [](entity* a, entity* b) {
		return a->get<components::camera>().layer > b->get<components::camera>().layer;
	});

	for (auto e : targets) {
		auto& camera = e->get<components::camera>();

		if (camera.enabled) {
			/* we obtain transform as a copy because we'll be now offsetting it by crosshair position */
			auto transform = e->get<components::transform>().current;

			/* if we set player and crosshair entity targets */
			if (camera.player && camera.crosshair) {
				/* skip calculations if no orbit_mode is specified */
				if (camera.orbit_mode != camera.NONE) {
					/* shortcuts */
					vec2<>& crosshair_pos = camera.crosshair->get<components::transform>().current.pos;
					vec2<> player_pos = camera.player->get<components::transform>().current.pos;
					vec2<> dir = (crosshair_pos - player_pos);

					dir.rotate(transform.rotation, vec2<>());

					if (camera.orbit_mode == camera.ANGLED) {
						vec2<> bound = camera.size / 2.f;
						/* save by copy */
						vec2<> normalized = dir.clamp(bound);
						transform.pos += normalized.normalize() * camera.angled_look_length;
					}

					if (camera.orbit_mode == camera.LOOK) {
						vec2<> bound = camera.max_look_expand + camera.size / 2.f;

						/* simple proportion in local frame of reference */
						vec2<> camera_offset = (dir.clamp(bound) / bound) * camera.max_look_expand;
						
						transform.pos += camera_offset.rotate(-transform.rotation, vec2<>());
					}
					
					/* rotate dir back */
					dir.rotate(-transform.rotation, vec2<>());
					/* update crosshair so it is snapped to visible area */
					crosshair_pos = player_pos + dir;
				}
			}

			auto drawn_transform = transform;
			auto drawn_size = camera.size;

			if (camera.enable_smoothing) {
				/* variable time step camera smoothing by averaging last position with the current */
				float averaging_constant = static_cast<float>(
					pow(camera.smoothing_average_factor, camera.averages_per_sec * delta)
					);
				
				if (camera.dont_smooth_once)
					averaging_constant = 0.f;

				//if ((transform.pos - camera.last_interpolant).length() < 2.0) camera.last_interpolant = transform.current.pos;
				//else
				camera.last_interpolant.pos = camera.last_interpolant.pos * averaging_constant + transform.pos * (1.0f - averaging_constant);
				camera.last_interpolant.rotation = camera.last_interpolant.rotation * averaging_constant + transform.rotation * (1.0f - averaging_constant);
					
				auto interp = [](float& a, float& b, float averaging_constant){
					a = static_cast<float>(a * averaging_constant + b * (1.0f - averaging_constant));
				};

				interp(camera.last_ortho_interpolant.x, camera.size.x, averaging_constant);
				interp(camera.last_ortho_interpolant.y, camera.size.y, averaging_constant);

				/* save smoothing result */
				//if ((drawn_transform.pos - camera.last_interpolant.pos).length() > 5)
				drawn_transform = camera.last_interpolant;
				
				drawn_size = camera.last_ortho_interpolant;

				if (camera.crosshair_follows_interpolant) {
					camera.crosshair->get<components::transform>().current.pos -= transform.pos - camera.last_interpolant.pos;
				}
			}
			
2			drawn_transform.pos = vec2<int>(drawn_transform.pos);
			drawn_size = vec2<int>(drawn_size);

			camera.dont_smooth_once = false;

			/* save the final smoothing results in previous transform state and component, we'll use them later in the rendering pass */
			e->get<components::transform>().previous = drawn_transform;
			camera.rendered_size = drawn_size;
			camera.target_transform = transform;
		}
	}
}

void camera_system::process_rendering(world& owner) {
	render_system& raw_renderer = owner.get_system<render_system>();

	for (auto e : targets) {
		auto& camera = e->get<components::camera>();

		if (camera.enabled) {
			glViewport(camera.screen_rect.x, camera.screen_rect.y, camera.screen_rect.w, camera.screen_rect.h);
			
			auto drawn_transform = e->get<components::transform>().previous;

			resources::renderable::draw_input in;
			in.rotated_camera_aabb =
				rects::ltrb<float>::get_aabb_rotated(camera.rendered_size, drawn_transform.rotation) + drawn_transform.pos - camera.rendered_size / 2;
			in.camera_transform = drawn_transform;
			in.output = &raw_renderer;
			in.visible_area = camera.rendered_size;

			if (camera.drawing_callback) {
				try {
					/* arguments: subject, renderer, visible_area, target_transform, mask */
{'fraction_non_alphanumeric': 0.13317008852891316, 'fraction_numerical': 0.004803164437747222, 'mean_word_length': 3.8845446182152714, 'pattern_counts': {'":': 0, '<': 63, '<?xml version=': 0, '>': 87, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5818115', 'n_tokens_mistral': 3981, 'n_tokens_neox': 3265, 'n_words': 701}