Scene loading/saving improvements, transform gizmo, entity creation

This commit is contained in:
2024-10-19 19:45:04 +02:00
parent fae8ea7cba
commit 3d98ba0023
15 changed files with 985 additions and 460 deletions

View File

@@ -55,6 +55,8 @@ Transform_Gizmo :: struct {
color_forward_buffer: Buffer_Handle;
color_right_buffer: Buffer_Handle;
pipeline: Pipeline_State_Handle;
uniform_gizmo_scale: float;
}
@@ -69,312 +71,610 @@ Editor :: struct {
last_right_mouse_click_time: float;
menu_position: Vector2;
icons : struct {
play: Texture_Handle;
stop: Texture_Handle;
}
}
init_editor :: () {
aspect_ratio := cast(float)engine.renderer.render_target_width / cast(float)engine.renderer.render_target_height;
engine.editor.camera = create_perspective_camera(.{0, 10, -10}, yaw=0, pitch=-40, roll=0.0, fov=40, aspect=aspect_ratio);
init_transform_gizmo();
engine.editor.icons.play = create_texture(engine.renderer, "../modules/Coven/assets/textures/ui_icons/play.png", false);
engine.editor.icons.stop = create_texture(engine.renderer, "../modules/Coven/assets/textures/ui_icons/stop.png", false);
}
init_transform_gizmo :: () {
gizmo : Transform_Gizmo;
gizmo.selected_axis = .NONE;
gizmo.transform = create_identity_transform();
gizmo.center_model_buffer = create_constant_buffer(engine.renderer, null, size_of(Matrix4), mappable=true);
gizmo.up_model_buffer = create_constant_buffer(engine.renderer, null, size_of(Matrix4), mappable=true);
gizmo.forward_model_buffer = create_constant_buffer(engine.renderer, null, size_of(Matrix4), mappable=true);
gizmo.right_model_buffer = create_constant_buffer(engine.renderer, null, size_of(Matrix4), mappable=true);
gizmo.color_center = Color.{1,1,1,1};
gizmo.color_up = Color.{0,1,0,1};
gizmo.color_forward = Color.{0,0,1,1};
gizmo.color_right = Color.{1,0,0,1};
gizmo.color_center_buffer = create_constant_buffer(engine.renderer, *gizmo.color_center, size_of(Vector4), mappable=true);
gizmo.color_up_buffer = create_constant_buffer(engine.renderer, *gizmo.color_up, size_of(Vector4), mappable=true);
gizmo.color_forward_buffer = create_constant_buffer(engine.renderer, *gizmo.color_forward, size_of(Vector4), mappable=true);
gizmo.color_right_buffer = create_constant_buffer(engine.renderer, *gizmo.color_right, size_of(Vector4), mappable=true);
engine.editor.transform_gizmo = gizmo;
// Transform gizmo shader
{
vs := create_vertex_shader_from_source(engine.renderer, TRANSFORM_GIZMO_SHADER, "VS", mesh_data_types = .[.POSITION]);
ps := create_pixel_shader_from_source(engine.renderer, TRANSFORM_GIZMO_SHADER, "PS");
engine.editor.transform_gizmo.pipeline = create_pipeline_state2(engine.renderer, vs, ps, blend_type=.OPAQUE);
}
}
update_transform_gizmo :: (ray: Ray, mouse_position: Vector2) -> bool {
return false;
// selected_entity := engine.editor.selected_entity;
//
// if key_down(.TAB) {
// if engine.editor.transform_gizmo.space == {
// case .WORLD;
// engine.editor.transform_gizmo.space = .LOCAL;
// case .LOCAL;
// engine.editor.transform_gizmo.space = .WORLD;
// }
// }
//
// if engine.editor.transform_gizmo.space == {
// case .WORLD;
// set_rotation(*engine.editor.transform_gizmo.transform, .{0,0,0,1});
// case .LOCAL;
// set_rotation(*engine.editor.transform_gizmo.transform, selected_entity.transform.orientation);
// }
//
// if engine.editor.transform_gizmo.transform_type == {
// case .TRANSLATION;
// if !key_pressed(.MOUSE_LEFT) {
// selected_axis, t := intersect_translation_gizmo(ray);
// engine.editor.transform_gizmo.selected_axis = selected_axis;
// } else if engine.editor.transform_gizmo.can_use && engine.editor.transform_gizmo.selected_axis != .NONE {
// first_update := key_down(.MOUSE_LEFT);
//
// if first_update {
// engine.editor.transform_gizmo.actual_entity_position = selected_entity.transform.position;
// }
//
// // Move the currently selected entity along the selected axis
// axis_vec : Vector3;
//
// if engine.editor.transform_gizmo.selected_axis == {
// case .UP;
// axis_vec.y = 1;
// case .FORWARD;
// axis_vec.z = 1;
// case .RIGHT;
// axis_vec.x = 1;
// }
//
// r1 : Ray;
// r1.origin = selected_entity.transform.position;
// r1.direction = rotate(axis_vec, engine.editor.transform_gizmo.transform.orientation);
//
// r2 := normalized_screen_to_ray_v2(*engine.editor.camera, mouse_position);
//
// d, t1, t2 := closest_distance_between_rays(r1, r2);
//
// new_position := r1.origin + r1.direction * t1;
//
// if first_update {
// engine.editor.transform_gizmo.first_hit_position = new_position;
// }
//
// position_change := new_position - engine.editor.transform_gizmo.first_hit_position;
//
// entity_position := engine.editor.transform_gizmo.actual_entity_position + position_change;
//
// if selected_entity.flags & Entity_Flags.SNAP_TO_GRID {
// entity_position.x -= fmod_cycling(entity_position.x - selected_entity.snap_offset.x, selected_entity.snap_intervals.x);// + selected_entity.snap_offset.x;
// entity_position.y -= fmod_cycling(entity_position.y - selected_entity.snap_offset.y, selected_entity.snap_intervals.y);// + selected_entity.snap_offset.y;
// entity_position.z -= fmod_cycling(entity_position.z - selected_entity.snap_offset.z, selected_entity.snap_intervals.z);// + selected_entity.snap_offset.z;
// }
//
// selected_entity.transform.position = entity_position;
// set_position(*engine.editor.transform_gizmo.transform, entity_position);
// }
//
// color_up := engine.editor.transform_gizmo.color_up;
// color_forward := engine.editor.transform_gizmo.color_forward;
// color_right := engine.editor.transform_gizmo.color_right;
//
// if engine.editor.transform_gizmo.selected_axis == {
// case .NONE;
// case .UP;
// color_up = Color.{1,1,0,1};
// case .FORWARD;
// color_forward = Color.{1,1,0,1};
// case .RIGHT;
// color_right = Color.{1,1,0,1};
// }
//
// upload_data_to_buffer(engine.renderer, engine.editor.transform_gizmo.color_up_buffer, *color_up, size_of(Color));
// upload_data_to_buffer(engine.renderer, engine.editor.transform_gizmo.color_forward_buffer, *color_forward, size_of(Color));
// upload_data_to_buffer(engine.renderer, engine.editor.transform_gizmo.color_right_buffer, *color_right, size_of(Color));
// case .ROTATION;
// selected_entity := engine.editor.selected_entity;
//
// if !engine.editor.transform_gizmo.clicked {
// selected_axis, point := intersect_rotation_gizmo(ray);
// engine.editor.transform_gizmo.selected_axis = selected_axis;
//
// if engine.editor.transform_gizmo.selected_axis != .NONE && key_down(.MOUSE_LEFT) {
// engine.editor.transform_gizmo.clicked = true;
// engine.editor.transform_gizmo.last_circle_dir = normalize(point - selected_entity.transform.position);
// }
// } else if !key_pressed(.MOUSE_LEFT) {
// engine.editor.transform_gizmo.clicked = false;
// } else {
// direction : Vector3;
// if engine.editor.transform_gizmo.selected_axis == {
// case .UP;
// direction = .{0,1,0};
// case .FORWARD;
// direction = .{0,0,1};
// case .RIGHT;
// direction = .{1,0,0};
// }
// direction = rotate(direction, engine.editor.transform_gizmo.transform.orientation);
//
// // Find the rotation
// circle : Circle;
// circle.radius = engine.editor.transform_gizmo.uniform_gizmo_scale;
// circle.center = selected_entity.transform.position;
// circle.orientation = direction;
//
// distance, point := closest_distance_ray_circle(ray, circle);
// new_dir := normalize(point - selected_entity.transform.position);
//
// dotp := dot(engine.editor.transform_gizmo.last_circle_dir, new_dir);
// angle := acos(clamp(dotp, -1.0, 1.0));
// cp := cross(engine.editor.transform_gizmo.last_circle_dir, new_dir);
//
// if dot(direction, cp) < 0 {
// angle *= -1.0;
// }
//
// q : Quaternion;
// set_from_axis_and_angle(*q, direction, angle);
//
// selected_entity.transform.orientation = q * selected_entity.transform.orientation;
// update_matrix(*selected_entity.transform);
//
// set_rotation(*engine.editor.transform_gizmo.transform, selected_entity.transform.orientation);
//
// engine.editor.transform_gizmo.last_circle_dir = new_dir;
// }
//
// color_up := engine.editor.transform_gizmo.color_up;
// color_forward := engine.editor.transform_gizmo.color_forward;
// color_right := engine.editor.transform_gizmo.color_right;
//
// if engine.editor.transform_gizmo.selected_axis == {
// case .NONE;
// case .UP;
// color_up = Color.{1,1,0,1};
// case .FORWARD;
// color_forward = Color.{1,1,0,1};
// case .RIGHT;
// color_right = Color.{1,1,0,1};
// }
//
// upload_data_to_buffer(engine.renderer, engine.editor.transform_gizmo.color_up_buffer, *color_up, size_of(Color));
// upload_data_to_buffer(engine.renderer, engine.editor.transform_gizmo.color_forward_buffer, *color_forward, size_of(Color));
// upload_data_to_buffer(engine.renderer, engine.editor.transform_gizmo.color_right_buffer, *color_right, size_of(Color));
// case .SCALE;
// if !key_pressed(.MOUSE_LEFT) {
// selected_axis, t := intersect_scale_gizmo(ray);
// engine.editor.transform_gizmo.selected_axis = selected_axis;
// } else if engine.editor.transform_gizmo.selected_axis != .NONE {
// selected_entity := engine.editor.selected_entity;
// first_update := key_down(.MOUSE_LEFT);
//
// if first_update {
// engine.editor.transform_gizmo.actual_entity_position = selected_entity.transform.position;
// engine.editor.transform_gizmo.actual_entity_scale = selected_entity.transform.scale;
// }
//
// // Move the currently selected entity along the selected axis
// axis_vec : Vector3;
//
// if engine.editor.transform_gizmo.selected_axis == {
// case .UP;
// axis_vec.y = 1;
// case .FORWARD;
// axis_vec.z = -1;
// case .RIGHT;
// axis_vec.x = 1;
// case .CENTER; axis_vec = .{1,1,1};
// }
//
// r1 : Ray;
// r1.origin = selected_entity.transform.position;
// r1.direction = rotate(axis_vec, engine.editor.transform_gizmo.transform.orientation);
// // Shoot a ray from screen to world
// mouse_position : Vector2;
// mouse_position.x = xx engine.engine.input.mouse.x;
// mouse_position.y = xx engine.engine.input.mouse.y;
//
// screen_size : Vector2;
// screen_size.x = cast(float)engine.engine.window.width;
// screen_size.y = cast(float)engine.engine.window.height;
//
// r2 := screen_to_ray_v2(*engine.editor.camera, mouse_position, screen_size);
//
// d, t1, t2 := closest_distance_between_rays(r1, r2);
// new_position := r1.origin + r1.direction * t1;
//
// if first_update {
// engine.editor.transform_gizmo.first_hit_position = new_position;
// }
//
// position_change := new_position - engine.editor.transform_gizmo.first_hit_position;
// scale_speed := ifx key_pressed(.SHIFT) then 4.0 else 1.0;
//
// if selected_entity.uses_uniform_scale {
// current_scale := selected_entity.transform.scale;
//
// if engine.editor.transform_gizmo.selected_axis == {
// case .UP; {
// current_scale.y = engine.editor.transform_gizmo.actual_entity_scale.y + position_change.y * scale_speed;
// position_change.x = 0;
// position_change.z = 0;
// }
// case .FORWARD; {
// current_scale.z = engine.editor.transform_gizmo.actual_entity_scale.z + position_change.z * scale_speed;
// position_change.x = 0;
// position_change.y = 0;
// }
// case .RIGHT; {
// current_scale.x = engine.editor.transform_gizmo.actual_entity_scale.x + position_change.x * scale_speed;
// position_change.y = 0;
// position_change.z = 0;
// }
// case .CENTER; {
// current_scale.x = engine.editor.transform_gizmo.actual_entity_scale.x + position_change.x * scale_speed;
// current_scale.y = current_scale.x; // @Incomplete: This is most definitely wrong!
// current_scale.z = current_scale.x;
//
// position_change.y = 0;
// position_change.z = 0;
// }
// }
//
// set_scale(*selected_entity.transform, current_scale);
//
// } else {
// if engine.editor.transform_gizmo.selected_axis == {
// case .UP;
// position_change.x = 0;
// position_change.z = 0;
// case .FORWARD;
// position_change.x = 0;
// position_change.y = 0;
// case .RIGHT;
// position_change.y = 0;
// position_change.z = 0;
// }
//
// entity_scale := engine.editor.transform_gizmo.actual_entity_scale + position_change * scale_speed;
// set_scale(*selected_entity.transform, entity_scale);
// }
// }
//
// color_up := engine.editor.transform_gizmo.color_up;
// color_forward := engine.editor.transform_gizmo.color_forward;
// color_right := engine.editor.transform_gizmo.color_right;
// color_center := Color.{1,1,1,1};
//
// if engine.editor.transform_gizmo.selected_axis == {
// case .NONE;
// case .UP;
// color_up = Color.{1,1,0,1};
// case .FORWARD;
// color_forward = Color.{1,1,0,1};
// case .RIGHT;
// color_right = Color.{1,1,0,1};
// case .CENTER;
// color_center = Color.{1,1,0,1};
// }
//
// upload_data_to_buffer(engine.renderer, engine.editor.transform_gizmo.color_center_buffer, *color_center, size_of(Color));
// upload_data_to_buffer(engine.renderer, engine.editor.transform_gizmo.color_up_buffer, *color_up, size_of(Color));
// upload_data_to_buffer(engine.renderer, engine.editor.transform_gizmo.color_forward_buffer, *color_forward, size_of(Color));
// upload_data_to_buffer(engine.renderer, engine.editor.transform_gizmo.color_right_buffer, *color_right, size_of(Color));
// }
//
// return engine.editor.transform_gizmo.selected_axis != .NONE;
if engine.editor.selected_entities.count != 1 return false;
selected_entity := engine.editor.selected_entities[0];
if key_down(.TAB) {
if engine.editor.transform_gizmo.space == {
case .WORLD;
engine.editor.transform_gizmo.space = .LOCAL;
case .LOCAL;
engine.editor.transform_gizmo.space = .WORLD;
}
}
if engine.editor.transform_gizmo.space == {
case .WORLD;
set_rotation(*engine.editor.transform_gizmo.transform, .{0,0,0,1});
case .LOCAL;
set_rotation(*engine.editor.transform_gizmo.transform, selected_entity.transform.orientation);
}
if engine.editor.transform_gizmo.transform_type == {
case .TRANSLATION;
if !key_pressed(.MOUSE_LEFT) {
selected_axis, t := intersect_translation_gizmo(ray);
engine.editor.transform_gizmo.selected_axis = selected_axis;
} else if engine.editor.transform_gizmo.can_use && engine.editor.transform_gizmo.selected_axis != .NONE {
first_update := key_down(.MOUSE_LEFT);
if first_update {
engine.editor.transform_gizmo.actual_entity_position = selected_entity.transform.position;
}
// Move the currently selected entity along the selected axis
axis_vec : Vector3;
if engine.editor.transform_gizmo.selected_axis == {
case .UP;
axis_vec.y = 1;
case .FORWARD;
axis_vec.z = 1;
case .RIGHT;
axis_vec.x = 1;
}
r1 : Ray;
r1.origin = selected_entity.transform.position;
r1.direction = rotate(axis_vec, engine.editor.transform_gizmo.transform.orientation);
r2 := normalized_screen_to_ray_v2(*engine.editor.camera, mouse_position);
d, t1, t2 := closest_distance_between_rays(r1, r2);
new_position := r1.origin + r1.direction * t1;
if first_update {
engine.editor.transform_gizmo.first_hit_position = new_position;
}
position_change := new_position - engine.editor.transform_gizmo.first_hit_position;
entity_position := engine.editor.transform_gizmo.actual_entity_position + position_change;
if selected_entity.flags & Entity_Flags.SNAP_TO_GRID {
entity_position.x -= fmod_cycling(entity_position.x - selected_entity.snap_offset.x, selected_entity.snap_intervals.x);// + selected_entity.snap_offset.x;
entity_position.y -= fmod_cycling(entity_position.y - selected_entity.snap_offset.y, selected_entity.snap_intervals.y);// + selected_entity.snap_offset.y;
entity_position.z -= fmod_cycling(entity_position.z - selected_entity.snap_offset.z, selected_entity.snap_intervals.z);// + selected_entity.snap_offset.z;
}
selected_entity.transform.position = entity_position;
selected_entity.transform.dirty = true;
set_position(*engine.editor.transform_gizmo.transform, entity_position);
}
color_up := engine.editor.transform_gizmo.color_up;
color_forward := engine.editor.transform_gizmo.color_forward;
color_right := engine.editor.transform_gizmo.color_right;
if engine.editor.transform_gizmo.selected_axis == {
case .NONE;
case .UP;
color_up = Color.{1,1,0,1};
case .FORWARD;
color_forward = Color.{1,1,0,1};
case .RIGHT;
color_right = Color.{1,1,0,1};
}
upload_data_to_buffer(engine.renderer, engine.editor.transform_gizmo.color_up_buffer, *color_up, size_of(Color));
upload_data_to_buffer(engine.renderer, engine.editor.transform_gizmo.color_forward_buffer, *color_forward, size_of(Color));
upload_data_to_buffer(engine.renderer, engine.editor.transform_gizmo.color_right_buffer, *color_right, size_of(Color));
case .ROTATION;
selected_entity := engine.editor.selected_entities[0];
if !engine.editor.transform_gizmo.clicked {
selected_axis, point := intersect_rotation_gizmo(ray);
engine.editor.transform_gizmo.selected_axis = selected_axis;
if engine.editor.transform_gizmo.selected_axis != .NONE && key_down(.MOUSE_LEFT) {
engine.editor.transform_gizmo.clicked = true;
engine.editor.transform_gizmo.last_circle_dir = normalize(point - selected_entity.transform.position);
}
} else if !key_pressed(.MOUSE_LEFT) {
engine.editor.transform_gizmo.clicked = false;
} else {
direction : Vector3;
if engine.editor.transform_gizmo.selected_axis == {
case .UP;
direction = .{0,1,0};
case .FORWARD;
direction = .{0,0,1};
case .RIGHT;
direction = .{1,0,0};
}
direction = rotate(direction, engine.editor.transform_gizmo.transform.orientation);
// Find the rotation
circle : Circle;
circle.radius = engine.editor.transform_gizmo.uniform_gizmo_scale;
circle.center = selected_entity.transform.position;
circle.orientation = direction;
distance, point := closest_distance_ray_circle(ray, circle);
new_dir := normalize(point - selected_entity.transform.position);
dotp := dot(engine.editor.transform_gizmo.last_circle_dir, new_dir);
angle := acos(clamp(dotp, -1.0, 1.0));
cp := cross(engine.editor.transform_gizmo.last_circle_dir, new_dir);
if dot(direction, cp) < 0 {
angle *= -1.0;
}
q : Quaternion;
set_from_axis_and_angle(*q, direction, angle);
selected_entity.transform.orientation = q * selected_entity.transform.orientation;
update_matrix(*selected_entity.transform);
set_rotation(*engine.editor.transform_gizmo.transform, selected_entity.transform.orientation);
engine.editor.transform_gizmo.last_circle_dir = new_dir;
}
color_up := engine.editor.transform_gizmo.color_up;
color_forward := engine.editor.transform_gizmo.color_forward;
color_right := engine.editor.transform_gizmo.color_right;
if engine.editor.transform_gizmo.selected_axis == {
case .NONE;
case .UP;
color_up = Color.{1,1,0,1};
case .FORWARD;
color_forward = Color.{1,1,0,1};
case .RIGHT;
color_right = Color.{1,1,0,1};
}
upload_data_to_buffer(engine.renderer, engine.editor.transform_gizmo.color_up_buffer, *color_up, size_of(Color));
upload_data_to_buffer(engine.renderer, engine.editor.transform_gizmo.color_forward_buffer, *color_forward, size_of(Color));
upload_data_to_buffer(engine.renderer, engine.editor.transform_gizmo.color_right_buffer, *color_right, size_of(Color));
case .SCALE;
if !key_pressed(.MOUSE_LEFT) {
selected_axis, t := intersect_scale_gizmo(ray);
engine.editor.transform_gizmo.selected_axis = selected_axis;
} else if engine.editor.transform_gizmo.selected_axis != .NONE {
selected_entity := engine.editor.selected_entities[0];
first_update := key_down(.MOUSE_LEFT);
if first_update {
engine.editor.transform_gizmo.actual_entity_position = selected_entity.transform.position;
engine.editor.transform_gizmo.actual_entity_scale = selected_entity.transform.scale;
}
// Move the currently selected entity along the selected axis
axis_vec : Vector3;
if engine.editor.transform_gizmo.selected_axis == {
case .UP;
axis_vec.y = 1;
case .FORWARD;
axis_vec.z = -1;
case .RIGHT;
axis_vec.x = 1;
case .CENTER; axis_vec = .{1,1,1};
}
r1 : Ray;
r1.origin = selected_entity.transform.position;
r1.direction = rotate(axis_vec, engine.editor.transform_gizmo.transform.orientation);
// Shoot a ray from screen to world
mouse_position : Vector2;
mouse_position.x = xx engine.input.mouse.x;
mouse_position.y = xx engine.input.mouse.y;
screen_size : Vector2;
screen_size.x = cast(float)engine.window.width;
screen_size.y = cast(float)engine.window.height;
r2 := screen_to_ray_v2(*engine.editor.camera, mouse_position, screen_size);
d, t1, t2 := closest_distance_between_rays(r1, r2);
new_position := r1.origin + r1.direction * t1;
if first_update {
engine.editor.transform_gizmo.first_hit_position = new_position;
}
position_change := new_position - engine.editor.transform_gizmo.first_hit_position;
scale_speed := ifx key_pressed(.SHIFT) then 4.0 else 1.0;
if selected_entity.flags & .UNIFORM_SCALE {
current_scale := selected_entity.transform.scale;
if engine.editor.transform_gizmo.selected_axis == {
case .UP; {
current_scale.y = engine.editor.transform_gizmo.actual_entity_scale.y + position_change.y * scale_speed;
position_change.x = 0;
position_change.z = 0;
}
case .FORWARD; {
current_scale.z = engine.editor.transform_gizmo.actual_entity_scale.z + position_change.z * scale_speed;
position_change.x = 0;
position_change.y = 0;
}
case .RIGHT; {
current_scale.x = engine.editor.transform_gizmo.actual_entity_scale.x + position_change.x * scale_speed;
position_change.y = 0;
position_change.z = 0;
}
case .CENTER; {
current_scale.x = engine.editor.transform_gizmo.actual_entity_scale.x + position_change.x * scale_speed;
current_scale.y = current_scale.x; // @Incomplete: This is most definitely wrong!
current_scale.z = current_scale.x;
position_change.y = 0;
position_change.z = 0;
}
}
set_scale(*selected_entity.transform, current_scale);
} else {
if engine.editor.transform_gizmo.selected_axis == {
case .UP;
position_change.x = 0;
position_change.z = 0;
case .FORWARD;
position_change.x = 0;
position_change.y = 0;
case .RIGHT;
position_change.y = 0;
position_change.z = 0;
}
entity_scale := engine.editor.transform_gizmo.actual_entity_scale + position_change * scale_speed;
set_scale(*selected_entity.transform, entity_scale);
}
}
color_up := engine.editor.transform_gizmo.color_up;
color_forward := engine.editor.transform_gizmo.color_forward;
color_right := engine.editor.transform_gizmo.color_right;
color_center := Color.{1,1,1,1};
if engine.editor.transform_gizmo.selected_axis == {
case .NONE;
case .UP;
color_up = Color.{1,1,0,1};
case .FORWARD;
color_forward = Color.{1,1,0,1};
case .RIGHT;
color_right = Color.{1,1,0,1};
case .CENTER;
color_center = Color.{1,1,0,1};
}
upload_data_to_buffer(engine.renderer, engine.editor.transform_gizmo.color_center_buffer, *color_center, size_of(Color));
upload_data_to_buffer(engine.renderer, engine.editor.transform_gizmo.color_up_buffer, *color_up, size_of(Color));
upload_data_to_buffer(engine.renderer, engine.editor.transform_gizmo.color_forward_buffer, *color_forward, size_of(Color));
upload_data_to_buffer(engine.renderer, engine.editor.transform_gizmo.color_right_buffer, *color_right, size_of(Color));
}
return engine.editor.transform_gizmo.selected_axis != .NONE;
}
intersect_translation_gizmo :: (ray: Ray) -> Transform_Axis, float {
transform := engine.editor.transform_gizmo.transform;
origin := transform.position;
orientation := transform.orientation;
up_ray: Ray;
up_ray.origin = origin;
up_ray.direction = rotate(.{0,1,0}, orientation);
right_ray: Ray;
right_ray.origin = origin;
right_ray.direction = rotate(.{1,0,0}, orientation);
forward_ray: Ray;
forward_ray.origin = origin;
forward_ray.direction = rotate(.{0,0,1}, orientation);
max_dist :: 0.5;
axis : Transform_Axis = .NONE;
closest := 100000000.0;
t := 0.0;
GIZMO_LENGTH := 1.3 * engine.editor.transform_gizmo.uniform_gizmo_scale;
du, tu1, tu2 := closest_distance_between_rays(ray, up_ray);
if du <= max_dist && du < closest && tu1 >= 0.0 && tu2 < GIZMO_LENGTH {
// Make sure that the point is not behind the gizmo
if dot(up_ray.direction, normalize((ray.origin + ray.direction * tu1) - origin)) >= 0.0 {
closest = du;
t = tu1;
axis = .UP;
}
}
dr, tr1, tr2 := closest_distance_between_rays(ray, right_ray);
if dr <= max_dist && dr < closest && tr1 >= 0.0 && tr2 < GIZMO_LENGTH {
// Make sure that the point is not behind the gizmo
if dot(right_ray.direction, normalize((ray.origin + ray.direction * tr1) - origin)) >= 0.0 {
closest = dr;
t = tr1;
axis = .RIGHT;
}
}
df, tf1, tf2 := closest_distance_between_rays(ray, forward_ray);
if df <= max_dist && df < closest && tf1 >= 0.0 && tf2 < GIZMO_LENGTH {
// Make sure that the point is not behind the gizmo
if dot(forward_ray.direction, normalize((ray.origin + ray.direction * tf1) - origin)) >= 0.0 {
closest = df;
t = tf1;
axis = .FORWARD;
}
}
return axis, t;
}
intersect_scale_gizmo :: (ray: Ray) -> Transform_Axis, float {
transform := engine.editor.transform_gizmo.transform;
origin := transform.position;
orientation := transform.orientation;
radius := engine.editor.transform_gizmo.uniform_gizmo_scale * 0.15;
if ray_sphere_intersect(ray, origin, radius) {
return .CENTER, 0.0;
}
up_ray: Ray;
up_ray.origin = origin;
up_ray.direction = rotate(.{0,1,0}, orientation);
right_ray: Ray;
right_ray.origin = origin;
right_ray.direction = rotate(.{1,0,0}, orientation);
forward_ray: Ray;
forward_ray.origin = origin;
forward_ray.direction = rotate(.{0,0,1}, orientation);
max_dist :: 0.5;
axis : Transform_Axis = .NONE;
closest := 100000000.0;
t := 0.0;
du, tu1, tu2 := closest_distance_between_rays(ray, up_ray);
if du <= max_dist && du < closest && tu1 >= 0.0 {
// Make sure that the point is not behind the gizmo
if dot(up_ray.direction, normalize((ray.origin + ray.direction * tu1) - origin)) >= 0.0 {
closest = du;
t = tu1;
axis = .UP;
}
}
dr, tr1, tr2 := closest_distance_between_rays(ray, right_ray);
if dr <= max_dist && dr < closest && tr1 >= 0.0 {
// Make sure that the point is not behind the gizmo
if dot(right_ray.direction, normalize((ray.origin + ray.direction * tr1) - origin)) >= 0.0 {
closest = dr;
t = tr1;
axis = .RIGHT;
}
}
df, tf1, tf2 := closest_distance_between_rays(ray, forward_ray);
if df <= max_dist && df < closest && tf1 >= 0.0 {
// Make sure that the point is not behind the gizmo
if dot(forward_ray.direction, normalize((ray.origin + ray.direction * tf1) - origin)) >= 0.0 {
closest = df;
t = tf1;
axis = .FORWARD;
}
}
return axis, t;
}
Circle :: struct {
center: Vector3;
radius: float;
orientation: Vector3;
}
closest_distance_ray_circle :: (r: Ray, c: Circle) -> float, Vector3 {
plane_p := c.center;
plane_orientation := c.orientation;
success, t := ray_plane_intersection(r, plane_p, plane_orientation);
if success {
// get the ray's intersection point on the plane which
// contains the circle
on_plane := r.origin + t * r.direction;
// project that point on to the circle's circumference
point := c.center + c.radius * normalize(on_plane - c.center);
return length(on_plane - point), point;
} else {
// the required point on the circle is the one closest to the camera origin
point := c.radius * normalize(reject(r.origin - c.center, c.orientation));
return distance_from_ray_to_point(r, point), point;
}
}
intersect_rotation_gizmo :: (ray: Ray) -> Transform_Axis, Vector3 {
selected_entity := engine.editor.selected_entities[0];
orientation := selected_entity.transform.orientation;
radius := engine.editor.transform_gizmo.uniform_gizmo_scale;
up: Circle;
up.radius = radius;
up.center = engine.editor.transform_gizmo.transform.position;
up.orientation = rotate(.{0,1,0}, orientation);
right: Circle;
right.radius = radius;
right.center = engine.editor.transform_gizmo.transform.position;
right.orientation = rotate(.{1,0,0}, orientation);
forward: Circle;
forward.radius = radius;
forward.center = engine.editor.transform_gizmo.transform.position;
forward.orientation = rotate(.{0,0,1}, orientation);
min_dist :: 0.4;
axis : Transform_Axis = .NONE;
closest := 100000000.0;
p : Vector3;
du, pu := closest_distance_ray_circle(ray, up);
if du <= min_dist && du < closest {
closest = du;
axis = .UP;
p = pu;
}
dr, pr := closest_distance_ray_circle(ray, right);
if dr <= min_dist && dr < closest {
closest = dr;
axis = .RIGHT;
p = pr;
}
df, pf := closest_distance_ray_circle(ray, forward);
if df <= min_dist && df < closest {
closest = df;
axis = .FORWARD;
p = pf;
}
return axis, p;
}
update_gizmo_buffers :: () {
// update_matrix(*engine.editor.transform_gizmo.transform);
//
// up_rotation := rotation_matrix(Matrix3, euler_to_quaternion(degrees_to_radians(90), degrees_to_radians(90), degrees_to_radians(0)));
// right_rotation := rotation_matrix(Matrix3, euler_to_quaternion(degrees_to_radians(90), degrees_to_radians(0), degrees_to_radians(90)));
// up_model := engine.editor.transform_gizmo.transform.model_matrix * up_rotation;
// right_model := engine.editor.transform_gizmo.transform.model_matrix * right_rotation;
// center_scale := make_scale_matrix4(.{0.15, 0.15, 0.15});
// center_model := engine.editor.transform_gizmo.transform.model_matrix * center_scale;
//
// upload_data_to_buffer(engine.renderer, engine.editor.transform_gizmo.center_model_buffer, *center_model, size_of(Matrix4));
// upload_data_to_buffer(engine.renderer, engine.editor.transform_gizmo.up_model_buffer, *up_model, size_of(Matrix4));
// upload_data_to_buffer(engine.renderer, engine.editor.transform_gizmo.forward_model_buffer, *engine.editor.transform_gizmo.transform.model_matrix, size_of(Matrix4));
// upload_data_to_buffer(engine.renderer, engine.editor.transform_gizmo.right_model_buffer, *right_model, size_of(Matrix4));
entity := engine.editor.selected_entities[0];
engine.editor.transform_gizmo.transform.position = entity.transform.position;
engine.editor.transform_gizmo.transform.orientation = entity.transform.orientation;
update_matrix(*engine.editor.transform_gizmo.transform);
up_rotation := rotation_matrix(Matrix3, euler_to_quaternion(degrees_to_radians(90), degrees_to_radians(90), degrees_to_radians(0)));
right_rotation := rotation_matrix(Matrix3, euler_to_quaternion(degrees_to_radians(90), degrees_to_radians(0), degrees_to_radians(90)));
up_model := engine.editor.transform_gizmo.transform.model_matrix * up_rotation;
right_model := engine.editor.transform_gizmo.transform.model_matrix * right_rotation;
center_scale := make_scale_matrix4(.{0.15, 0.15, 0.15});
center_model := engine.editor.transform_gizmo.transform.model_matrix * center_scale;
upload_data_to_buffer(engine.renderer, engine.editor.transform_gizmo.center_model_buffer, *center_model, size_of(Matrix4));
upload_data_to_buffer(engine.renderer, engine.editor.transform_gizmo.up_model_buffer, *up_model, size_of(Matrix4));
upload_data_to_buffer(engine.renderer, engine.editor.transform_gizmo.forward_model_buffer, *engine.editor.transform_gizmo.transform.model_matrix, size_of(Matrix4));
upload_data_to_buffer(engine.renderer, engine.editor.transform_gizmo.right_model_buffer, *right_model, size_of(Matrix4));
}
render_transform_gizmo :: () {
if engine.editor.selected_entities.count == 1 {
update_gizmo_buffers();
renderer := engine.renderer;
push_cmd_set_draw_mode(renderer, .FILL);
push_cmd_set_depth_write(renderer, false);
push_cmd_set_pipeline_state(renderer, engine.editor.transform_gizmo.pipeline);
push_cmd_set_constant_buffer(engine.renderer, 0, engine.camera_buffer,.VERTEX);
#load "editor_ui.jai";
render_gizmo :: (mesh: *Mesh) {
renderer := engine.renderer;
vb := get_mesh_vb(mesh, engine.editor.transform_gizmo.pipeline);
// RIGHT
push_cmd_set_constant_buffer(engine.renderer, 1, engine.editor.transform_gizmo.right_model_buffer, .VERTEX);
push_cmd_set_constant_buffer(engine.renderer, 2, engine.editor.transform_gizmo.color_right_buffer, .PIXEL);
push_cmd_set_vertex_buffer(renderer, vb);
push_cmd_set_index_buffer(renderer, mesh.ib);
push_cmd_draw_indexed(renderer, mesh.indices.count);
// FORWARD
push_cmd_set_constant_buffer(engine.renderer, 1, engine.editor.transform_gizmo.forward_model_buffer, .VERTEX);
push_cmd_set_constant_buffer(engine.renderer, 2, engine.editor.transform_gizmo.color_forward_buffer, .PIXEL);
push_cmd_set_vertex_buffer(renderer, vb);
push_cmd_set_index_buffer(renderer, mesh.ib);
push_cmd_draw_indexed(renderer, mesh.indices.count);
// UP
push_cmd_set_constant_buffer(engine.renderer, 1, engine.editor.transform_gizmo.up_model_buffer, .VERTEX);
push_cmd_set_constant_buffer(engine.renderer, 2, engine.editor.transform_gizmo.color_up_buffer, .PIXEL);
push_cmd_set_vertex_buffer(renderer, vb);
push_cmd_set_index_buffer(renderer, mesh.ib);
push_cmd_draw_indexed(renderer, mesh.indices.count);
}
if engine.editor.transform_gizmo.transform_type == {
case .TRANSLATION; {
mesh := parray_get(*engine.renderer.meshes, engine.renderer.default_meshes.translation_gizmo);
render_gizmo(mesh);
}
case .SCALE; {
mesh := parray_get(*engine.renderer.meshes, engine.renderer.default_meshes.scale_gizmo);
render_gizmo(mesh);
center_mesh := parray_get(*engine.renderer.meshes, engine.renderer.default_meshes.cube);
push_cmd_set_constant_buffer(engine.renderer, 1, engine.editor.transform_gizmo.center_model_buffer, .VERTEX);
push_cmd_set_constant_buffer(engine.renderer, 2, engine.editor.transform_gizmo.color_center_buffer, .PIXEL);
vb := get_mesh_vb(mesh, engine.editor.transform_gizmo.pipeline);
push_cmd_set_vertex_buffer(renderer, vb);
push_cmd_set_index_buffer(renderer, center_mesh.ib);
push_cmd_draw_indexed(renderer, center_mesh.indices.count);
}
case .ROTATION; {
mesh := parray_get(*engine.renderer.meshes, engine.renderer.default_meshes.rotation_gizmo);
render_gizmo(mesh);
}
}
}
}
#load "editor_ui.jai";
#load "../renderer/shaders.jai";

