1 #include <linmath.h/linmath.h>
3 #include "client/camera.h"
4 #include "client/client.h"
5 #include "client/client_item.h"
6 #include "client/client_node.h"
7 #include "client/client_player.h"
8 #include "client/cube.h"
9 #include "client/debug_menu.h"
10 #include "client/frustum.h"
11 #include "client/gl_debug.h"
12 #include "client/gui.h"
13 #include "client/interact.h"
14 #include "client/mesh.h"
15 #include "client/raycast.h"
16 #include "client/shader.h"
18 struct InteractPointed interact_pointed;
20 static GLuint shader_prog;
22 static GLint loc_color;
27 } __attribute__((packed)) SelectionVertex;
28 static Mesh selection_mesh = {
29 .layout = &(VertexLayout) {
30 .attributes = (VertexAttribute[]) {
31 {GL_FLOAT, 3, sizeof(v3f32)},
34 .size = sizeof(SelectionVertex),
45 if (!shader_program_create(RESSOURCE_PATH "shaders/3d/selection", &shader_prog, NULL)) {
46 fprintf(stderr, "[error] failed to create selection shader program\n");
50 loc_MVP = glGetUniformLocation(shader_prog, "MVP"); GL_DEBUG
51 loc_color = glGetUniformLocation(shader_prog, "color"); GL_DEBUG
53 SelectionVertex vertices[6][6];
54 for (int f = 0; f < 6; f++)
55 for (int v = 0; v < 6; v++)
56 vertices[f][v].position = v3f32_scale(cube_vertices[f][v].position, 1.1f);
58 selection_mesh.data = vertices;
59 mesh_upload(&selection_mesh);
61 gui_add(NULL, (GUIElementDef) {
66 .align = {0.5f, 0.5f},
67 .scale = {1.0f, 1.0f},
68 .scale_type = SCALE_IMAGE,
69 .affect_parent_scale = false,
71 .image = texture_load(RESSOURCE_PATH "textures/crosshair.png", false),
72 .text_color = {0.0f, 0.0f, 0.0f, 0.0f},
73 .bg_color = {0.0f, 0.0f, 0.0f, 0.0f},
79 void interact_deinit()
81 glDeleteProgram(shader_prog); GL_DEBUG
82 mesh_destroy(&selection_mesh);
87 bool old_exists = interact_pointed.exists;
88 v3s32 old_pointed = interact_pointed.pos;
89 if ((interact_pointed.exists = raycast(
90 (v3f64) {camera.eye [0], camera.eye [1], camera.eye [2]},
91 (v3f64) {camera.front[0], camera.front[1], camera.front[2]},
92 5, &interact_pointed.pos, &interact_pointed.node))
93 && !v3s32_equals(interact_pointed.pos, old_pointed)) {
94 mat4x4_translate(model,
95 interact_pointed.pos.x, interact_pointed.pos.y, interact_pointed.pos.z);
96 v3f32 *color = &client_node_defs[interact_pointed.node].selection_color;
97 glProgramUniform3f(shader_prog, loc_color, color->x, color->y, color->z); GL_DEBUG
98 debug_menu_changed(ENTRY_POINTED);
101 if (old_exists && !interact_pointed.exists)
102 debug_menu_changed(ENTRY_POINTED);
105 void interact_render()
107 if (!interact_pointed.exists)
111 mat4x4_mul(mvp, frustum, model);
113 glUseProgram(shader_prog); GL_DEBUG
114 glUniformMatrix4fv(loc_MVP, 1, GL_FALSE, mvp[0]); GL_DEBUG
115 mesh_render(&selection_mesh);
118 void interact_use(bool left)
120 ClientEntity *entity = client_player_entity_local();
124 ClientPlayerData *data = entity->extra;
125 pthread_mutex_lock(&data->mtx_inv);
127 ItemStack *stack = left ? &data->inventory.left : &data->inventory.right;
128 if (client_item_defs[stack->type].use && client_item_defs[stack->type].use(stack))
129 dragonnet_peer_send_ToServerInteract(client, &(ToServerInteract) {
131 .pointed = interact_pointed.exists,
132 .pos = interact_pointed.pos,
135 pthread_mutex_unlock(&data->mtx_inv);
136 refcount_drp(&entity->rc);