Files
2026-08-25 15:38:59 +02:00

552 lines
19 KiB
C

#include "global.h"
void context_init() {
g_context = ALLOC_INIT(context_t, {0});
g_context->merged_object_is_atlas = false; // Only objects referenced by atlas are merged
g_context->ddirty = 0; // depth
g_context->pdirty = 0; // paint
g_context->brush_blend_dirty = true;
g_context->split_view = false;
g_context->view_index = -1;
g_context->view_index_last = -1;
g_context->picked_color = project_make_swatch(0xffffffff);
g_context->envmap_loaded = false;
g_context->show_envmap = false;
g_context->show_envmap_blur = false;
g_context->show_envmap_spheres = false;
g_context->capturing_screenshot = false;
g_context->capture_background = false;
g_context->envmap_angle = 0.0;
g_context->light_angle = 0.0;
g_context->cull_backfaces = true;
g_context->format_type = TEXTURE_LDR_FORMAT_PNG;
g_context->format_quality = 100.0;
g_context->layers_destination = EXPORT_DESTINATION_DISK;
g_context->split_by = SPLIT_TYPE_OBJECT;
g_context->select_time = 0.0;
g_context->viewport_mode = g_config->viewport_mode;
g_context->hscale_was_changed = false;
g_context->export_mesh_format = MESH_FORMAT_OBJ;
g_context->export_mesh_index = 0;
g_context->pack_assets_on_export = true;
g_context->pack_assets_on_save = false;
g_context->paint_vec = (vec4_t){0.0, 0.0, 0.0, 1.0};
g_context->last_paint_x = -1.0;
g_context->last_paint_y = -1.0;
g_context->foreground_event = false;
g_context->painted = 0;
g_context->brush_time = 0.0;
g_context->clone_start_x = -1.0;
g_context->clone_start_y = -1.0;
g_context->clone_delta_x = 0.0;
g_context->clone_delta_y = 0.0;
g_context->clone_set_source = false;
g_context->show_compass = true;
g_context->last_paint_vec_x = -1.0;
g_context->last_paint_vec_y = -1.0;
g_context->prev_paint_vec_x = -1.0;
g_context->prev_paint_vec_y = -1.0;
g_context->frame = 0;
g_context->paint2d_view = false;
g_context->brush_locked = false;
g_context->camera_type = CAMERA_TYPE_PERSPECTIVE;
g_context->texture_export_path = "";
g_context->last_status_position = 0;
g_context->camera_pivot = CAMERA_PIVOT_CURSOR;
g_context->camera_controls = CAMERA_CONTROLS_ORBIT;
g_context->pen_painting_only = false; // Reject painting with finger when using pen
g_context->layer_preview_dirty = true;
g_context->layers_preview_dirty = false;
g_context->node_preview_name = "";
g_context->node_preview_socket_map = any_map_create();
g_context->node_preview_map = any_map_create();
g_context->selected_node_preview = true;
g_context->material_preview = false; // Drawing material previews
g_context->saved_camera = mat4_identity();
g_context->materialid_picked = 0;
g_context->uvx_picked = 0.0;
g_context->uvy_picked = 0.0;
g_context->picker_select_material = false;
g_context->picker_paint_mask = false;
g_context->picker_viewport_mask = false;
g_context->pick_pos_nor_tex = false;
g_context->pick_object_id = false;
g_context->posx_picked = 0.0;
g_context->posy_picked = 0.0;
g_context->posz_picked = 0.0;
g_context->norx_picked = 0.0;
g_context->nory_picked = 0.0;
g_context->norz_picked = 0.0;
g_context->draw_wireframe = false;
g_context->draw_texels = false;
g_context->colorid = 0;
g_context->colorid_picked = false;
g_context->layers_export = EXPORT_MODE_VISIBLE;
g_context->decal_preview = false;
g_context->decal_x = 0.0;
g_context->decal_y = 0.0;
g_context->write_icon_on_export = false;
g_context->particle_hit_x = 0.0;
g_context->particle_hit_y = 0.0;
g_context->particle_hit_z = 0.0;
g_context->last_particle_hit_x = 0.0;
g_context->last_particle_hit_y = 0.0;
g_context->last_particle_hit_z = 0.0;
g_context->particle_friction = 0.1;
g_context->particle_bounciness = 0.0;
g_context->particle_gravity_x = 0.0;
g_context->particle_gravity_y = 0.0;
g_context->particle_gravity_z = -9.81;
g_context->particle_lifetime = 5.0;
g_context->particle_mass = 1.0;
g_context->particle_random = 0.1;
g_context->particle_spawn_distance = 0.0;
g_context->layer_filter = 0;
g_context->gizmo_started = false;
g_context->gizmo_offset = 0.0;
g_context->gizmo_drag = 0.0;
g_context->gizmo_drag_last = 0.0;
g_context->translate_x = false;
g_context->translate_y = false;
g_context->translate_z = false;
g_context->scale_x = false;
g_context->scale_y = false;
g_context->scale_z = false;
g_context->rotate_x = false;
g_context->rotate_y = false;
g_context->rotate_z = false;
g_context->brush_nodes_radius = 1.0;
g_context->brush_nodes_opacity = 1.0;
g_context->brush_nodes_uses_random = false;
g_context->brush_mask_image_is_alpha = false;
g_context->brush_stencil_image_is_alpha = false;
g_context->brush_stencil_x = 0.02;
g_context->brush_stencil_y = 0.02;
g_context->brush_stencil_scale = 0.9;
g_context->brush_stencil_scaling = false;
g_context->brush_stencil_angle = 0.0;
g_context->brush_stencil_rotating = false;
g_context->brush_nodes_scale = 1.0;
g_context->brush_nodes_angle = 0.0;
g_context->brush_nodes_hardness = 1.0;
g_context->brush_directional = false;
g_context->brush_scale_x = 1.0;
g_context->brush_decal_mask_radius = 0.5;
g_context->brush_blending = BLEND_TYPE_MIX;
g_context->brush_opacity = 1.0;
g_context->brush_scale = 1.0;
g_context->brush_angle = 0.0;
g_context->brush_lazy_radius = 0.0;
g_context->brush_lazy_step = 0.0;
g_context->brush_lazy_x = 0.0;
g_context->brush_lazy_y = 0.0;
g_context->brush_paint = UV_TYPE_UVMAP;
g_context->brush_angle_reject_dot = 0.5;
g_context->bake_type = BAKE_TYPE_CURVATURE;
g_context->bake_axis = BAKE_AXIS_XYZ;
g_context->bake_up_axis = BAKE_UP_AXIS_Z;
g_context->bake_samples = 128;
g_context->bake_ao_strength = 1.0;
g_context->bake_ao_radius = 1.0;
g_context->bake_ao_offset = 1.0;
g_context->bake_curv_strength = 1.0;
g_context->bake_curv_radius = 1.0;
g_context->bake_curv_offset = 0.0;
g_context->bake_curv_smooth = 1;
g_context->bake_high_poly = 0;
g_context->xray = false;
g_context->sym_x = false;
g_context->sym_y = false;
g_context->sym_z = false;
g_context->fill_type = FILL_TYPE_OBJECT;
g_context->blur_type = BLUR_TYPE_BLUR;
g_context->paint2d = false;
g_context->maximized_sidebar_width = 0;
g_context->drag_dest = 0;
g_context->tool = TOOL_TYPE_BRUSH;
g_context->color_picker_previous_tool = TOOL_TYPE_BRUSH;
g_context->brush_radius = 0.5;
g_context->brush_hardness = 1.0;
g_context->project_type = -1;
}
bool context_use_deferred() {
return g_config->render_mode != RENDER_MODE_FORWARD &&
(g_context->viewport_mode == VIEWPORT_MODE_LIT || g_context->viewport_mode == VIEWPORT_MODE_PATH_TRACE) && g_context->tool != TOOL_TYPE_COLORID;
}
void context_select_material(i32 i) {
if (g_project->_->materials->length <= i) {
return;
}
context_set_material(g_project->_->materials->buffer[i]);
}
void context_set_material_on_next_frame(void *_) {
util_render_make_decal_preview();
}
void context_set_material(slot_material_t *m) {
if (array_index_of(g_project->_->materials, m) == -1) {
return;
}
g_context->material = m;
make_material_parse_paint_material(true);
ui_base_hwnds->buffer[TAB_AREA_SIDEBAR1]->redraws = 2;
ui_header_handle->redraws = 2;
ui_nodes_hwnd->redraws = 2;
ui_nodes_group_stack = any_array_create_from_raw((void *[]){}, 0);
bool decal = context_is_decal();
if (decal) {
sys_notify_on_next_frame(&context_set_material_on_next_frame, NULL);
}
}
void context_select_brush(i32 i) {
if (g_project->_->brushes->length <= i) {
return;
}
context_set_brush(g_project->_->brushes->buffer[i]);
}
void context_set_brush(slot_brush_t *b) {
if (array_index_of(g_project->_->brushes, b) == -1) {
return;
}
g_context->brush = b;
make_material_parse_brush();
brush_output_node_parse_inputs();
make_material_parse_paint_material(false);
ui_base_hwnds->buffer[TAB_AREA_SIDEBAR1]->redraws = 2;
ui_nodes_hwnd->redraws = 2;
}
void context_set_font(slot_font_t *f) {
if (array_index_of(g_project->_->fonts, f) == -1) {
return;
}
g_context->font = f;
util_render_make_text_preview();
util_render_make_decal_preview();
ui_base_hwnds->buffer[TAB_AREA_STATUS]->redraws = 2;
ui_view2d_hwnd->redraws = 2;
}
void context_select_font(i32 i) {
if (g_project->_->fonts->length <= i) {
return;
}
context_set_font(g_project->_->fonts->buffer[i]);
}
void context_set_sound(slot_sound_t *s) {
if (array_index_of(g_project->_->sounds, s) == -1) {
return;
}
g_context->sound = s;
ui_base_hwnds->buffer[TAB_AREA_STATUS]->redraws = 2;
ui_view2d_hwnd->redraws = 2;
}
void context_select_sound(i32 i) {
if (g_project->_->sounds->length <= i) {
return;
}
context_set_sound(g_project->_->sounds->buffer[i]);
}
void context_select_layer(i32 i) {
if (g_project->_->layers->length <= i) {
return;
}
context_set_layer(g_project->_->layers->buffer[i]);
}
void context_set_layer(slot_layer_t *l) {
if (l == g_context->layer) {
return;
}
g_context->layer = l;
ui_header_handle->redraws = 2;
gpu_texture_t *current = _draw_current;
bool in_use = gpu_in_use;
if (in_use)
draw_end();
layers_set_object_mask();
make_material_parse_mesh_material();
make_material_parse_paint_material(true);
if (in_use)
draw_begin(current, false, 0);
ui_base_hwnds->buffer[TAB_AREA_SIDEBAR0]->redraws = 2;
ui_view2d_hwnd->redraws = 2;
}
void context_select_tool(i32 i) {
g_context->tool = i;
make_material_parse_paint_material(true);
make_material_parse_mesh_material();
g_context->ddirty = 3;
viewport_mode_t _viewport_mode = g_context->viewport_mode;
g_context->viewport_mode = VIEWPORT_MODE_NONE;
context_set_viewport_mode(_viewport_mode);
context_init_tool();
ui_header_handle->redraws = 2;
ui_toolbar_handle->redraws = 2;
}
void context_init_tool() {
if (context_is_decal()) {
if (g_context->tool == TOOL_TYPE_TEXT) {
util_render_make_text_preview();
}
util_render_make_decal_preview();
}
else if (g_context->tool == TOOL_TYPE_MATERIAL) {
layers_update_fill_layers();
context_main_object()->skip_context = NULL;
}
}
void context_select_paint_object(mesh_object_t *o) {
ui_header_handle->redraws = 2;
for (i32 i = 0; i < g_project->_->paint_objects->length; ++i) {
mesh_object_t *p = g_project->_->paint_objects->buffer[i];
p->skip_context = "paint";
}
g_context->paint_object = o;
i32 mask = slot_layer_get_object_mask(g_context->layer);
if (context_layer_filter_used()) {
mask = g_context->layer_filter;
}
if (g_context->merged_object == NULL || mask > 0) {
g_context->paint_object->skip_context = "";
}
util_uv_uvmap_cached = false;
util_uv_trianglemap_cached = false;
util_uv_dilatemap_cached = false;
}
mesh_object_t *context_main_object() {
for (i32 i = 0; i < g_project->_->paint_objects->length; ++i) {
mesh_object_t *po = g_project->_->paint_objects->buffer[i];
if (po->base->children->length > 0) {
return po;
}
}
return g_project->_->paint_objects->buffer[0];
}
bool context_layer_filter_used() {
return g_context->layer_filter > 0 && g_context->layer_filter <= g_project->_->paint_objects->length;
}
bool context_object_mask_used() {
return slot_layer_get_object_mask(g_context->layer) > 0 && slot_layer_get_object_mask(g_context->layer) <= g_project->_->paint_objects->length;
}
bool context_in_3d_view() {
return g_context->paint_vec.x < 1 && g_context->paint_vec.x > 0 && g_context->paint_vec.y < 1 && g_context->paint_vec.y > 0;
}
bool context_in_paint_area() {
return context_in_3d_view() || context_in_2d_view(VIEW_2D_TYPE_LAYER);
}
bool context_in_layers() {
char *tab = ui_hovered_tab_name();
return string_equals(tab, tr("Layers"));
}
bool context_in_materials() {
char *tab = ui_hovered_tab_name();
return string_equals(tab, tr("Materials"));
}
bool context_in_meshes() {
char *tab = ui_hovered_tab_name();
return string_equals(tab, tr("Meshes"));
}
bool context_in_swatches() {
char *tab = ui_hovered_tab_name();
return string_equals(tab, tr("Swatches"));
}
bool context_in_brushes() {
char *tab = ui_hovered_tab_name();
return string_equals(tab, tr("Brushes"));
}
bool context_in_fonts() {
char *tab = ui_hovered_tab_name();
return string_equals(tab, tr("Fonts"));
}
bool context_in_textures() {
char *tab = ui_hovered_tab_name();
return string_equals(tab, tr("Textures"));
}
bool context_in_browser() {
char *tab = ui_hovered_tab_name();
return string_equals(tab, tr("Browser"));
}
bool context_in_2d_view(view_2d_type_t type) {
return ui_view2d_show && ui_view2d_type == type && mouse_x > ui_view2d_wx && mouse_x < ui_view2d_wx + ui_view2d_ww && mouse_y > ui_view2d_wy &&
mouse_y < ui_view2d_wy + ui_view2d_wh;
}
bool context_in_nodes() {
return ui_nodes_show && mouse_x > ui_nodes_wx && mouse_x < ui_nodes_wx + ui_nodes_ww && mouse_y > ui_nodes_wy && mouse_y < ui_nodes_wy + ui_nodes_wh;
}
bool context_is_decal() {
return g_context->tool == TOOL_TYPE_DECAL || g_context->tool == TOOL_TYPE_TEXT;
}
bool context_is_decal_mask() {
return context_is_decal() && keymap_shortcut(any_map_get(g_keymap, "decal_mask"), SHORTCUT_TYPE_DOWN);
}
bool context_is_brush_camera_align() {
bool brush = g_context->tool == TOOL_TYPE_BRUSH || g_context->tool == TOOL_TYPE_ERASER;
return (context_is_decal() || brush) &&
(g_context->brush_camera_align || keymap_shortcut(any_map_get(g_keymap, "brush_camera_align"), SHORTCUT_TYPE_DOWN));
}
bool context_is_decal_mask_paint() {
return context_is_decal() &&
keymap_shortcut(string_tmp("%s+%s", any_map_get(g_keymap, "decal_mask"), any_map_get(g_keymap, "action_paint")), SHORTCUT_TYPE_DOWN);
}
bool context_is_decal_mask_paint_pass() {
return context_is_decal_mask() && (mouse_down("left") || g_context->brush_time > 0);
}
bool context_is_floating_toolbar() {
// Header is off -> floating toolbar
return g_config->layout->buffer[LAYOUT_SIZE_HEADER] == 0 || (!base_view3d_show && ui_view2d_show);
}
void context_set_viewport_mode(viewport_mode_t mode) {
if (mode == g_context->viewport_mode) {
return;
}
viewport_mode_t prev_viewport_mode = g_context->viewport_mode;
g_context->viewport_mode = mode;
if (context_use_deferred()) {
render_path_commands = render_path_deferred_commands;
}
else {
render_path_commands = render_path_forward_commands;
}
make_material_parse_mesh_material();
if (g_context->viewport_mode == VIEWPORT_MODE_PATH_TRACE) {
util_mesh_merge(NULL);
}
// Rotate mode is not supported for path tracing yet
if (g_context->viewport_mode == VIEWPORT_MODE_PATH_TRACE && g_context->camera_controls == CAMERA_CONTROLS_ROTATE) {
g_context->camera_controls = CAMERA_CONTROLS_ORBIT;
viewport_reset();
}
// Bake in lit mode for now
if (g_context->viewport_mode == VIEWPORT_MODE_PATH_TRACE && g_context->tool == TOOL_TYPE_BAKE) {
g_context->viewport_mode = VIEWPORT_MODE_LIT;
}
bool has_sculpt = false;
for (i32 i = 0; i < g_project->_->layers->length; ++i) {
if (g_project->_->layers->buffer[i]->texpaint_sculpt != NULL && slot_layer_is_visible(g_project->_->layers->buffer[i])) {
has_sculpt = true;
break;
}
}
if (has_sculpt) {
if (g_context->viewport_mode == VIEWPORT_MODE_PATH_TRACE) {
sculpt_bake_to_mesh();
}
else if (prev_viewport_mode == VIEWPORT_MODE_PATH_TRACE) {
// Restore un-sculpted mesh
util_mesh_merge(NULL);
}
}
}
void context_set_camera_controls(int i) {
g_context->camera_controls = i;
}
void context_load_envmap() {
if (!g_context->envmap_loaded) {
// TODO: Unable to share texture for both radiance and envmap - reload image
g_context->envmap_loaded = true;
map_delete(data_cached_textures, "World_radiance.k");
}
world_data_load_envmap(scene_world);
if (g_context->saved_envmap == NULL) {
g_context->saved_envmap = scene_world->_->envmap;
}
}
void context_update_envmap() {
if (g_context->show_envmap) {
scene_world->_->envmap = g_context->show_envmap_blur ? scene_world->_->radiance_mipmaps->buffer[0] : g_context->saved_envmap;
}
else {
scene_world->_->envmap = g_context->empty_envmap;
}
}
void context_set_viewport_shader(void *viewport_shader) {
g_context->viewport_shader = viewport_shader;
context_set_render_path();
}
void context_set_render_path_on_next_frame(void *_) {
make_material_parse_mesh_material();
}
void context_set_render_path() {
if (g_config->render_mode == RENDER_MODE_FORWARD || g_context->viewport_shader != NULL) {
render_path_commands = render_path_forward_commands;
}
else {
render_path_commands = render_path_deferred_commands;
}
sys_notify_on_next_frame(&context_set_render_path_on_next_frame, NULL);
}
bool context_enable_import_plugin(char *file) {
// Return plugin name suitable for importing the specified file
if (box_preferences_files_plugin == NULL) {
box_preferences_fetch_plugins();
}
char *ext = substring(file, string_last_index_of(file, ".") + 1, string_length(file));
for (i32 i = 0; i < box_preferences_files_plugin->length; ++i) {
char *f = box_preferences_files_plugin->buffer[i];
if (starts_with(f, "import_") && string_index_of(f, ext) >= 0) {
config_enable_plugin(f);
console_info(string("%s %s", f, tr("plugin enabled")));
return true;
}
}
return false;
}