View File

@@ -1,5 +1,7 @@
#load "../ui/widgets.jai";
#placeholder editor_ui_entity_creation;
pick_scene_view_at :: (camera: Camera, coordinates: Vector2) {
ray := normalized_screen_to_ray_v2(camera, coordinates);
@@ -54,22 +56,22 @@ editor_ui :: () {
ui_space(20, 0);
//if mode == {
// case .PLAYING; {
// ui_set_next_background_color(.{0,0.6,0,1});
// if ui_button_with_texture(editor.icons.stop) {
// edit_engine.current_scene();
// }
// ui_label(tprint("Playing '%'", engine.current_scene.name), .{0,0.7,0,1});
// }
// case .EDITING; {
if engine.mode == {
case .PLAYING; {
ui_set_next_background_color(.{0,0.6,0,1});
if ui_button_with_texture(engine.editor.icons.stop) {
switch_engine_mode(.EDITING);
}
ui_label(tprint("Playing '%'", engine.current_scene.name), .{0,0.7,0,1});
}
case .EDITING; {
ui_set_next_background_color(.{0.6,0,0,1});
//if ui_button_with_texture(editor.icons.play) {
// play_current_editor_scene();
//}
if ui_button_with_texture(engine.editor.icons.play) {
switch_engine_mode(.PLAYING);
}
ui_label(tprint("Editing '%'", engine.current_scene.name), .{1,1,1,1});
//}
//}
}
}
}
ui_pop_parent();
@@ -135,7 +137,7 @@ editor_ui :: () {
ui_set_next_size_x(.PCT, 1.0);
ui_tab_title_bar("SCENE");
ui_set_next_size_x(.PCT, 1.0);
ui_set_next_size_y(.PCT, 0.9);
ui_set_next_size_y(.PCT, 0.75);
state := ui_interactable_texture(get_texture_from_pass("UI Blend Pass"));
if state.left_mouse_down {
@@ -146,8 +148,15 @@ editor_ui :: () {
engine.editor.mouse_viewport_state = state;
ui_set_next_size_x(.PCT, 1.0);
ui_set_next_size_y(.PCT, 0.1);
ui_tab_title_bar("SCENES");
ui_set_next_size_y(.PCT, 0.25);
ui_tab_title_bar("Create entities");
{
new_entity := editor_ui_entity_creation();
if new_entity != null {
engine.editor.selected_entities.count = 0;
array_add(*engine.editor.selected_entities, new_entity);
}
}
}
ui_pop_parent();
@@ -162,14 +171,15 @@ editor_ui :: () {
ui_set_next_size_x(.PCT, 1.0);
ui_tab_title_bar("PROPERTIES");
//if editor.selected_entity != null {
// ui_slider(*slider_value, 0.0, 1.0);
// ui_label(tprint("Name: %", editor.selected_entity.name));
// ui_label(tprint("Id: %", editor.selected_entity.id));
// ui_label(tprint("Position: % % %", editor.selected_entity.transform.position.x, editor.selected_entity.transform.position.y, editor.selected_entity.transform.position.z));
// ui_label(tprint("Rotation: % % % %", editor.selected_entity.transform.orientation.x, editor.selected_entity.transform.orientation.y, editor.selected_entity.transform.orientation.z, editor.selected_entity.transform.orientation.w));
// ui_label(tprint("Scale: % % %", editor.selected_entity.transform.scale.x, editor.selected_entity.transform.scale.y, editor.selected_entity.transform.scale.z));
//}
if engine.editor.selected_entities.count == 1 {
entity := engine.editor.selected_entities[0];
ui_slider(*slider_value, 0.0, 1.0);
ui_label(tprint("Name: %", entity.name));
ui_label(tprint("Id: %", entity.id));
ui_label(tprint("Position: % % %", entity.transform.position.x, entity.transform.position.y, entity.transform.position.z));
ui_label(tprint("Rotation: % % % %", entity.transform.orientation.x, entity.transform.orientation.y, entity.transform.orientation.z, entity.transform.orientation.w));
ui_label(tprint("Scale: % % %", entity.transform.scale.x, entity.transform.scale.y, entity.transform.scale.z));
}
}
ui_pop_parent();
@@ -187,22 +197,28 @@ base_editor_update :: () {
eat_key(.MOUSE_LEFT);
}
// @Incomplete: Show that we saved the scene in the editor. Maybe a quick text message or just inside one of the tab titles
if key_pressed(.CTRL) && key_down(.S) {
save_scene(engine.current_scene);
}
// Check if we hit the gizmo
// @Incomplete: MOVE THIS
engine.editor.should_check_entities = true;
//if editor.selected_entity != null {
// gizmo_scale := distance(editor.selected_entity.transform.position, editor.camera.position) * 0.1 * 0.5;
// editor.transform_gizmo.uniform_gizmo_scale = gizmo_scale;
// set_scale(*editor.transform_gizmo.transform, .{gizmo_scale, gizmo_scale, gizmo_scale});
if engine.editor.selected_entities.count == 1 {
entity := engine.editor.selected_entities[0];
gizmo_scale := distance(entity.transform.position, engine.editor.camera.position) * 0.1 * 0.5;
engine.editor.transform_gizmo.uniform_gizmo_scale = gizmo_scale;
set_scale(*engine.editor.transform_gizmo.transform, .{gizmo_scale, gizmo_scale, gizmo_scale});
// coordinates := Vector2.{editor.mouse_viewport_state.normalized_local_mouse_coordinates.x, 1.0 - editor.mouse_viewport_state.normalized_local_mouse_coordinates.y};
// ray := normalized_screen_to_ray_v2(*editor.camera, coordinates);
coordinates := Vector2.{engine.editor.mouse_viewport_state.normalized_local_mouse_coordinates.x, 1.0 - engine.editor.mouse_viewport_state.normalized_local_mouse_coordinates.y};
ray := normalized_screen_to_ray_v2(engine.editor.camera, coordinates);
// if update_transform_gizmo(ray, coordinates) {
// editor.should_check_entities = false;
// }
//}
if update_transform_gizmo(ray, coordinates) {
engine.editor.should_check_entities = false;
}
}
editor_ui();
@@ -212,7 +228,7 @@ base_editor_update :: () {
// // @Incomplete: At some point we want this to place entities at either a set distance or a distance depending on a raycast in the camera's forward direction so that we don't place things behind other entities
// set_position(*placed_entity.transform, editor.camera.position + editor.camera.forward * 30);
// editor.show_menu = false;
// editor.selected_entity = placed_entity;
// entity = placed_entity;
// }
//}
@@ -223,20 +239,20 @@ base_editor_update :: () {
//show_message("Saved scene");
}
//if editor.selected_entity != null {
//if entity != null {
// // @Incomplete:@Incomplete: Duplicate
// //if key_pressed(.CTRL) && key_down(.D) {
// // make_directory_if_it_does_not_exist("../temp");
// // save_entity(editor.selected_entity, "../temp/", "temp");
// // save_entity(entity, "../temp/", "temp");
// // duplicated := load_entity(editor_scene, "../temp/temp.ent");
// // editor.selected_entity = duplicated;
// // entity = duplicated;
// //}
// // DELETE
// // DELETE
// //if key_down(.DELETE) || key_down(.BACKSPACE) {
// // delete_entity(editor.selected_entity);
// // editor.selected_entity = null;
// // delete_entity(entity);
// // entity = null;
// // editor.transform_gizmo.selected_axis = .NONE;
// //}
//}
@@ -297,27 +313,26 @@ base_editor_update :: () {
engine.editor.menu_position.y = cast(float)engine.renderer.render_target_height - mouse_position.y;
}
if key_down(.W) {
engine.editor.transform_gizmo.transform_type = .TRANSLATION;
}
if !key_pressed(.CTRL) {
if key_down(.W) {
engine.editor.transform_gizmo.transform_type = .TRANSLATION;
}
if key_down(.E) {
engine.editor.transform_gizmo.transform_type = .ROTATION;
}
if key_down(.E) {
engine.editor.transform_gizmo.transform_type = .ROTATION;
}
if key_down(.R) {
engine.editor.transform_gizmo.transform_type = .SCALE;
if key_down(.R) {
engine.editor.transform_gizmo.transform_type = .SCALE;
}
}
}
update_view_matrix(camera);
}
//if editor.selected_entity != null {
// e := editor.selected_entity;
// set_position(*editor.transform_gizmo.transform, e.transform.position);
// update_gizmo_buffers();
//}
//edit_scene_settings(*game_state.engine.current_scene.settings);
if key_pressed(.CTRL) && key_down(.E) {
new_mode := ifx engine.mode == .EDITING then Engine_Mode.PLAYING else .EDITING;
switch_engine_mode(new_mode);
}
}