#include "global.h" context_t *context_create() { context_t *c = GC_ALLOC_INIT(context_t, {0}); c->merged_object_is_atlas = false; // Only objects referenced by atlas are merged c->ddirty = 0; // depth c->pdirty = 0; // paint c->rdirty = 0; // render c->brush_blend_dirty = true; c->split_view = false; c->view_index = -1; c->view_index_last = -1; c->picked_color = project_make_swatch(0xffffffff); c->envmap_loaded = false; c->show_envmap = false; c->show_envmap_handle = ui_handle_create(); c->show_envmap_blur = false; c->show_envmap_blur_handle = ui_handle_create(); c->show_envmap_spheres = false; c->show_envmap_spheres_handle = ui_handle_create(); c->capturing_screenshot = false; c->capture_background = false; c->envmap_angle = 0.0; c->light_angle = 0.0; c->cull_backfaces = true; c->texture_filter = true; c->format_type = TEXTURE_LDR_FORMAT_PNG; c->format_quality = 100.0; c->layers_destination = EXPORT_DESTINATION_DISK; c->split_by = SPLIT_TYPE_OBJECT; c->select_time = 0.0; c->viewport_mode = g_config->viewport_mode; c->hscale_was_changed = false; c->export_mesh_format = MESH_FORMAT_OBJ; c->export_mesh_index = 0; c->pack_assets_on_export = true; c->pack_assets_on_save = false; c->paint_vec = (vec4_t){0.0, 0.0, 0.0, 1.0}; c->last_paint_x = -1.0; c->last_paint_y = -1.0; c->foreground_event = false; c->painted = 0; c->brush_time = 0.0; c->clone_start_x = -1.0; c->clone_start_y = -1.0; c->clone_delta_x = 0.0; c->clone_delta_y = 0.0; c->show_compass = true; c->project_aspect_ratio = 0; // 1:1, 2:1, 1:2 c->last_paint_vec_x = -1.0; c->last_paint_vec_y = -1.0; c->prev_paint_vec_x = -1.0; c->prev_paint_vec_y = -1.0; c->frame = 0; c->paint2d_view = false; c->brush_locked = false; c->camera_type = CAMERA_TYPE_PERSPECTIVE; c->cam_handle = ui_handle_create(); c->fov_handle = ui_handle_create(); c->texture_export_path = ""; c->last_status_position = 0; c->camera_pivot = CAMERA_PIVOT_CURSOR; c->camera_controls = CAMERA_CONTROLS_ORBIT; c->pen_painting_only = false; // Reject painting with finger when using pen c->layer_preview_dirty = true; c->layers_preview_dirty = false; c->node_preview_name = ""; c->node_preview_socket_map = any_map_create(); c->node_preview_map = any_map_create(); c->selected_node_preview = true; c->colorid_picked = false; c->material_preview = false; // Drawing material previews c->saved_camera = mat4_identity(); c->materialid_picked = 0; c->uvx_picked = 0.0; c->uvy_picked = 0.0; c->picker_select_material = false; c->picker_mask_handle = ui_handle_create(); c->pick_pos_nor_tex = false; c->pick_object_id = false; c->posx_picked = 0.0; c->posy_picked = 0.0; c->posz_picked = 0.0; c->norx_picked = 0.0; c->nory_picked = 0.0; c->norz_picked = 0.0; c->draw_wireframe = false; c->wireframe_handle = ui_handle_create(); c->draw_texels = false; c->texels_handle = ui_handle_create(); c->colorid_handle = ui_handle_create(); c->layers_export = EXPORT_MODE_VISIBLE; c->decal_preview = false; c->decal_x = 0.0; c->decal_y = 0.0; // c.cache_draws = false; c->write_icon_on_export = false; c->particle_hit_x = 0.0; c->particle_hit_y = 0.0; c->particle_hit_z = 0.0; c->last_particle_hit_x = 0.0; c->last_particle_hit_y = 0.0; c->last_particle_hit_z = 0.0; c->particle_friction = 0.1; c->particle_bounciness = 0.0; c->particle_gravity_x = 0.0; c->particle_gravity_y = 0.0; c->particle_gravity_z = -9.81; c->particle_lifetime = 5.0; c->particle_mass = 1.0; c->particle_random = 0.1; c->particle_spawn_distance = 0.3; c->layer_filter = 0; c->gizmo_started = false; c->gizmo_offset = 0.0; c->gizmo_drag = 0.0; c->gizmo_drag_last = 0.0; c->translate_x = false; c->translate_y = false; c->translate_z = false; c->scale_x = false; c->scale_y = false; c->scale_z = false; c->rotate_x = false; c->rotate_y = false; c->rotate_z = false; c->brush_nodes_radius = 1.0; c->brush_nodes_opacity = 1.0; c->brush_mask_image_is_alpha = false; c->brush_stencil_image_is_alpha = false; c->brush_stencil_x = 0.02; c->brush_stencil_y = 0.02; c->brush_stencil_scale = 0.9; c->brush_stencil_scaling = false; c->brush_stencil_angle = 0.0; c->brush_stencil_rotating = false; c->brush_nodes_scale = 1.0; c->brush_nodes_angle = 0.0; c->brush_nodes_hardness = 1.0; c->brush_directional = false; c->brush_scale_x = 1.0; c->brush_decal_mask_radius = 0.5; c->brush_decal_mask_radius_handle = ui_handle_create(); c->brush_decal_mask_radius_handle->f = 0.5; c->brush_scale_x_handle = ui_handle_create(); c->brush_scale_x_handle->f = 1.0; c->brush_blending = BLEND_TYPE_MIX; c->brush_opacity = 1.0; c->brush_opacity_handle = ui_handle_create(); c->brush_opacity_handle->f = 1.0; c->brush_scale = 1.0; c->brush_angle = 0.0; c->brush_angle_handle = ui_handle_create(); c->brush_angle_handle->f = 0.0; c->brush_lazy_radius = 0.0; c->brush_lazy_step = 0.0; c->brush_lazy_x = 0.0; c->brush_lazy_y = 0.0; c->brush_paint = UV_TYPE_UVMAP; c->brush_angle_reject_dot = 0.5; c->bake_type = BAKE_TYPE_CURVATURE; c->bake_axis = BAKE_AXIS_XYZ; c->bake_up_axis = BAKE_UP_AXIS_Z; c->bake_samples = 128; c->bake_ao_strength = 1.0; c->bake_ao_radius = 1.0; c->bake_ao_offset = 1.0; c->bake_curv_strength = 1.0; c->bake_curv_radius = 1.0; c->bake_curv_offset = 0.0; c->bake_curv_smooth = 1; c->bake_high_poly = 0; c->xray = false; c->sym_x = false; c->sym_y = false; c->sym_z = false; c->fill_type_handle = ui_handle_create(); c->blur_type_handle = ui_handle_create(); c->blur_type = BLUR_TYPE_BLUR; c->paint2d = false; c->maximized_sidebar_width = 0; c->drag_dest = 0; return c; } void context_init() { g_context = context_create(); gc_root(g_context); 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; } 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 (project_materials->length <= i) { return; } context_set_material(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(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; gc_unroot(ui_nodes_group_stack); ui_nodes_group_stack = any_array_create_from_raw((void *[]){}, 0); gc_root(ui_nodes_group_stack); 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 (project_brushes->length <= i) { return; } context_set_brush(project_brushes->buffer[i]); } void context_set_brush(slot_brush_t *b) { if (array_index_of(project_brushes, b) == -1) { return; } g_context->brush = b; make_material_parse_brush(); 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(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 (project_fonts->length <= i) { return; } context_set_font(project_fonts->buffer[i]); } void context_select_layer(i32 i) { if (project_layers->length <= i) { return; } context_set_layer(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 < project_paint_objects->length; ++i) { mesh_object_t *p = project_paint_objects->buffer[i]; p->skip_context = "paint"; } // #ifdef is_forge // g_context->paint_object->skip_context = ""; // #endif 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 < project_paint_objects->length; ++i) { mesh_object_t *po = project_paint_objects->buffer[i]; if (po->base->children->length > 0) { return po; } } return project_paint_objects->buffer[0]; } bool context_layer_filter_used() { return g_context->layer_filter > 0 && g_context->layer_filter <= 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) <= 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_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_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_is_decal() { return g_context->tool == TOOL_TYPE_DECAL || g_context->tool == TOOL_TYPE_TEXT; } bool context_is_decal_mask() { return context_is_decal() && operator_shortcut(any_map_get(config_keymap, "decal_mask"), SHORTCUT_TYPE_DOWN); } bool context_is_decal_camera_align() { return context_is_decal() && (g_context->decal_camera_align || operator_shortcut(any_map_get(config_keymap, "decal_camera_align"), SHORTCUT_TYPE_DOWN)); } bool context_is_decal_mask_paint() { return context_is_decal() && operator_shortcut(string("%s+%s", any_map_get(config_keymap, "decal_mask"), any_map_get(config_keymap, "action_paint")), SHORTCUT_TYPE_DOWN); } 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; } g_context->viewport_mode = mode; if (context_use_deferred()) { gc_unroot(render_path_commands); render_path_commands = render_path_deferred_commands; gc_root(render_path_commands); } else { gc_unroot(render_path_commands); render_path_commands = render_path_forward_commands; gc_root(render_path_commands); } make_material_parse_mesh_material(); // 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; } } 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_images, "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) { gc_unroot(render_path_commands); render_path_commands = render_path_forward_commands; gc_root(render_path_commands); } else { gc_unroot(render_path_commands); render_path_commands = render_path_deferred_commands; gc_root(render_path_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; } void context_set_swatch(swatch_color_t *s) { g_context->swatch = s; }