+ v3f baseangles;
+ player_vector_angles( baseangles, basevector, 1.0f, 0.0f );
+
+ v2_add( workshop_form.view_angles, baseangles, cam.angles );
+ cam.angles[2] = 0.0f;
+
+ float sX = sinf( cam.angles[0] ),
+ cX = cosf( cam.angles[0] ),
+ sY = sinf( cam.angles[1] ),
+ cY = cosf( cam.angles[1] );
+
+ v3f offset = { -sX * cY, sY, cX * cY };
+
+ v3_muladds( display->transform.co, offset,
+ dist*workshop_form.view_dist, cam.pos );
+
+ cam.pos[0] += -sX*workshop_form.view_offset[2];
+ cam.pos[2] += cX*workshop_form.view_offset[2];
+ cam.pos[0] += cX*workshop_form.view_offset[0];
+ cam.pos[2] += sX*workshop_form.view_offset[0];
+ cam.pos[1] += workshop_form.view_offset[1];
+
+ cam.nearz = 0.01f;
+ cam.farz = 100.0f;
+ cam.fov = ref->fov;
+
+ camera_update_transform( &cam );
+ camera_update_view( &cam );
+ camera_update_projection( &cam );
+ camera_finalize( &cam );
+
+ m4x3f mmdl, mmdl1;
+ mdl_transform_m4x3( &display->transform, mmdl );
+ mdl_transform_m4x3( &display1->transform, mmdl1 );
+
+ /* force update this for nice shadows. its usually set in the world
+ * pre-render step, but that includes timer stuff
+ */
+ struct player_board *board = &workshop_form.board_model;
+ struct ub_world_lighting *ubo = &world->ub_lighting;
+ v3f vp0, vp1;
+ v3_copy((v3f){0.0f,0.1f, board->truck_positions[0][2]}, vp0 );
+ v3_copy((v3f){0.0f,0.1f, board->truck_positions[1][2]}, vp1 );
+ m4x3_mulv( mmdl1, vp0, ubo->g_board_0 );
+ m4x3_mulv( mmdl1, vp1, ubo->g_board_1 );
+ glBindBuffer( GL_UNIFORM_BUFFER, world->ubo_lighting );
+ glBufferSubData( GL_UNIFORM_BUFFER, 0,
+ sizeof(struct ub_world_lighting), &world->ub_lighting );
+
+ render_world( world, &cam, 1 );
+ render_board( &cam, world, board, mmdl, k_board_shader_entity );
+ render_board( &cam, world, board, mmdl1, k_board_shader_entity );
+
+ glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+ glViewport( 0,0, vg.window_x, vg.window_y );
+}
+
+/*
+ * ImGUI section for workshop form
+ * -----------------------------------------------------------------------------
+ */
+
+VG_STATIC void workshop_changed_model_path( char *buf, u32 len ){
+ workshop_form.submission.submit_file_and_image = 1;
+}
+
+VG_STATIC void workshop_changed_title( char *buf, u32 len ){
+ workshop_form.submission.submit_title = 1;
+}
+
+VG_STATIC void workshop_changed_description( char *buf, u32 len ){
+ workshop_form.submission.submit_description = 1;
+}
+
+VG_STATIC void workshop_form_gui_edit_page( ui_rect content )
+{
+ if( workshop_form.submission.type == k_workshop_file_type_none ){
+ ui_rect box;
+ rect_copy( content, box );
+ box[3] = 128;
+ box[2] = (box[2]*2)/3;
+ ui_rect_center( content, box );
+
+ ui_rect row;
+ ui_split( box, k_ui_axis_h, 28, 0, row, box );
+ ui_text( row, "Select the type of item\n", 1, k_ui_align_middle_center,0);
+ ui_split( box, k_ui_axis_h, 28, 0, row, box );
+ ui_enum( row, "Type:", workshop_form_type_opts,
+ 3, &workshop_form.submission.submission_type_selection );
+ ui_split( box, k_ui_axis_h, 8, 0, row, box );
+ ui_split( box, k_ui_axis_h, 28, 0, row, box );
+
+ ui_rect button_l, button_r;
+ rect_copy( row, button_l );
+ button_l[2] = 128*2;
+ ui_rect_center( row, button_l );
+ ui_split_ratio( button_l, k_ui_axis_v, 0.5f, 2, button_l, button_r );
+
+ if( workshop_form.submission.submission_type_selection.value !=
+ k_workshop_file_type_none ){
+ if( ui_button_text( button_l, "OK", 1 ) ){
+ workshop_form.submission.type =
+ workshop_form.submission.submission_type_selection.value;
+ }
+ }
+ else{
+ ui_fill( button_l, ui_colour(k_ui_bg) );
+ ui_text( button_l, "OK", 1, k_ui_align_middle_center,
+ ui_colour(k_ui_bg+4) );
+ }
+
+ if( ui_button_text( button_r, "Cancel", 1 ) ){
+ workshop_form.page = k_workshop_form_open;
+ workshop_form.file_intent = k_workshop_form_file_intent_none;
+ }
+ return;