summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--3rdparty/bgfx/.gitignore1
-rw-r--r--3rdparty/bgfx/3rdparty/dxsdk/include/d3d10.h8
-rw-r--r--3rdparty/bgfx/3rdparty/dxsdk/include/d3dx12.h40
-rw-r--r--3rdparty/bgfx/3rdparty/dxsdk/include/dxgitype.h48
-rw-r--r--3rdparty/bgfx/3rdparty/glsl-optimizer/Changelog.md12
-rw-r--r--3rdparty/bgfx/3rdparty/glsl-optimizer/projects/vs2010/glsl_optimizer_lib.vcxproj1
-rw-r--r--3rdparty/bgfx/3rdparty/glsl-optimizer/projects/vs2010/glsl_optimizer_lib.vcxproj.filters3
-rw-r--r--3rdparty/bgfx/3rdparty/glsl-optimizer/projects/xcode5/glsl_optimizer_lib.xcodeproj/project.pbxproj4
-rw-r--r--3rdparty/bgfx/3rdparty/glsl-optimizer/src/glsl/Makefile1
-rw-r--r--3rdparty/bgfx/3rdparty/glsl-optimizer/src/glsl/glsl_optimizer.cpp14
-rw-r--r--3rdparty/bgfx/3rdparty/glsl-optimizer/src/glsl/glsl_optimizer.h2
-rw-r--r--3rdparty/bgfx/3rdparty/glsl-optimizer/src/glsl/ir_optimization.h8
-rw-r--r--3rdparty/bgfx/3rdparty/glsl-optimizer/src/glsl/ir_print_glsl_visitor.cpp8
-rw-r--r--3rdparty/bgfx/3rdparty/glsl-optimizer/src/glsl/ir_print_metal_visitor.cpp27
-rw-r--r--3rdparty/bgfx/3rdparty/glsl-optimizer/src/glsl/opt_vector_splitting.cpp485
-rw-r--r--3rdparty/bgfx/3rdparty/glsl-optimizer/src/glsl_optimizer_lib.gyp1
-rw-r--r--3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/tex2DArray-in.txt20
-rw-r--r--3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/tex2DArray-inES3.txt19
-rw-r--r--3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/tex2DArray-out.txt14
-rw-r--r--3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/tex2DArray-outES3.txt33
-rw-r--r--3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/tex2DArray-outES3Metal.txt42
-rw-r--r--3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/tex2dshadow-out.txt2
-rw-r--r--3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/tex2dshadow-outES.txt2
-rw-r--r--3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/tex2dshadow-outES3.txt2
-rw-r--r--3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/tex2dshadow-outES3Metal.txt2
-rw-r--r--3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/texProj-outES.txt2
-rw-r--r--3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/texProj-outES3.txt2
-rw-r--r--3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/texProj-outES3Metal.txt2
-rw-r--r--3rdparty/bgfx/3rdparty/glsl-optimizer/tests/glsl_optimizer_tests.cpp2
-rw-r--r--3rdparty/bgfx/3rdparty/glsl-optimizer/tests/vertex/loops-for-withvec4-out.txt72
-rw-r--r--3rdparty/bgfx/3rdparty/glsl-optimizer/tests/vertex/loops-for-withvec4-outES3.txt72
-rw-r--r--3rdparty/bgfx/3rdparty/glsl-optimizer/tests/vertex/loops-for-withvec4-outES3Metal.txt66
-rw-r--r--3rdparty/bgfx/3rdparty/ocornut-imgui/imconfig.h3
-rw-r--r--3rdparty/bgfx/3rdparty/ocornut-imgui/imgui.cpp339
-rw-r--r--3rdparty/bgfx/3rdparty/ocornut-imgui/imgui.h49
-rw-r--r--3rdparty/bgfx/3rdparty/ocornut-imgui/imgui_demo.cpp40
-rw-r--r--3rdparty/bgfx/3rdparty/ocornut-imgui/imgui_draw.cpp28
-rw-r--r--3rdparty/bgfx/3rdparty/ocornut-imgui/imgui_internal.h28
-rw-r--r--3rdparty/bgfx/3rdparty/ocornut-imgui/imgui_wm.cpp1686
-rw-r--r--3rdparty/bgfx/3rdparty/ocornut-imgui/imgui_wm.h310
-rw-r--r--3rdparty/bgfx/3rdparty/renderdoc/renderdoc_app.h627
-rw-r--r--3rdparty/bgfx/3rdparty/scintilla/gtk/makefile.orig105
-rw-r--r--3rdparty/bgfx/3rdparty/scintilla/src/Editor.cxx.orig9647
-rw-r--r--3rdparty/bgfx/3rdparty/stb/stb_image.c8
-rw-r--r--3rdparty/bgfx/3rdparty/stb/stb_truetype.h2
-rw-r--r--3rdparty/bgfx/README.md5
-rw-r--r--3rdparty/bgfx/examples/00-helloworld/helloworld.cpp2
-rw-r--r--3rdparty/bgfx/examples/02-metaballs/metaballs.cpp7
-rw-r--r--3rdparty/bgfx/examples/08-update/update.cpp23
-rw-r--r--3rdparty/bgfx/examples/10-font/font.cpp2
-rw-r--r--3rdparty/bgfx/examples/11-fontsdf/fontsdf.cpp2
-rw-r--r--3rdparty/bgfx/examples/13-stencil/stencil.cpp2
-rw-r--r--3rdparty/bgfx/examples/14-shadowvolumes/shadowvolumes.cpp2
-rw-r--r--3rdparty/bgfx/examples/15-shadowmaps-simple/shadowmaps_simple.cpp3
-rw-r--r--3rdparty/bgfx/examples/16-shadowmaps/shadowmaps.cpp2
-rw-r--r--3rdparty/bgfx/examples/17-drawstress/drawstress.cpp7
-rw-r--r--3rdparty/bgfx/examples/19-oit/oit.cpp8
-rw-r--r--3rdparty/bgfx/examples/20-nanovg/nanovg.cpp2
-rw-r--r--3rdparty/bgfx/examples/21-deferred/deferred.cpp15
-rw-r--r--3rdparty/bgfx/examples/23-vectordisplay/vectordisplay.cpp4
-rw-r--r--3rdparty/bgfx/examples/23-vectordisplay/vectordisplay.h2
-rw-r--r--3rdparty/bgfx/examples/24-nbody/nbody.cpp2
-rw-r--r--3rdparty/bgfx/examples/25-c99/helloworld.c2
-rw-r--r--3rdparty/bgfx/examples/common/bgfx_utils.cpp2
-rw-r--r--3rdparty/bgfx/examples/common/bgfx_utils.h2
-rw-r--r--3rdparty/bgfx/examples/common/cube_atlas.cpp2
-rw-r--r--3rdparty/bgfx/examples/common/cube_atlas.h2
-rw-r--r--3rdparty/bgfx/examples/common/entry/entry.cpp2
-rw-r--r--3rdparty/bgfx/examples/common/entry/entry_android.cpp2
-rw-r--r--3rdparty/bgfx/examples/common/entry/entry_glfw.cpp2
-rw-r--r--3rdparty/bgfx/examples/common/entry/entry_ios.mm2
-rw-r--r--3rdparty/bgfx/examples/common/entry/entry_nacl.cpp4
-rw-r--r--3rdparty/bgfx/examples/common/entry/entry_osx.mm2
-rw-r--r--3rdparty/bgfx/examples/common/entry/entry_sdl.cpp2
-rw-r--r--3rdparty/bgfx/examples/common/entry/entry_windows.cpp43
-rw-r--r--3rdparty/bgfx/examples/common/entry/entry_winrt.cpp2
-rw-r--r--3rdparty/bgfx/examples/common/entry/entry_x11.cpp92
-rw-r--r--3rdparty/bgfx/examples/common/font/font_manager.cpp2
-rw-r--r--3rdparty/bgfx/examples/common/font/font_manager.h2
-rw-r--r--3rdparty/bgfx/examples/common/font/text_buffer_manager.cpp25
-rw-r--r--3rdparty/bgfx/examples/common/imgui/imgui.cpp6
-rw-r--r--3rdparty/bgfx/examples/common/imgui/imgui.h64
-rw-r--r--3rdparty/bgfx/examples/common/imgui/ocornut_imgui.cpp493
-rw-r--r--3rdparty/bgfx/examples/common/imgui/scintilla.cpp4
-rw-r--r--3rdparty/bgfx/examples/common/nanovg/nanovg_bgfx.cpp3
-rw-r--r--3rdparty/bgfx/examples/makefile20
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_bump.binbin0 -> 5921 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_callback.binbin0 -> 804 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_cubes.binbin0 -> 404 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_deferred_combine.binbin0 -> 1196 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_deferred_debug.binbin0 -> 598 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_deferred_debug_line.binbin0 -> 404 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_deferred_geom.binbin0 -> 1605 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_deferred_light.binbin0 -> 2518 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_hdr_blur.binbin0 -> 2044 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_hdr_bright.binbin0 -> 3656 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_hdr_lum.binbin0 -> 3492 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_hdr_lumavg.binbin0 -> 4916 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_hdr_mesh.binbin0 -> 2434 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_hdr_skybox.binbin0 -> 1054 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_hdr_tonemap.binbin0 -> 4043 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_ibl_mesh.binbin0 -> 2838 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_ibl_skybox.binbin0 -> 1086 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_instancing.binbin0 -> 404 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_mesh.binbin0 -> 1720 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_oit.binbin0 -> 402 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_oit_wb.binbin0 -> 750 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_oit_wb_blit.binbin0 -> 933 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_oit_wb_separate.binbin0 -> 683 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_oit_wb_separate_blit.binbin0 -> 933 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_particle.binbin0 -> 694 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_raymarching.binbin0 -> 12676 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_black.binbin0 -> 396 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_esm.binbin0 -> 4597 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_esm_csm.binbin0 -> 11097 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_esm_linear.binbin0 -> 4641 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_esm_linear_csm.binbin0 -> 11317 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_esm_linear_omni.binbin0 -> 7861 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_esm_omni.binbin0 -> 7815 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_hard.binbin0 -> 4425 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_hard_csm.binbin0 -> 10377 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_hard_linear.binbin0 -> 4457 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_hard_linear_csm.binbin0 -> 10513 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_hard_linear_omni.binbin0 -> 7678 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_hard_omni.binbin0 -> 7644 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_pcf.binbin0 -> 16606 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_pcf_csm.binbin0 -> 66411 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_pcf_linear.binbin0 -> 16555 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_pcf_linear_csm.binbin0 -> 66449 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_pcf_linear_omni.binbin0 -> 19991 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_pcf_omni.binbin0 -> 19940 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_vsm.binbin0 -> 5037 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_vsm_csm.binbin0 -> 13099 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_vsm_linear.binbin0 -> 5081 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_vsm_linear_csm.binbin0 -> 13319 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_vsm_linear_omni.binbin0 -> 8303 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_vsm_omni.binbin0 -> 8257 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_texture.binbin0 -> 1045 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_hblur.binbin0 -> 2840 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_hblur_vsm.binbin0 -> 3934 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_packdepth.binbin0 -> 623 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_packdepth_linear.binbin0 -> 566 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_packdepth_vsm.binbin0 -> 807 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_packdepth_vsm_linear.binbin0 -> 729 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_texture.binbin0 -> 598 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_unpackdepth.binbin0 -> 815 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_unpackdepth_vsm.binbin0 -> 790 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_vblur.binbin0 -> 2840 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_vblur_vsm.binbin0 -> 3934 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_color_lightning.binbin0 -> 2666 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_color_texture.binbin0 -> 1045 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svbackblank.binbin0 -> 396 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svbackcolor.binbin0 -> 442 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svbacktex1.binbin0 -> 794 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svbacktex2.binbin0 -> 794 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svfrontblank.binbin0 -> 426 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svfrontcolor.binbin0 -> 442 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svfronttex1.binbin0 -> 791 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svfronttex2.binbin0 -> 791 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svside.binbin0 -> 823 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svsideblank.binbin0 -> 396 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svsidecolor.binbin0 -> 442 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svsidetex.binbin0 -> 905 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_texture.binbin0 -> 598 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_texture_lightning.binbin0 -> 3054 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_sms_mesh.binbin0 -> 9729 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_sms_mesh_pd.binbin0 -> 9605 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_sms_shadow.binbin0 -> 396 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_sms_shadow_pd.binbin0 -> 623 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_stencil_color_black.binbin0 -> 396 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_stencil_color_lightning.binbin0 -> 2345 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_stencil_color_texture.binbin0 -> 1045 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_stencil_texture.binbin0 -> 598 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_stencil_texture_lightning.binbin0 -> 2745 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_tree.binbin0 -> 1846 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_update.binbin0 -> 596 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_update_3d.binbin0 -> 737 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_update_cmp.binbin0 -> 644 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_vectordisplay_blit.binbin0 -> 824 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_vectordisplay_blur.binbin0 -> 3314 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/fs_vectordisplay_fb.binbin0 -> 796 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_bump.binbin0 -> 2038 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_bump_instanced.binbin0 -> 2272 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_callback.binbin0 -> 819 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_cubes.binbin0 -> 647 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_deferred_combine.binbin0 -> 659 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_deferred_debug.binbin0 -> 659 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_deferred_debug_line.binbin0 -> 647 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_deferred_geom.binbin0 -> 2038 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_deferred_light.binbin0 -> 659 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_hdr_blur.binbin0 -> 1880 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_hdr_bright.binbin0 -> 659 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_hdr_lum.binbin0 -> 659 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_hdr_lumavg.binbin0 -> 659 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_hdr_mesh.binbin0 -> 984 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_hdr_skybox.binbin0 -> 659 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_hdr_tonemap.binbin0 -> 1782 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_ibl_mesh.binbin0 -> 979 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_ibl_skybox.binbin0 -> 781 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_instancing.binbin0 -> 987 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_mesh.binbin0 -> 1749 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_oit.binbin0 -> 898 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_oit_blit.binbin0 -> 659 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_particle.binbin0 -> 1204 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_raymarching.binbin0 -> 751 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_color.binbin0 -> 555 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_color_lightning.binbin0 -> 1223 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_color_lightning_csm.binbin0 -> 1751 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_color_lightning_linear.binbin0 -> 1282 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_color_lightning_linear_csm.binbin0 -> 1971 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_color_lightning_linear_omni.binbin0 -> 1913 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_color_lightning_omni.binbin0 -> 1693 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_color_texture.binbin0 -> 659 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_depth.binbin0 -> 555 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_hblur.binbin0 -> 1835 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_packdepth.binbin0 -> 618 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_packdepth_linear.binbin0 -> 629 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_texture.binbin0 -> 659 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_texture_lightning.binbin0 -> 1035 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_unpackdepth.binbin0 -> 659 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_vblur.binbin0 -> 1835 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowvolume_color_lightning.binbin0 -> 931 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowvolume_color_texture.binbin0 -> 659 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowvolume_svback.binbin0 -> 730 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowvolume_svfront.binbin0 -> 555 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowvolume_svside.binbin0 -> 931 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowvolume_texture.binbin0 -> 659 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowvolume_texture_lightning.binbin0 -> 1035 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_sms_mesh.binbin0 -> 1190 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_sms_shadow.binbin0 -> 555 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_sms_shadow_pd.binbin0 -> 618 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_stencil_color.binbin0 -> 555 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_stencil_color_lightning.binbin0 -> 931 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_stencil_color_texture.binbin0 -> 659 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_stencil_texture.binbin0 -> 659 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_stencil_texture_lightning.binbin0 -> 1035 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_tree.binbin0 -> 1113 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_update.binbin0 -> 659 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/shaders/metal/vs_vectordisplay_fb.binbin0 -> 751 bytes
-rw-r--r--3rdparty/bgfx/examples/runtime/tvos-info.plist30
-rw-r--r--3rdparty/bgfx/include/bgfx/bgfx.h (renamed from 3rdparty/bgfx/include/bgfx.h)21
-rw-r--r--3rdparty/bgfx/include/bgfx/bgfxdefines.h (renamed from 3rdparty/bgfx/include/bgfxdefines.h)50
-rw-r--r--3rdparty/bgfx/include/bgfx/bgfxplatform.h (renamed from 3rdparty/bgfx/include/bgfxplatform.h)0
-rw-r--r--3rdparty/bgfx/include/bgfx/c99/bgfx.h (renamed from 3rdparty/bgfx/include/bgfx.c99.h)5
-rw-r--r--3rdparty/bgfx/include/bgfx/c99/bgfxplatform.h (renamed from 3rdparty/bgfx/include/bgfxplatform.c99.h)0
-rw-r--r--3rdparty/bgfx/scripts/bgfx.lua8
-rw-r--r--3rdparty/bgfx/scripts/example-common.lua2
-rw-r--r--3rdparty/bgfx/scripts/genie.lua17
-rw-r--r--3rdparty/bgfx/src/bgfx.cpp154
-rw-r--r--3rdparty/bgfx/src/bgfx_p.h127
-rw-r--r--3rdparty/bgfx/src/config.h15
-rw-r--r--3rdparty/bgfx/src/glcontext_ppapi.cpp2
-rw-r--r--3rdparty/bgfx/src/glimports.h5
-rw-r--r--3rdparty/bgfx/src/image.cpp2
-rw-r--r--3rdparty/bgfx/src/renderdoc.cpp57
-rw-r--r--3rdparty/bgfx/src/renderer_d3d11.cpp251
-rw-r--r--3rdparty/bgfx/src/renderer_d3d11.h11
-rw-r--r--3rdparty/bgfx/src/renderer_d3d12.cpp139
-rw-r--r--3rdparty/bgfx/src/renderer_d3d12.h6
-rw-r--r--3rdparty/bgfx/src/renderer_d3d9.cpp70
-rw-r--r--3rdparty/bgfx/src/renderer_d3d9.h6
-rw-r--r--3rdparty/bgfx/src/renderer_gl.cpp164
-rw-r--r--3rdparty/bgfx/src/renderer_gl.h20
-rw-r--r--3rdparty/bgfx/src/renderer_mtl.h466
-rw-r--r--3rdparty/bgfx/src/renderer_mtl.mm490
-rw-r--r--3rdparty/bgfx/src/shader_dxbc.cpp2
-rw-r--r--3rdparty/bgfx/src/vertexdecl.h2
-rw-r--r--3rdparty/bgfx/tools/geometryc/geometryc.cpp10
268 files changed, 14848 insertions, 2045 deletions
diff --git a/3rdparty/bgfx/.gitignore b/3rdparty/bgfx/.gitignore
index 728a1d0fe01..3f3804ea8ea 100644
--- a/3rdparty/bgfx/.gitignore
+++ b/3rdparty/bgfx/.gitignore
@@ -4,3 +4,4 @@
.git
.svn
tags
+.gdb_history
diff --git a/3rdparty/bgfx/3rdparty/dxsdk/include/d3d10.h b/3rdparty/bgfx/3rdparty/dxsdk/include/d3d10.h
index 4d89fc479ce..980838b336d 100644
--- a/3rdparty/bgfx/3rdparty/dxsdk/include/d3d10.h
+++ b/3rdparty/bgfx/3rdparty/dxsdk/include/d3d10.h
@@ -1667,7 +1667,7 @@ struct CD3D10_BUFFER_DESC : public D3D10_BUFFER_DESC
MiscFlags = miscFlags;
}
~CD3D10_BUFFER_DESC() {}
- operator const D3D10_BUFFER_DESC&() const { return *this; }
+// operator const D3D10_BUFFER_DESC&() const { return *this; }
};
#endif
@@ -1894,7 +1894,7 @@ struct CD3D10_TEXTURE1D_DESC : public D3D10_TEXTURE1D_DESC
MiscFlags = miscFlags;
}
~CD3D10_TEXTURE1D_DESC() {}
- operator const D3D10_TEXTURE1D_DESC&() const { return *this; }
+// operator const D3D10_TEXTURE1D_DESC&() const { return *this; }
};
#endif
@@ -2137,7 +2137,7 @@ struct CD3D10_TEXTURE2D_DESC : public D3D10_TEXTURE2D_DESC
MiscFlags = miscFlags;
}
~CD3D10_TEXTURE2D_DESC() {}
- operator const D3D10_TEXTURE2D_DESC&() const { return *this; }
+// operator const D3D10_TEXTURE2D_DESC&() const { return *this; }
};
#endif
typedef struct D3D10_MAPPED_TEXTURE2D
@@ -2381,7 +2381,7 @@ struct CD3D10_TEXTURE3D_DESC : public D3D10_TEXTURE3D_DESC
MiscFlags = miscFlags;
}
~CD3D10_TEXTURE3D_DESC() {}
- operator const D3D10_TEXTURE3D_DESC&() const { return *this; }
+// operator const D3D10_TEXTURE3D_DESC&() const { return *this; }
};
#endif
typedef struct D3D10_MAPPED_TEXTURE3D
diff --git a/3rdparty/bgfx/3rdparty/dxsdk/include/d3dx12.h b/3rdparty/bgfx/3rdparty/dxsdk/include/d3dx12.h
index ba59dfc7068..6b5e97d858a 100644
--- a/3rdparty/bgfx/3rdparty/dxsdk/include/d3dx12.h
+++ b/3rdparty/bgfx/3rdparty/dxsdk/include/d3dx12.h
@@ -48,7 +48,7 @@ struct CD3DX12_RECT : public D3D12_RECT
bottom = Bottom;
}
~CD3DX12_RECT() {}
- operator const D3D12_RECT&() const { return *this; }
+// operator const D3D12_RECT&() const { return *this; }
};
//------------------------------------------------------------------------------------------------
@@ -99,7 +99,7 @@ struct CD3DX12_BOX : public D3D12_BOX
back = Back;
}
~CD3DX12_BOX() {}
- operator const D3D12_BOX&() const { return *this; }
+// operator const D3D12_BOX&() const { return *this; }
};
inline bool operator==( const D3D12_BOX& l, const D3D12_BOX& r )
{
@@ -162,7 +162,7 @@ struct CD3DX12_DEPTH_STENCIL_DESC : public D3D12_DEPTH_STENCIL_DESC
BackFace.StencilFunc = backStencilFunc;
}
~CD3DX12_DEPTH_STENCIL_DESC() {}
- operator const D3D12_DEPTH_STENCIL_DESC&() const { return *this; }
+// operator const D3D12_DEPTH_STENCIL_DESC&() const { return *this; }
};
//------------------------------------------------------------------------------------------------
@@ -189,7 +189,7 @@ struct CD3DX12_BLEND_DESC : public D3D12_BLEND_DESC
RenderTarget[ i ] = defaultRenderTargetBlendDesc;
}
~CD3DX12_BLEND_DESC() {}
- operator const D3D12_BLEND_DESC&() const { return *this; }
+// operator const D3D12_BLEND_DESC&() const { return *this; }
};
//------------------------------------------------------------------------------------------------
@@ -240,7 +240,7 @@ struct CD3DX12_RASTERIZER_DESC : public D3D12_RASTERIZER_DESC
ConservativeRaster = conservativeRaster;
}
~CD3DX12_RASTERIZER_DESC() {}
- operator const D3D12_RASTERIZER_DESC&() const { return *this; }
+// operator const D3D12_RASTERIZER_DESC&() const { return *this; }
};
//------------------------------------------------------------------------------------------------
@@ -258,7 +258,7 @@ struct CD3DX12_RESOURCE_ALLOCATION_INFO : public D3D12_RESOURCE_ALLOCATION_INFO
SizeInBytes = size;
Alignment = alignment;
}
- operator const D3D12_RESOURCE_ALLOCATION_INFO&() const { return *this; }
+// operator const D3D12_RESOURCE_ALLOCATION_INFO&() const { return *this; }
};
//------------------------------------------------------------------------------------------------
@@ -292,7 +292,7 @@ struct CD3DX12_HEAP_PROPERTIES : public D3D12_HEAP_PROPERTIES
CreationNodeMask = creationNodeMask;
VisibleNodeMask = nodeMask;
}
- operator const D3D12_HEAP_PROPERTIES&() const { return *this; }
+// operator const D3D12_HEAP_PROPERTIES&() const { return *this; }
bool IsCPUAccessible() const
{
return Type == D3D12_HEAP_TYPE_UPLOAD || Type == D3D12_HEAP_TYPE_READBACK || (Type == D3D12_HEAP_TYPE_CUSTOM &&
@@ -382,7 +382,7 @@ struct CD3DX12_HEAP_DESC : public D3D12_HEAP_DESC
Alignment = resAllocInfo.Alignment;
Flags = flags;
}
- operator const D3D12_HEAP_DESC&() const { return *this; }
+// operator const D3D12_HEAP_DESC&() const { return *this; }
bool IsCPUAccessible() const
{ return static_cast< const CD3DX12_HEAP_PROPERTIES* >( &Properties )->IsCPUAccessible(); }
};
@@ -421,7 +421,7 @@ struct CD3DX12_CLEAR_VALUE : public D3D12_CLEAR_VALUE
memcpy( &DepthStencil.Depth, &depth, sizeof( depth ) );
DepthStencil.Stencil = stencil;
}
- operator const D3D12_CLEAR_VALUE&() const { return *this; }
+// operator const D3D12_CLEAR_VALUE&() const { return *this; }
};
//------------------------------------------------------------------------------------------------
@@ -439,7 +439,7 @@ struct CD3DX12_RANGE : public D3D12_RANGE
Begin = begin;
End = end;
}
- operator const D3D12_RANGE&() const { return *this; }
+// operator const D3D12_RANGE&() const { return *this; }
};
//------------------------------------------------------------------------------------------------
@@ -461,7 +461,7 @@ struct CD3DX12_TILED_RESOURCE_COORDINATE : public D3D12_TILED_RESOURCE_COORDINAT
Z = z;
Subresource = subresource;
}
- operator const D3D12_TILED_RESOURCE_COORDINATE&() const { return *this; }
+// operator const D3D12_TILED_RESOURCE_COORDINATE&() const { return *this; }
};
//------------------------------------------------------------------------------------------------
@@ -485,7 +485,7 @@ struct CD3DX12_TILE_REGION_SIZE : public D3D12_TILE_REGION_SIZE
Height = height;
Depth = depth;
}
- operator const D3D12_TILE_REGION_SIZE&() const { return *this; }
+// operator const D3D12_TILE_REGION_SIZE&() const { return *this; }
};
//------------------------------------------------------------------------------------------------
@@ -507,7 +507,7 @@ struct CD3DX12_SUBRESOURCE_TILING : public D3D12_SUBRESOURCE_TILING
DepthInTiles = depthInTiles;
StartTileIndexInOverallResource = startTileIndexInOverallResource;
}
- operator const D3D12_SUBRESOURCE_TILING&() const { return *this; }
+// operator const D3D12_SUBRESOURCE_TILING&() const { return *this; }
};
//------------------------------------------------------------------------------------------------
@@ -527,7 +527,7 @@ struct CD3DX12_TILE_SHAPE : public D3D12_TILE_SHAPE
HeightInTexels = heightInTexels;
DepthInTexels = depthInTexels;
}
- operator const D3D12_TILE_SHAPE&() const { return *this; }
+// operator const D3D12_TILE_SHAPE&() const { return *this; }
};
//------------------------------------------------------------------------------------------------
@@ -578,7 +578,7 @@ struct CD3DX12_RESOURCE_BARRIER : public D3D12_RESOURCE_BARRIER
barrier.UAV.pResource = pResource;
return result;
}
- operator const D3D12_RESOURCE_BARRIER&() const { return *this; }
+// operator const D3D12_RESOURCE_BARRIER&() const { return *this; }
};
//------------------------------------------------------------------------------------------------
@@ -600,7 +600,7 @@ struct CD3DX12_PACKED_MIP_INFO : public D3D12_PACKED_MIP_INFO
NumTilesForPackedMips = numTilesForPackedMips;
StartTileIndexInOverallResource = startTileIndexInOverallResource;
}
- operator const D3D12_PACKED_MIP_INFO&() const { return *this; }
+// operator const D3D12_PACKED_MIP_INFO&() const { return *this; }
};
//------------------------------------------------------------------------------------------------
@@ -634,7 +634,7 @@ struct CD3DX12_SUBRESOURCE_FOOTPRINT : public D3D12_SUBRESOURCE_FOOTPRINT
Depth = (resDesc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D ? resDesc.DepthOrArraySize : 1);
RowPitch = rowPitch;
}
- operator const D3D12_SUBRESOURCE_FOOTPRINT&() const { return *this; }
+// operator const D3D12_SUBRESOURCE_FOOTPRINT&() const { return *this; }
};
//------------------------------------------------------------------------------------------------
@@ -1304,7 +1304,7 @@ struct CD3DX12_RESOURCE_DESC : public D3D12_RESOURCE_DESC
{ return MipLevels * ArraySize() * PlaneCount(pDevice); }
inline UINT CalcSubresource(UINT MipSlice, UINT ArraySlice, UINT PlaneSlice)
{ return D3D12CalcSubresource(MipSlice, ArraySlice, PlaneSlice, MipLevels, ArraySize()); }
- operator const D3D12_RESOURCE_DESC&() const { return *this; }
+// operator const D3D12_RESOURCE_DESC&() const { return *this; }
};
inline bool operator==( const D3D12_RESOURCE_DESC& l, const D3D12_RESOURCE_DESC& r )
{
@@ -1356,7 +1356,7 @@ inline UINT64 GetRequiredIntermediateSize(
UINT64 RequiredSize = 0;
ID3D12Device* pDevice;
- pDestinationResource->GetDevice(__uuidof(*pDevice), reinterpret_cast<void**>(&pDevice));
+ pDestinationResource->GetDevice(__uuidof(ID3D12Device), reinterpret_cast<void**>(&pDevice));
pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, 0, nullptr, nullptr, nullptr, &RequiredSize);
pDevice->Release();
@@ -1450,7 +1450,7 @@ inline UINT64 UpdateSubresources(
D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc();
ID3D12Device* pDevice;
- pDestinationResource->GetDevice(__uuidof(*pDevice), reinterpret_cast<void**>(&pDevice));
+ pDestinationResource->GetDevice(__uuidof(ID3D12Device), reinterpret_cast<void**>(&pDevice));
pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, pLayouts, pNumRows, pRowSizesInBytes, &RequiredSize);
pDevice->Release();
diff --git a/3rdparty/bgfx/3rdparty/dxsdk/include/dxgitype.h b/3rdparty/bgfx/3rdparty/dxsdk/include/dxgitype.h
index ccd9d14261e..28b706fced2 100644
--- a/3rdparty/bgfx/3rdparty/dxsdk/include/dxgitype.h
+++ b/3rdparty/bgfx/3rdparty/dxsdk/include/dxgitype.h
@@ -10,74 +10,30 @@
#define MAKE_DXGI_HRESULT(code) MAKE_HRESULT(1, _FACDXGI, code)
#define MAKE_DXGI_STATUS(code) MAKE_HRESULT(0, _FACDXGI, code)
-//#if defined(__MINGW32__) || !defined(DXGI_ERROR_INVALID_CALL)
-#ifndef DXGI_STATUS_OCCLUDED
+#if defined(__MINGW32__) || !defined(DXGI_ERROR_INVALID_CALL)
# define DXGI_STATUS_OCCLUDED MAKE_DXGI_STATUS(1)
-#endif
-#ifndef DXGI_STATUS_CLIPPED
# define DXGI_STATUS_CLIPPED MAKE_DXGI_STATUS(2)
-#endif
-#ifndef DXGI_STATUS_NO_DIRECTION
# define DXGI_STATUS_NO_REDIRECTION MAKE_DXGI_STATUS(4)
-#endif
-#ifndef DXGI_STATUS_NO_DESKTOP_ACCESS
# define DXGI_STATUS_NO_DESKTOP_ACCESS MAKE_DXGI_STATUS(5)
-#endif
-#ifndef DXGI_STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE
# define DXGI_STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE MAKE_DXGI_STATUS(6)
-#endif
-#ifndef DXGI_STATUS_MODE_CHANGED
# define DXGI_STATUS_MODE_CHANGED MAKE_DXGI_STATUS(7)
-#endif
-#ifndef DXGI_STATUS_MODE_CHANGE_IN_PROGRESS
# define DXGI_STATUS_MODE_CHANGE_IN_PROGRESS MAKE_DXGI_STATUS(8)
-#endif
-#ifndef DXGI_ERROR_INVALID_CALL
# define DXGI_ERROR_INVALID_CALL MAKE_DXGI_HRESULT(1)
-#endif
-#ifndef DXGI_ERROR_NOT_FOUND
# define DXGI_ERROR_NOT_FOUND MAKE_DXGI_HRESULT(2)
-#endif
-#ifndef DXGI_ERROR_MORE_DATA
# define DXGI_ERROR_MORE_DATA MAKE_DXGI_HRESULT(3)
-#endif
-#ifndef DXGI_ERROR_UNSUPPORTED
# define DXGI_ERROR_UNSUPPORTED MAKE_DXGI_HRESULT(4)
-#endif
-#ifndef DXGI_ERROR_DEVICE_REMOVED
# define DXGI_ERROR_DEVICE_REMOVED MAKE_DXGI_HRESULT(5)
-#endif
-#ifndef DXGI_ERROR_DEVICE_HUNG
# define DXGI_ERROR_DEVICE_HUNG MAKE_DXGI_HRESULT(6)
-#endif
-#ifndef DXGI_ERROR_DEVICE_RESET
# define DXGI_ERROR_DEVICE_RESET MAKE_DXGI_HRESULT(7)
-#endif
-#ifndef DXGI_ERROR_WAS_STILL_DRAWING
# define DXGI_ERROR_WAS_STILL_DRAWING MAKE_DXGI_HRESULT(10)
-#endif
-#ifndef DXGI_ERROR_FRAME_STATISTICS_DISJOINT
# define DXGI_ERROR_FRAME_STATISTICS_DISJOINT MAKE_DXGI_HRESULT(11)
-#endif
-#ifndef DXGI_ERROR_GRAPHICS_VIDPN_SOURCE_IN_USE
# define DXGI_ERROR_GRAPHICS_VIDPN_SOURCE_IN_USE MAKE_DXGI_HRESULT(12)
-#endif
-#ifndef DXGI_ERROR_DRIVER_INTERNAL_ERROR
# define DXGI_ERROR_DRIVER_INTERNAL_ERROR MAKE_DXGI_HRESULT(32)
-#endif
-#ifndef DXGI_ERROR_NONEXCLUSIVE
# define DXGI_ERROR_NONEXCLUSIVE MAKE_DXGI_HRESULT(33)
-#endif
-#ifndef DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
# define DXGI_ERROR_NOT_CURRENTLY_AVAILABLE MAKE_DXGI_HRESULT(34)
-#endif
-#ifndef DXGI_ERROR_REMOTE_CLIENT_DISCONNECTED
# define DXGI_ERROR_REMOTE_CLIENT_DISCONNECTED MAKE_DXGI_HRESULT(35)
-#endif
-#ifndef DXGI_ERROR_REMOTE_OUTOFMEMORY
# define DXGI_ERROR_REMOTE_OUTOFMEMORY MAKE_DXGI_HRESULT(36)
-#endif
-//#endif // defined(__MINGW32__) || (_WIN32_WINNT < 0x0601)
+#endif // defined(__MINGW32__) || (_WIN32_WINNT < 0x0601)
#define DXGI_CPU_ACCESS_NONE ( 0 )
#define DXGI_CPU_ACCESS_DYNAMIC ( 1 )
diff --git a/3rdparty/bgfx/3rdparty/glsl-optimizer/Changelog.md b/3rdparty/bgfx/3rdparty/glsl-optimizer/Changelog.md
index 3c0dd4166db..ee09e0250e6 100644
--- a/3rdparty/bgfx/3rdparty/glsl-optimizer/Changelog.md
+++ b/3rdparty/bgfx/3rdparty/glsl-optimizer/Changelog.md
@@ -1,6 +1,18 @@
GLSL optimizer Change Log
=========================
+2015 08
+-------
+
+Changes:
+
+* 2D shadow and 2D array uniforms got their own glslopt_basic_type entries.
+
+Fixes:
+
+* Fixed translation of 2D texture arrays (GLSL with EXT_texture_array, GLES3 and Metal).
+
+
2015 06
-------
diff --git a/3rdparty/bgfx/3rdparty/glsl-optimizer/projects/vs2010/glsl_optimizer_lib.vcxproj b/3rdparty/bgfx/3rdparty/glsl-optimizer/projects/vs2010/glsl_optimizer_lib.vcxproj
index 2c8a23954a5..92063b3edc8 100644
--- a/3rdparty/bgfx/3rdparty/glsl-optimizer/projects/vs2010/glsl_optimizer_lib.vcxproj
+++ b/3rdparty/bgfx/3rdparty/glsl-optimizer/projects/vs2010/glsl_optimizer_lib.vcxproj
@@ -317,7 +317,6 @@
<ClCompile Include="..\..\src\glsl\opt_swizzle_swizzle.cpp" />
<ClCompile Include="..\..\src\glsl\opt_tree_grafting.cpp" />
<ClCompile Include="..\..\src\glsl\opt_vectorize.cpp" />
- <ClCompile Include="..\..\src\glsl\opt_vector_splitting.cpp" />
<ClCompile Include="..\..\src\glsl\s_expression.cpp" />
<ClCompile Include="..\..\src\glsl\standalone_scaffolding.cpp" />
<ClCompile Include="..\..\src\glsl\strtod.c" />
diff --git a/3rdparty/bgfx/3rdparty/glsl-optimizer/projects/vs2010/glsl_optimizer_lib.vcxproj.filters b/3rdparty/bgfx/3rdparty/glsl-optimizer/projects/vs2010/glsl_optimizer_lib.vcxproj.filters
index 31bb2648f1e..6e9f9443410 100644
--- a/3rdparty/bgfx/3rdparty/glsl-optimizer/projects/vs2010/glsl_optimizer_lib.vcxproj.filters
+++ b/3rdparty/bgfx/3rdparty/glsl-optimizer/projects/vs2010/glsl_optimizer_lib.vcxproj.filters
@@ -491,9 +491,6 @@
<ClCompile Include="..\..\src\glsl\ir_stats.cpp">
<Filter>src\glsl</Filter>
</ClCompile>
- <ClCompile Include="..\..\src\glsl\opt_vector_splitting.cpp">
- <Filter>src\glsl</Filter>
- </ClCompile>
<ClCompile Include="..\..\src\util\hash_table.c">
<Filter>src\util</Filter>
</ClCompile>
diff --git a/3rdparty/bgfx/3rdparty/glsl-optimizer/projects/xcode5/glsl_optimizer_lib.xcodeproj/project.pbxproj b/3rdparty/bgfx/3rdparty/glsl-optimizer/projects/xcode5/glsl_optimizer_lib.xcodeproj/project.pbxproj
index 04a79805cf7..0adb4785f4c 100644
--- a/3rdparty/bgfx/3rdparty/glsl-optimizer/projects/xcode5/glsl_optimizer_lib.xcodeproj/project.pbxproj
+++ b/3rdparty/bgfx/3rdparty/glsl-optimizer/projects/xcode5/glsl_optimizer_lib.xcodeproj/project.pbxproj
@@ -126,7 +126,6 @@
2BA7E14617D0AEB200D5C475 /* lower_vector_insert.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2BA7E13C17D0AEB200D5C475 /* lower_vector_insert.cpp */; };
2BA7E14817D0AEB200D5C475 /* opt_dead_builtin_varyings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2BA7E13D17D0AEB200D5C475 /* opt_dead_builtin_varyings.cpp */; };
2BA7E14A17D0AEB200D5C475 /* opt_flip_matrices.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2BA7E13E17D0AEB200D5C475 /* opt_flip_matrices.cpp */; };
- 2BA84CA619580C9D0021BE1D /* opt_vector_splitting.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2BA84CA519580C9D0021BE1D /* opt_vector_splitting.cpp */; };
2BB2F5B012B8F1580052C6B0 /* lower_discard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2BB2F5AA12B8F1580052C6B0 /* lower_discard.cpp */; };
2BB2F5B112B8F1580052C6B0 /* lower_instructions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2BB2F5AB12B8F1580052C6B0 /* lower_instructions.cpp */; };
2BB2F5B212B8F1580052C6B0 /* lower_vector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2BB2F5AC12B8F1580052C6B0 /* lower_vector.cpp */; };
@@ -292,7 +291,6 @@
2BA7E13C17D0AEB200D5C475 /* lower_vector_insert.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = lower_vector_insert.cpp; path = ../../src/glsl/lower_vector_insert.cpp; sourceTree = "<group>"; };
2BA7E13D17D0AEB200D5C475 /* opt_dead_builtin_varyings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = opt_dead_builtin_varyings.cpp; path = ../../src/glsl/opt_dead_builtin_varyings.cpp; sourceTree = "<group>"; };
2BA7E13E17D0AEB200D5C475 /* opt_flip_matrices.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = opt_flip_matrices.cpp; path = ../../src/glsl/opt_flip_matrices.cpp; sourceTree = "<group>"; };
- 2BA84CA519580C9D0021BE1D /* opt_vector_splitting.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = opt_vector_splitting.cpp; path = ../../src/glsl/opt_vector_splitting.cpp; sourceTree = "<group>"; };
2BB2F5AA12B8F1580052C6B0 /* lower_discard.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = lower_discard.cpp; path = ../../src/glsl/lower_discard.cpp; sourceTree = SOURCE_ROOT; };
2BB2F5AB12B8F1580052C6B0 /* lower_instructions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = lower_instructions.cpp; path = ../../src/glsl/lower_instructions.cpp; sourceTree = SOURCE_ROOT; };
2BB2F5AC12B8F1580052C6B0 /* lower_vector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = lower_vector.cpp; path = ../../src/glsl/lower_vector.cpp; sourceTree = SOURCE_ROOT; };
@@ -543,7 +541,6 @@
2B38545B1293BE5000F3E692 /* opt_swizzle_swizzle.cpp */,
2B38545C1293BE5000F3E692 /* opt_tree_grafting.cpp */,
2B9F0A3C189664F3002FF617 /* opt_vectorize.cpp */,
- 2BA84CA519580C9D0021BE1D /* opt_vector_splitting.cpp */,
2BA55A991207FEA6002DC82D /* program.h */,
2BA55A9A1207FEA6002DC82D /* s_expression.cpp */,
2BA55A9B1207FEA6002DC82D /* s_expression.h */,
@@ -730,7 +727,6 @@
2B78C91D1858B052007F5D2A /* ir_equals.cpp in Sources */,
2B6A99F61223B1670059FBED /* glcpp-parse.c in Sources */,
2B6A99FB1223B1670059FBED /* pp.c in Sources */,
- 2BA84CA619580C9D0021BE1D /* opt_vector_splitting.cpp in Sources */,
2BBA49281254706A00D42573 /* glsl_symbol_table.cpp in Sources */,
2BBA492A1254706A00D42573 /* loop_analysis.cpp in Sources */,
2BBA492C1254706A00D42573 /* loop_controls.cpp in Sources */,
diff --git a/3rdparty/bgfx/3rdparty/glsl-optimizer/src/glsl/Makefile b/3rdparty/bgfx/3rdparty/glsl-optimizer/src/glsl/Makefile
index 373bfeb8c46..27d7ad363bd 100644
--- a/3rdparty/bgfx/3rdparty/glsl-optimizer/src/glsl/Makefile
+++ b/3rdparty/bgfx/3rdparty/glsl-optimizer/src/glsl/Makefile
@@ -103,7 +103,6 @@ SRC = ast_array_index.cpp \
opt_swizzle_swizzle.cpp \
opt_tree_grafting.cpp \
opt_vectorize.cpp \
- opt_vector_splitting.cpp \
s_expression.cpp \
standalone_scaffolding.cpp \
strtod.c \
diff --git a/3rdparty/bgfx/3rdparty/glsl-optimizer/src/glsl/glsl_optimizer.cpp b/3rdparty/bgfx/3rdparty/glsl-optimizer/src/glsl/glsl_optimizer.cpp
index ed732e2db5b..c4e7a03cccc 100644
--- a/3rdparty/bgfx/3rdparty/glsl-optimizer/src/glsl/glsl_optimizer.cpp
+++ b/3rdparty/bgfx/3rdparty/glsl-optimizer/src/glsl/glsl_optimizer.cpp
@@ -454,10 +454,6 @@ static void do_optimization_passes(exec_list* ir, bool linked, _mesa_glsl_parse_
progress2 = propagate_precision (ir, state->metal_target); progress |= progress2; if (progress2) debug_print_ir ("After prec propagation", ir, state, mem_ctx);
progress2 = do_copy_propagation(ir); progress |= progress2; if (progress2) debug_print_ir ("After copy propagation", ir, state, mem_ctx);
progress2 = do_copy_propagation_elements(ir); progress |= progress2; if (progress2) debug_print_ir ("After copy propagation elems", ir, state, mem_ctx);
- if (state->es_shader && linked)
- {
- progress2 = optimize_split_vectors(ir, linked, OPT_SPLIT_ONLY_LOOP_INDUCTORS); progress |= progress2; if (progress2) debug_print_ir("After split vectors", ir, state, mem_ctx);
- }
if (linked)
{
@@ -488,7 +484,6 @@ static void do_optimization_passes(exec_list* ir, bool linked, _mesa_glsl_parse_
progress2 = do_swizzle_swizzle(ir); progress |= progress2; if (progress2) debug_print_ir ("After swizzle swizzle", ir, state, mem_ctx);
progress2 = do_noop_swizzle(ir); progress |= progress2; if (progress2) debug_print_ir ("After noop swizzle", ir, state, mem_ctx);
progress2 = optimize_split_arrays(ir, linked, state->metal_target && state->stage == MESA_SHADER_FRAGMENT); progress |= progress2; if (progress2) debug_print_ir ("After split arrays", ir, state, mem_ctx);
- progress2 = optimize_split_vectors(ir, linked, OPT_SPLIT_ONLY_UNUSED); progress |= progress2; if (progress2) debug_print_ir("After split unused vectors", ir, state, mem_ctx);
progress2 = optimize_redundant_jumps(ir); progress |= progress2; if (progress2) debug_print_ir ("After redundant jumps", ir, state, mem_ctx);
// do loop stuff only when linked; otherwise causes duplicate loop induction variable
@@ -528,7 +523,14 @@ static void glsl_type_to_optimizer_desc(const glsl_type* type, glsl_precision pr
else if (type->is_sampler())
{
if (type->sampler_dimensionality == GLSL_SAMPLER_DIM_2D)
- out->type = kGlslTypeTex2D;
+ {
+ if (type->sampler_shadow)
+ out->type = kGlslTypeTex2DShadow;
+ else if (type->sampler_array)
+ out->type = kGlslTypeTex2DArray;
+ else
+ out->type = kGlslTypeTex2D;
+ }
else if (type->sampler_dimensionality == GLSL_SAMPLER_DIM_3D)
out->type = kGlslTypeTex3D;
else if (type->sampler_dimensionality == GLSL_SAMPLER_DIM_CUBE)
diff --git a/3rdparty/bgfx/3rdparty/glsl-optimizer/src/glsl/glsl_optimizer.h b/3rdparty/bgfx/3rdparty/glsl-optimizer/src/glsl/glsl_optimizer.h
index 8dfc74bb007..668351e0079 100644
--- a/3rdparty/bgfx/3rdparty/glsl-optimizer/src/glsl/glsl_optimizer.h
+++ b/3rdparty/bgfx/3rdparty/glsl-optimizer/src/glsl/glsl_optimizer.h
@@ -52,6 +52,8 @@ enum glslopt_basic_type {
kGlslTypeTex2D,
kGlslTypeTex3D,
kGlslTypeTexCube,
+ kGlslTypeTex2DShadow,
+ kGlslTypeTex2DArray,
kGlslTypeOther,
kGlslTypeCount
};
diff --git a/3rdparty/bgfx/3rdparty/glsl-optimizer/src/glsl/ir_optimization.h b/3rdparty/bgfx/3rdparty/glsl-optimizer/src/glsl/ir_optimization.h
index e1154e9dfc3..c4f5465f846 100644
--- a/3rdparty/bgfx/3rdparty/glsl-optimizer/src/glsl/ir_optimization.h
+++ b/3rdparty/bgfx/3rdparty/glsl-optimizer/src/glsl/ir_optimization.h
@@ -124,14 +124,6 @@ bool lower_vector_insert(exec_list *instructions, bool lower_nonconstant_index);
void lower_named_interface_blocks(void *mem_ctx, gl_shader *shader);
bool optimize_redundant_jumps(exec_list *instructions);
-typedef enum {
- OPT_SPLIT_ONLY_LOOP_INDUCTORS = 0, //< only split vectors that are used as loop inductors (and are not used by any vector operation)
- OPT_SPLIT_ONLY_UNUSED = 1, //< only split vectors that have unused components (and are not used by any vector operation)
- OPT_SPLIT_ANY_POSSIBLE = 2, //< Split all vectors that are only accessed by their components
-} glsl_vector_splitting_mode;
-
-bool optimize_split_vectors(exec_list *instructions, bool linked, glsl_vector_splitting_mode mode);
-
bool optimize_split_arrays(exec_list *instructions, bool linked, bool split_shader_outputs);
bool lower_offset_arrays(exec_list *instructions);
void optimize_dead_builtin_variables(exec_list *instructions,
diff --git a/3rdparty/bgfx/3rdparty/glsl-optimizer/src/glsl/ir_print_glsl_visitor.cpp b/3rdparty/bgfx/3rdparty/glsl-optimizer/src/glsl/ir_print_glsl_visitor.cpp
index 9c5d807d896..f11893bbad6 100644
--- a/3rdparty/bgfx/3rdparty/glsl-optimizer/src/glsl/ir_print_glsl_visitor.cpp
+++ b/3rdparty/bgfx/3rdparty/glsl-optimizer/src/glsl/ir_print_glsl_visitor.cpp
@@ -254,6 +254,8 @@ _mesa_print_ir_glsl(exec_list *instructions,
str.asprintf_append ("#extension GL_EXT_shader_framebuffer_fetch : enable\n");
if (state->ARB_shader_bit_encoding_enable)
str.asprintf_append("#extension GL_ARB_shader_bit_encoding : enable\n");
+ if (state->EXT_texture_array_enable)
+ str.asprintf_append ("#extension GL_EXT_texture_array : enable\n");
}
// remove unused struct declarations
@@ -822,11 +824,14 @@ void ir_print_glsl_visitor::visit(ir_texture *ir)
{
glsl_sampler_dim sampler_dim = (glsl_sampler_dim)ir->sampler->type->sampler_dimensionality;
const bool is_shadow = ir->sampler->type->sampler_shadow;
+ const bool is_array = ir->sampler->type->sampler_array;
const glsl_type* uv_type = ir->coordinate->type;
const int uv_dim = uv_type->vector_elements;
int sampler_uv_dim = tex_sampler_dim_size[sampler_dim];
if (is_shadow)
sampler_uv_dim += 1;
+ if (is_array)
+ sampler_uv_dim += 1;
const bool is_proj = (uv_dim > sampler_uv_dim);
const bool is_lod = (ir->op == ir_txl);
@@ -876,6 +881,9 @@ void ir_print_glsl_visitor::visit(ir_texture *ir)
else
buffer.asprintf_append ("texture");
}
+
+ if (is_array && state->EXT_texture_array_enable)
+ buffer.asprintf_append ("Array");
if (is_proj)
buffer.asprintf_append ("Proj");
diff --git a/3rdparty/bgfx/3rdparty/glsl-optimizer/src/glsl/ir_print_metal_visitor.cpp b/3rdparty/bgfx/3rdparty/glsl-optimizer/src/glsl/ir_print_metal_visitor.cpp
index bad74c2de55..f9988a31f61 100644
--- a/3rdparty/bgfx/3rdparty/glsl-optimizer/src/glsl/ir_print_metal_visitor.cpp
+++ b/3rdparty/bgfx/3rdparty/glsl-optimizer/src/glsl/ir_print_metal_visitor.cpp
@@ -209,6 +209,7 @@ _mesa_print_ir_metal(exec_list *instructions,
// includes, prefix etc.
ctx.prefixStr.asprintf_append ("#include <metal_stdlib>\n");
+ ctx.prefixStr.asprintf_append ("#pragma clang diagnostic ignored \"-Wparentheses-equality\"\n");
ctx.prefixStr.asprintf_append ("using namespace metal;\n");
ctx.inputStr.asprintf_append("struct xlatMtlShaderInput {\n");
@@ -235,8 +236,10 @@ _mesa_print_ir_metal(exec_list *instructions,
// skip gl_ variables if they aren't used/assigned
if (strstr(var->name, "gl_") == var->name)
{
- if (!var->data.used && !var->data.assigned)
- continue;
+ if (NULL == strstr(var->name, "gl_FragData_") ) {
+ if (!var->data.used && !var->data.assigned)
+ continue;
+ }
}
//
@@ -464,6 +467,8 @@ static void print_type_precision(string_buffer& buffer, const glsl_type *t, glsl
typeName = "depth2d<float>"; // depth type must always be float
else if (!strcmp(typeName, "samplerCubeShadow"))
typeName = "depthcube<float>"; // depth type must always be float
+ else if (!strcmp(typeName, "sampler2DArray"))
+ typeName = halfPrec ? "texture2d_array<half>" : "texture2d_array<float>";
if (t->base_type == GLSL_TYPE_ARRAY) {
print_type_precision(buffer, t->fields.array, prec, true);
@@ -1160,17 +1165,26 @@ static int tex_sampler_dim_size[] = {
};
-static void print_texture_uv (ir_print_metal_visitor* vis, ir_texture* ir, bool is_shadow, bool is_proj, int uv_dim, int sampler_uv_dim)
+static void print_texture_uv (ir_print_metal_visitor* vis, ir_texture* ir, bool is_shadow, bool is_proj, bool is_array, int uv_dim, int sampler_uv_dim)
{
if (!is_shadow)
{
- if (!is_proj)
+ if (!is_proj && !is_array)
{
// regular UV
vis->buffer.asprintf_append (sampler_uv_dim == 3 ? "(float3)(" : "(float2)(");
ir->coordinate->accept(vis);
vis->buffer.asprintf_append (")");
}
+ else if (is_array)
+ {
+ // array sample
+ vis->buffer.asprintf_append ("(float2)((");
+ ir->coordinate->accept(vis);
+ vis->buffer.asprintf_append (").xy), (uint)((");
+ ir->coordinate->accept(vis);
+ vis->buffer.asprintf_append (").z)");
+ }
else
{
// regular projected
@@ -1212,12 +1226,13 @@ void ir_print_metal_visitor::visit(ir_texture *ir)
{
glsl_sampler_dim sampler_dim = (glsl_sampler_dim)ir->sampler->type->sampler_dimensionality;
const bool is_shadow = ir->sampler->type->sampler_shadow;
+ const bool is_array = ir->sampler->type->sampler_array;
const glsl_type* uv_type = ir->coordinate->type;
const int uv_dim = uv_type->vector_elements;
int sampler_uv_dim = tex_sampler_dim_size[sampler_dim];
if (is_shadow)
sampler_uv_dim += 1;
- const bool is_proj = (uv_dim > sampler_uv_dim);
+ const bool is_proj = (uv_dim > sampler_uv_dim) && !is_array;
// texture name & call to sample
ir->sampler->accept(this);
@@ -1239,7 +1254,7 @@ void ir_print_metal_visitor::visit(ir_texture *ir)
buffer.asprintf_append (", ");
// texture coordinate
- print_texture_uv (this, ir, is_shadow, is_proj, uv_dim, sampler_uv_dim);
+ print_texture_uv (this, ir, is_shadow, is_proj, is_array, uv_dim, sampler_uv_dim);
// lod bias
if (ir->op == ir_txb)
diff --git a/3rdparty/bgfx/3rdparty/glsl-optimizer/src/glsl/opt_vector_splitting.cpp b/3rdparty/bgfx/3rdparty/glsl-optimizer/src/glsl/opt_vector_splitting.cpp
deleted file mode 100644
index 978d429a5ec..00000000000
--- a/3rdparty/bgfx/3rdparty/glsl-optimizer/src/glsl/opt_vector_splitting.cpp
+++ /dev/null
@@ -1,485 +0,0 @@
-/*
- * Based on work Copyright © 2010 Intel Corporation, vector splitting
- * implemented by Copyright © 2014 Unity Technologies
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file opt_vector_splitting.cpp
- *
- * If a vector is always dereferenced only by its xyzw components separately,
- * and never accessed as a whole (or with swizzle mask with >1 bits set), then
- * split it apart into its elements, making it more amenable to other
- * optimization passes.
- *
- * This skips uniforms/varyings, which would need careful
- * handling due to their ir->location fields tying them to the GL API
- * and other shader stages.
- */
-
-#include "ir.h"
-#include "ir_visitor.h"
-#include "ir_rvalue_visitor.h"
-#include "glsl_types.h"
-#include "ir_optimization.h"
-#include "loop_analysis.h"
-
-static bool debug = false;
-
-namespace {
- namespace opt_vector_splitting {
-
- class variable_entry : public exec_node
- {
- public:
- variable_entry(ir_variable *var)
- {
- this->var = var;
- this->split = true;
- this->use_mask = 0;
- this->declaration = false;
- this->components = NULL;
- this->mem_ctx = NULL;
- }
-
- ir_variable *var; /* The key: the variable's pointer. */
-
- /** Whether this array should be split or not. */
- bool split;
-
- /** bitmask for the components in the vector that actually get written to.
- * If multiple slots are written simultaneously, split gets set to false.*/
- int use_mask;
-
- /* If the variable had a decl we can work with in the instruction
- * stream. We can't do splitting on function arguments, which
- * don't get this variable set.
- */
- bool declaration;
-
- ir_variable **components;
-
- /** ralloc_parent(this->var) -- the shader's talloc context. */
- void *mem_ctx;
- };
-
- } /* namespace */
-
-
-using namespace opt_vector_splitting;
-
-/**
- * This class does a walk over the tree, coming up with the set of
- * variables that could be split by looking to see if they are arrays
- * that are only ever constant-index dereferenced.
- */
-class ir_vector_reference_visitor : public ir_hierarchical_visitor {
-public:
- ir_vector_reference_visitor(void)
- {
- this->mem_ctx = ralloc_context(NULL);
- this->variable_list.make_empty();
- }
-
- ~ir_vector_reference_visitor(void)
- {
- ralloc_free(mem_ctx);
- }
-
- bool get_split_list(exec_list *instructions, bool linked, glsl_vector_splitting_mode mode);
-
- virtual ir_visitor_status visit(ir_variable *);
- virtual ir_visitor_status visit(ir_dereference_variable *);
- virtual ir_visitor_status visit_enter(ir_swizzle *);
- virtual ir_visitor_status visit_enter(ir_assignment *);
- virtual ir_visitor_status visit_enter(ir_function_signature *);
-
- variable_entry *get_variable_entry(ir_variable *var);
-
- /* List of variable_entry */
- exec_list variable_list;
-
- /* Current split mode */
- glsl_vector_splitting_mode mode;
-
- loop_state *loopstate;
-
- void *mem_ctx;
-};
-
-} /* namespace */
-
-variable_entry *
-ir_vector_reference_visitor::get_variable_entry(ir_variable *var)
-{
- assert(var);
-
- if (var->data.mode != ir_var_auto &&
- var->data.mode != ir_var_temporary)
- return NULL;
-
- if (!var->type->is_vector())
- return NULL;
-
- // If mode is loop_inductors, allow only loop inductors to be stored.
- if (mode == OPT_SPLIT_ONLY_LOOP_INDUCTORS && loopstate)
- {
- loop_variable_state* inductor_state = loopstate->get_for_inductor(var);
- if (!inductor_state)
- {
- return NULL;
- }
- }
-
- foreach_in_list(variable_entry, entry, &this->variable_list) {
- if (entry->var == var)
- return entry;
- }
-
-
- variable_entry *entry = new(mem_ctx) variable_entry(var);
- this->variable_list.push_tail(entry);
- return entry;
-}
-
-
-ir_visitor_status
-ir_vector_reference_visitor::visit(ir_variable *ir)
-{
- variable_entry *entry = this->get_variable_entry(ir);
-
- if (entry)
- entry->declaration = true;
-
- return visit_continue;
-}
-
-ir_visitor_status
-ir_vector_reference_visitor::visit(ir_dereference_variable *ir)
-{
- variable_entry *entry = this->get_variable_entry(ir->var);
-
- /* If we made it to here without seeing an ir_swizzle,
- * then the dereference of this vector didn't have a swizzle in it
- * (see the visit_continue_with_parent below), so we can't split
- * the variable.
- */
- if (entry)
- entry->split = false;
-
- return visit_continue;
-}
-
-ir_visitor_status
-ir_vector_reference_visitor::visit_enter(ir_swizzle *ir)
-{
- ir_variable *var = ir->variable_referenced();
- if (!var)
- return visit_continue;
-
- variable_entry *entry = this->get_variable_entry(var);
-
- if (entry)
- {
- if (ir->mask.num_components > 1)
- {
- entry->split = false;
- }
- else
- {
- // Update the usemask
- entry->use_mask |= (1 << ir->mask.x);
- }
- }
-
- // Skip the rest of the swizzle IR tree, we're done here.
- return visit_continue_with_parent;
-}
-
-ir_visitor_status
-ir_vector_reference_visitor::visit_enter(ir_assignment *ir)
-{
- ir_dereference_variable *dest = ir->lhs->as_dereference_variable();
- if (dest)
- {
- variable_entry *entry = this->get_variable_entry(dest->var);
- if (entry)
- {
- // Count how many bits the write mask has
- unsigned maskbitval = ir->write_mask; // count the number of bits set
- int maskbitcount; // accumulates the total bits set
- for ( maskbitcount = 0; maskbitval; maskbitcount++)
- {
- maskbitval &= maskbitval - 1; // clear the least significant bit set
- }
- if (maskbitcount > 1)
- {
- // Writing to more than one slot, cannot split.
- entry->split = false;
- }
-
- // Update write mask
- entry->use_mask |= ir->write_mask;
- }
- }
-
- // Visit only the rhs, there may be swizzles and variable dereferences there as well
- ir->rhs->accept(this);
- return visit_continue_with_parent;
-
-}
-
-ir_visitor_status
-ir_vector_reference_visitor::visit_enter(ir_function_signature *ir)
-{
- /* We don't have logic for array-splitting function arguments,
- * so just look at the body instructions and not the parameter
- * declarations.
- */
- visit_list_elements(this, &ir->body);
- return visit_continue_with_parent;
-}
-
-bool
-ir_vector_reference_visitor::get_split_list(exec_list *instructions,
- bool linked,
- glsl_vector_splitting_mode _mode)
-{
- mode = _mode;
-
- if (linked)
- {
- loop_state* ls = analyze_loop_variables(instructions);
- if (ls->loop_found)
- set_loop_controls(instructions, ls);
-
- loopstate = ls;
- }
- else
- {
- loopstate = NULL;
- }
-
- visit_list_elements(this, instructions);
-
- /* If the shaders aren't linked yet, we can't mess with global
- * declarations, which need to be matched by name across shaders.
- */
- if (!linked) {
- foreach_in_list(ir_variable, var, instructions) {
- if (var) {
- variable_entry *entry = get_variable_entry(var);
- if (entry)
- entry->remove();
- }
- }
- }
-
- /* Trim out variables we found that we can't split. */
- foreach_in_list_safe(variable_entry, entry, &variable_list) {
-
- if (debug) {
- printf("array %s@%p: decl %d, split %d\n",
- entry->var->name, (void *) entry->var, entry->declaration,
- entry->split);
- }
-
- if (!(entry->declaration && entry->split)) {
- entry->remove();
- }
- else if (mode == OPT_SPLIT_ONLY_UNUSED)
- {
- /* Build mask of fully used vector (vec2 -> 0x3, vec3 -> 0x7, vec4 -> 0xe) */
- unsigned int fullmask = (1 << entry->var->type->vector_elements) - 1;
- if (entry->use_mask == fullmask)
- {
- entry->remove();
- }
- }
- }
-
- return !variable_list.is_empty();
-}
-
-/**
- * This class rewrites the dereferences of arrays that have been split
- * to use the newly created ir_variables for each component.
- */
-class ir_vector_splitting_visitor : public ir_rvalue_visitor {
-public:
- ir_vector_splitting_visitor(exec_list *vars)
- {
- this->variable_list = vars;
- }
-
- virtual ~ir_vector_splitting_visitor()
- {
- }
-
- virtual ir_visitor_status visit_leave(ir_assignment *);
-
- void split_rvalue(ir_rvalue **rval);
- void handle_rvalue(ir_rvalue **rvalue);
- variable_entry *get_splitting_entry(ir_variable *var);
-
- exec_list *variable_list;
-};
-
-variable_entry *
-ir_vector_splitting_visitor::get_splitting_entry(ir_variable *var)
-{
- assert(var);
-
- foreach_in_list(variable_entry, entry, this->variable_list) {
- if (entry->var == var) {
- return entry;
- }
- }
-
- return NULL;
-}
-
-void
-ir_vector_splitting_visitor::split_rvalue(ir_rvalue **rval)
-{
- ir_swizzle *swizzle = (*rval)->as_swizzle();
-
- if (!swizzle)
- return;
-
- ir_variable *var = swizzle->variable_referenced();
- if (!var)
- return;
-
- variable_entry *entry = get_splitting_entry(var);
- if (!entry)
- return;
-
- assert(swizzle->mask.num_components == 1);
-
- *rval = new(entry->mem_ctx)
- ir_dereference_variable(entry->components[swizzle->mask.x]);
-}
-
-void
-ir_vector_splitting_visitor::handle_rvalue(ir_rvalue **rvalue)
-{
- if (!*rvalue)
- return;
-
- ir_rvalue *v = *rvalue;
- split_rvalue(&v);
- *rvalue = v;
-}
-
-ir_visitor_status
-ir_vector_splitting_visitor::visit_leave(ir_assignment *ir)
-{
- /* The normal rvalue visitor skips the LHS of assignments, but we
- * need to process those just the same.
- */
- ir_rvalue *lhs = ir->lhs;
-
- ir_dereference_variable *dest = ir->lhs->as_dereference_variable();
- if (dest)
- {
- variable_entry *entry = get_splitting_entry(dest->var);
- if (entry)
- {
- // Find the only set bit in writemask
- int component = 0;
- while (((ir->write_mask & (1 << component)) == 0) && (component < 4))
- {
- component++;
- }
- assert(ir->write_mask == (1 << component));
-
- ir_dereference_variable *newderef = new(entry->mem_ctx)
- ir_dereference_variable(entry->components[component]);
-
- ir->set_lhs(newderef);
- }
- }
- else
- {
- ir->lhs = lhs->as_dereference();
- ir->lhs->accept(this);
- }
-
- handle_rvalue(&ir->rhs);
- ir->rhs->accept(this);
-
- if (ir->condition) {
- handle_rvalue(&ir->condition);
- ir->condition->accept(this);
- }
-
- return visit_continue;
-}
-
-bool
-optimize_split_vectors(exec_list *instructions, bool linked, glsl_vector_splitting_mode mode)
-{
- ir_vector_reference_visitor refs;
- if (!refs.get_split_list(instructions, linked, mode))
- return false;
-
- void *mem_ctx = ralloc_context(NULL);
-
- /* Replace the decls of the vectors to be split with their split
- * components.
- */
- foreach_in_list(variable_entry, entry, &refs.variable_list) {
- const struct glsl_type *type = entry->var->type;
- const struct glsl_type *subtype;
- glsl_precision subprec = (glsl_precision)entry->var->data.precision;
-
- subtype = type->get_base_type();
-
- entry->mem_ctx = ralloc_parent(entry->var);
-
- entry->components = ralloc_array(mem_ctx,
- ir_variable *,
- type->vector_elements);
-
- for (unsigned int i = 0; i < type->vector_elements; i++) {
- const char *name = ralloc_asprintf(mem_ctx, "%s_%c",
- entry->var->name, "xyzw"[i]);
-
- entry->components[i] =
- new(entry->mem_ctx) ir_variable(subtype, name, ir_var_temporary, subprec);
- entry->var->insert_before(entry->components[i]);
- }
-
- entry->var->remove();
- }
-
- ir_vector_splitting_visitor split(&refs.variable_list);
- visit_list_elements(&split, instructions);
-
- if (debug)
- _mesa_print_ir(stdout, instructions, NULL);
-
- ralloc_free(mem_ctx);
-
- return true;
-
-}
diff --git a/3rdparty/bgfx/3rdparty/glsl-optimizer/src/glsl_optimizer_lib.gyp b/3rdparty/bgfx/3rdparty/glsl-optimizer/src/glsl_optimizer_lib.gyp
index 37ae920360e..eb0d0489785 100644
--- a/3rdparty/bgfx/3rdparty/glsl-optimizer/src/glsl_optimizer_lib.gyp
+++ b/3rdparty/bgfx/3rdparty/glsl-optimizer/src/glsl_optimizer_lib.gyp
@@ -135,7 +135,6 @@
'glsl/opt_swizzle_swizzle.cpp',
'glsl/opt_tree_grafting.cpp',
'glsl/opt_vectorize.cpp',
- 'glsl/opt_vector_splitting.cpp',
'glsl/opt_flip_matrices.cpp',
'glsl/opt_dead_builtin_varyings.cpp',
'glsl/program.h',
diff --git a/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/tex2DArray-in.txt b/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/tex2DArray-in.txt
new file mode 100644
index 00000000000..3fd866df99d
--- /dev/null
+++ b/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/tex2DArray-in.txt
@@ -0,0 +1,20 @@
+#extension GL_EXT_texture_array : require
+
+vec4 xll_tex2DArray(sampler2DArray s, vec3 coord) { return texture2DArray (s, coord); }
+vec4 xll_tex2DArrayBias(sampler2DArray s, vec4 coord) { return texture2DArray (s, coord.xyz, coord.w); }
+
+uniform sampler2DArray myarr;
+
+vec4 xlat_main( in vec4 uv ) {
+ vec4 s = xll_tex2DArray( myarr, uv.xyz);
+ vec4 sswiz = xll_tex2DArray( myarr, uv.xyw);
+ vec4 sbias = xll_tex2DArrayBias( myarr, vec4( uv.xyz, 1.5));
+ return s + sswiz + sbias;
+}
+
+varying vec4 uv;
+void main() {
+ vec4 xl_retval;
+ xl_retval = xlat_main(uv);
+ gl_FragData[0] = vec4(xl_retval);
+}
diff --git a/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/tex2DArray-inES3.txt b/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/tex2DArray-inES3.txt
new file mode 100644
index 00000000000..a84428edb42
--- /dev/null
+++ b/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/tex2DArray-inES3.txt
@@ -0,0 +1,19 @@
+#version 300 es
+out lowp vec4 _fragData;
+
+vec4 xll_tex2DArray(sampler2DArray s, vec3 coord) { return texture (s, coord); }
+vec4 xll_tex2DArrayBias(sampler2DArray s, vec4 coord) { return texture (s, coord.xyz, coord.w); }
+
+uniform lowp sampler2DArray myarr;
+
+lowp vec4 xlat_main( in highp vec4 uv ) {
+ highp vec4 s = xll_tex2DArray( myarr, uv.xyz);
+ highp vec4 sswiz = xll_tex2DArray( myarr, uv.xyw);
+ highp vec4 sbias = xll_tex2DArrayBias( myarr, vec4( uv.xyz, 1.5));
+ highp vec4 slod = textureLod(myarr, uv.xyz, 2.5);
+ return (((s + sswiz) + sbias) + slod);
+}
+in highp vec4 uv;
+void main() {
+ _fragData = xlat_main(uv);
+}
diff --git a/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/tex2DArray-out.txt b/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/tex2DArray-out.txt
new file mode 100644
index 00000000000..ed5629c6d12
--- /dev/null
+++ b/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/tex2DArray-out.txt
@@ -0,0 +1,14 @@
+#extension GL_EXT_texture_array : enable
+uniform sampler2DArray myarr;
+varying vec4 uv;
+void main ()
+{
+ gl_FragData[0] = ((texture2DArray (myarr, uv.xyz) + texture2DArray (myarr, uv.xyw)) + texture2DArray (myarr, uv.xyz, 1.5));
+}
+
+
+// stats: 2 alu 3 tex 0 flow
+// inputs: 1
+// #0: uv (high float) 4x1 [-1]
+// textures: 1
+// #0: myarr (high 2darray) 0x0 [-1]
diff --git a/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/tex2DArray-outES3.txt b/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/tex2DArray-outES3.txt
new file mode 100644
index 00000000000..1b564fee2ba
--- /dev/null
+++ b/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/tex2DArray-outES3.txt
@@ -0,0 +1,33 @@
+#version 300 es
+out lowp vec4 _fragData;
+uniform sampler2DArray myarr;
+in highp vec4 uv;
+void main ()
+{
+ lowp vec4 tmpvar_1;
+ highp vec4 slod_2;
+ lowp vec4 tmpvar_3;
+ tmpvar_3 = texture (myarr, uv.xyz);
+ highp vec4 tmpvar_4;
+ tmpvar_4 = tmpvar_3;
+ lowp vec4 tmpvar_5;
+ tmpvar_5 = texture (myarr, uv.xyw);
+ highp vec4 tmpvar_6;
+ tmpvar_6 = tmpvar_5;
+ lowp vec4 tmpvar_7;
+ tmpvar_7 = texture (myarr, uv.xyz, 1.5);
+ highp vec4 tmpvar_8;
+ tmpvar_8 = tmpvar_7;
+ lowp vec4 tmpvar_9;
+ tmpvar_9 = textureLod (myarr, uv.xyz, 2.5);
+ slod_2 = tmpvar_9;
+ tmpvar_1 = ((tmpvar_4 + tmpvar_6) + (tmpvar_8 + slod_2));
+ _fragData = tmpvar_1;
+}
+
+
+// stats: 3 alu 4 tex 0 flow
+// inputs: 1
+// #0: uv (high float) 4x1 [-1]
+// textures: 1
+// #0: myarr (low 2darray) 0x0 [-1]
diff --git a/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/tex2DArray-outES3Metal.txt b/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/tex2DArray-outES3Metal.txt
new file mode 100644
index 00000000000..f74638ff102
--- /dev/null
+++ b/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/tex2DArray-outES3Metal.txt
@@ -0,0 +1,42 @@
+#include <metal_stdlib>
+using namespace metal;
+struct xlatMtlShaderInput {
+ float4 uv;
+};
+struct xlatMtlShaderOutput {
+ half4 _fragData [[color(0)]];
+};
+struct xlatMtlShaderUniform {
+};
+fragment xlatMtlShaderOutput xlatMtlMain (xlatMtlShaderInput _mtl_i [[stage_in]], constant xlatMtlShaderUniform& _mtl_u [[buffer(0)]]
+ , texture2d_array<half> myarr [[texture(0)]], sampler _mtlsmp_myarr [[sampler(0)]])
+{
+ xlatMtlShaderOutput _mtl_o;
+ half4 tmpvar_1;
+ float4 slod_2;
+ half4 tmpvar_3;
+ tmpvar_3 = myarr.sample(_mtlsmp_myarr, (float2)((_mtl_i.uv.xyz).xy), (uint)((_mtl_i.uv.xyz).z));
+ float4 tmpvar_4;
+ tmpvar_4 = float4(tmpvar_3);
+ half4 tmpvar_5;
+ tmpvar_5 = myarr.sample(_mtlsmp_myarr, (float2)((_mtl_i.uv.xyw).xy), (uint)((_mtl_i.uv.xyw).z));
+ float4 tmpvar_6;
+ tmpvar_6 = float4(tmpvar_5);
+ half4 tmpvar_7;
+ tmpvar_7 = myarr.sample(_mtlsmp_myarr, (float2)((_mtl_i.uv.xyz).xy), (uint)((_mtl_i.uv.xyz).z), bias(1.5));
+ float4 tmpvar_8;
+ tmpvar_8 = float4(tmpvar_7);
+ half4 tmpvar_9;
+ tmpvar_9 = myarr.sample(_mtlsmp_myarr, (float2)((_mtl_i.uv.xyz).xy), (uint)((_mtl_i.uv.xyz).z), level(2.5));
+ slod_2 = float4(tmpvar_9);
+ tmpvar_1 = half4(((tmpvar_4 + tmpvar_6) + (tmpvar_8 + slod_2)));
+ _mtl_o._fragData = tmpvar_1;
+ return _mtl_o;
+}
+
+
+// stats: 3 alu 4 tex 0 flow
+// inputs: 1
+// #0: uv (high float) 4x1 [-1]
+// textures: 1
+// #0: myarr (low 2darray) 0x0 [-1] loc 0
diff --git a/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/tex2dshadow-out.txt b/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/tex2dshadow-out.txt
index a99982e46a5..68e11513629 100644
--- a/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/tex2dshadow-out.txt
+++ b/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/tex2dshadow-out.txt
@@ -10,4 +10,4 @@ void main ()
// inputs: 1
// #0: xlv_TEXCOORD0 (high float) 4x1 [-1]
// textures: 1
-// #0: shadowmap (high 2d) 0x0 [-1]
+// #0: shadowmap (high 2dshadow) 0x0 [-1]
diff --git a/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/tex2dshadow-outES.txt b/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/tex2dshadow-outES.txt
index d64af25bfa3..fcbba67c309 100644
--- a/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/tex2dshadow-outES.txt
+++ b/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/tex2dshadow-outES.txt
@@ -13,4 +13,4 @@ void main ()
// inputs: 1
// #0: xlv_TEXCOORD0 (high float) 4x1 [-1]
// textures: 1
-// #0: shadowmap (low 2d) 0x0 [-1]
+// #0: shadowmap (low 2dshadow) 0x0 [-1]
diff --git a/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/tex2dshadow-outES3.txt b/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/tex2dshadow-outES3.txt
index 6523b890fd6..64af66456a0 100644
--- a/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/tex2dshadow-outES3.txt
+++ b/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/tex2dshadow-outES3.txt
@@ -20,4 +20,4 @@ void main ()
// #0: uvHi (high float) 4x1 [-1]
// #1: uvMed (medium float) 4x1 [-1]
// textures: 1
-// #0: shadowmap (low 2d) 0x0 [-1]
+// #0: shadowmap (low 2dshadow) 0x0 [-1]
diff --git a/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/tex2dshadow-outES3Metal.txt b/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/tex2dshadow-outES3Metal.txt
index 6c7de8b1500..2d85a7fc869 100644
--- a/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/tex2dshadow-outES3Metal.txt
+++ b/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/tex2dshadow-outES3Metal.txt
@@ -30,4 +30,4 @@ fragment xlatMtlShaderOutput xlatMtlMain (xlatMtlShaderInput _mtl_i [[stage_in]]
// #0: uvHi (high float) 4x1 [-1]
// #1: uvMed (medium float) 4x1 [-1]
// textures: 1
-// #0: shadowmap (low 2d) 0x0 [-1] loc 0
+// #0: shadowmap (low 2dshadow) 0x0 [-1] loc 0
diff --git a/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/texProj-outES.txt b/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/texProj-outES.txt
index 2e61bbdab8d..33f2890ec37 100644
--- a/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/texProj-outES.txt
+++ b/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/texProj-outES.txt
@@ -38,4 +38,4 @@ void main ()
// #0: uv (high float) 4x1 [-1]
// textures: 2
// #0: tex (low 2d) 0x0 [-1]
-// #1: shadowmap (low 2d) 0x0 [-1]
+// #1: shadowmap (low 2dshadow) 0x0 [-1]
diff --git a/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/texProj-outES3.txt b/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/texProj-outES3.txt
index 5f4cfe4cd1b..cbcfaba03ea 100644
--- a/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/texProj-outES3.txt
+++ b/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/texProj-outES3.txt
@@ -20,4 +20,4 @@ void main ()
// #0: uv (high float) 4x1 [-1]
// textures: 2
// #0: tex (low 2d) 0x0 [-1]
-// #1: shadowmap (low 2d) 0x0 [-1]
+// #1: shadowmap (low 2dshadow) 0x0 [-1]
diff --git a/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/texProj-outES3Metal.txt b/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/texProj-outES3Metal.txt
index 287e243e6fc..961349b0a26 100644
--- a/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/texProj-outES3Metal.txt
+++ b/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/fragment/texProj-outES3Metal.txt
@@ -30,4 +30,4 @@ fragment xlatMtlShaderOutput xlatMtlMain (xlatMtlShaderInput _mtl_i [[stage_in]]
// #0: uv (high float) 4x1 [-1]
// textures: 2
// #0: tex (low 2d) 0x0 [-1] loc 0
-// #1: shadowmap (low 2d) 0x0 [-1] loc 1
+// #1: shadowmap (low 2dshadow) 0x0 [-1] loc 1
diff --git a/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/glsl_optimizer_tests.cpp b/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/glsl_optimizer_tests.cpp
index 98c3d032fe3..ddca5d1f288 100644
--- a/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/glsl_optimizer_tests.cpp
+++ b/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/glsl_optimizer_tests.cpp
@@ -460,6 +460,8 @@ static const char* kGlslTypeNames[kGlslTypeCount] = {
"2d",
"3d",
"cube",
+ "2dshadow",
+ "2darray",
"other",
};
static const char* kGlslPrecNames[kGlslPrecCount] = {
diff --git a/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/vertex/loops-for-withvec4-out.txt b/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/vertex/loops-for-withvec4-out.txt
index d851b3948b6..2f8889de926 100644
--- a/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/vertex/loops-for-withvec4-out.txt
+++ b/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/vertex/loops-for-withvec4-out.txt
@@ -40,14 +40,14 @@ vec4 Temp_0;
vec4 Temp_1;
vec4 Temp_2;
vec4 Temp_3;
-int tmpvar_1;
+ivec4 Temp_int_0;
void main ()
{
Temp_0 = (dcl_Input0_POSITION0.yyyy * glstate_matrix_mvp[1]);
Temp_0 = ((glstate_matrix_mvp[0] * dcl_Input0_POSITION0.xxxx) + Temp_0);
Temp_0 = ((glstate_matrix_mvp[2] * dcl_Input0_POSITION0.zzzz) + Temp_0);
- vec4 tmpvar_2;
- tmpvar_2 = ((glstate_matrix_mvp[3] * dcl_Input0_POSITION0.wwww) + Temp_0);
+ vec4 tmpvar_1;
+ tmpvar_1 = ((glstate_matrix_mvp[3] * dcl_Input0_POSITION0.wwww) + Temp_0);
VtxGeoOutput1_TEXCOORD0.xy = ((dcl_Input2_TEXCOORD0.xyxx * _MainTex_ST.xyxx) + _MainTex_ST.zwzz).xy;
Temp_0.xyz = (dcl_Input0_POSITION0.yyyy * glstate_matrix_modelview0[1].xyzx).xyz;
Temp_0.xyz = ((glstate_matrix_modelview0[0].xyzx * dcl_Input0_POSITION0.xxxx) + Temp_0.xyzx).xyz;
@@ -60,58 +60,30 @@ void main ()
Temp_0.w = inversesqrt(Temp_0.w);
Temp_1.xyz = (Temp_0.wwww * Temp_1.xyzx).xyz;
Temp_2.xyz = glstate_lightmodel_ambient.xyz;
- tmpvar_1 = 0;
- Temp_3.xyz = ((-(Temp_0.xyzx) * unity_LightPosition[tmpvar_1].wwww) + unity_LightPosition[tmpvar_1].xyzx).xyz;
- Temp_1.w = dot (Temp_3.xyz, Temp_3.xyz);
- Temp_2.w = ((Temp_1.w * unity_LightAtten[tmpvar_1].z) + 1.0);
- Temp_2.w = (1.0/(Temp_2.w));
- Temp_1.w = inversesqrt(Temp_1.w);
- Temp_3.xyz = (Temp_1.wwww * Temp_3.xyzx).xyz;
- Temp_1.w = dot (Temp_1.xyz, Temp_3.xyz);
- Temp_1.w = max (Temp_1.w, 0.0);
- Temp_1.w = (Temp_1.w * Temp_2.w);
- Temp_2.xyz = ((unity_LightColor[tmpvar_1].xyzx * Temp_1.wwww) + glstate_lightmodel_ambient.xyzx).xyz;
- tmpvar_1++;
- Temp_3.xyz = ((-(Temp_0.xyzx) * unity_LightPosition[tmpvar_1].wwww) + unity_LightPosition[tmpvar_1].xyzx).xyz;
- Temp_1.w = dot (Temp_3.xyz, Temp_3.xyz);
- Temp_2.w = ((Temp_1.w * unity_LightAtten[tmpvar_1].z) + 1.0);
- Temp_2.w = (1.0/(Temp_2.w));
- Temp_1.w = inversesqrt(Temp_1.w);
- Temp_3.xyz = (Temp_1.wwww * Temp_3.xyzx).xyz;
- Temp_1.w = dot (Temp_1.xyz, Temp_3.xyz);
- Temp_1.w = max (Temp_1.w, 0.0);
- Temp_1.w = (Temp_1.w * Temp_2.w);
- Temp_2.xyz = ((unity_LightColor[tmpvar_1].xyzx * Temp_1.wwww) + Temp_2.xyzx).xyz;
- tmpvar_1++;
- Temp_3.xyz = ((-(Temp_0.xyzx) * unity_LightPosition[tmpvar_1].wwww) + unity_LightPosition[tmpvar_1].xyzx).xyz;
- Temp_1.w = dot (Temp_3.xyz, Temp_3.xyz);
- Temp_2.w = ((Temp_1.w * unity_LightAtten[tmpvar_1].z) + 1.0);
- Temp_2.w = (1.0/(Temp_2.w));
- Temp_1.w = inversesqrt(Temp_1.w);
- Temp_3.xyz = (Temp_1.wwww * Temp_3.xyzx).xyz;
- Temp_1.w = dot (Temp_1.xyz, Temp_3.xyz);
- Temp_1.w = max (Temp_1.w, 0.0);
- Temp_1.w = (Temp_1.w * Temp_2.w);
- Temp_2.xyz = ((unity_LightColor[tmpvar_1].xyzx * Temp_1.wwww) + Temp_2.xyzx).xyz;
- tmpvar_1++;
- Temp_3.xyz = ((-(Temp_0.xyzx) * unity_LightPosition[tmpvar_1].wwww) + unity_LightPosition[tmpvar_1].xyzx).xyz;
- Temp_1.w = dot (Temp_3.xyz, Temp_3.xyz);
- Temp_2.w = ((Temp_1.w * unity_LightAtten[tmpvar_1].z) + 1.0);
- Temp_2.w = (1.0/(Temp_2.w));
- Temp_1.w = inversesqrt(Temp_1.w);
- Temp_3.xyz = (Temp_1.wwww * Temp_3.xyzx).xyz;
- Temp_1.w = dot (Temp_1.xyz, Temp_3.xyz);
- Temp_1.w = max (Temp_1.w, 0.0);
- Temp_1.w = (Temp_1.w * Temp_2.w);
- Temp_2.xyz = ((unity_LightColor[tmpvar_1].xyzx * Temp_1.wwww) + Temp_2.xyzx).xyz;
- tmpvar_1++;
+ Temp_int_0.w = 0;
+ while (true) {
+ if ((Temp_int_0.w >= 4)) {
+ break;
+ };
+ Temp_3.xyz = ((-(Temp_0.xyzx) * unity_LightPosition[Temp_int_0.w].wwww) + unity_LightPosition[Temp_int_0.w].xyzx).xyz;
+ Temp_1.w = dot (Temp_3.xyz, Temp_3.xyz);
+ Temp_2.w = ((Temp_1.w * unity_LightAtten[Temp_int_0.w].z) + 1.0);
+ Temp_2.w = (1.0/(Temp_2.w));
+ Temp_1.w = inversesqrt(Temp_1.w);
+ Temp_3.xyz = (Temp_1.wwww * Temp_3.xyzx).xyz;
+ Temp_1.w = dot (Temp_1.xyz, Temp_3.xyz);
+ Temp_1.w = max (Temp_1.w, 0.0);
+ Temp_1.w = (Temp_1.w * Temp_2.w);
+ Temp_2.xyz = ((unity_LightColor[Temp_int_0.w].xyzx * Temp_1.wwww) + Temp_2.xyzx).xyz;
+ Temp_int_0.w = (Temp_int_0.w + 1);
+ };
VtxGeoOutput2_COLOR0.xyz = (Temp_2.xyzx + Temp_2.xyzx).xyz;
VtxGeoOutput2_COLOR0.w = 1.0;
- gl_Position = tmpvar_2;
+ gl_Position = tmpvar_1;
}
-// stats: 87 alu 0 tex 0 flow
+// stats: 43 alu 0 tex 2 flow
// inputs: 3
// #0: dcl_Input0_POSITION0 (high float) 4x1 [-1]
// #1: dcl_Input1_NORMAL0 (high float) 4x1 [-1]
diff --git a/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/vertex/loops-for-withvec4-outES3.txt b/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/vertex/loops-for-withvec4-outES3.txt
index e62f0f22107..dce767a5403 100644
--- a/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/vertex/loops-for-withvec4-outES3.txt
+++ b/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/vertex/loops-for-withvec4-outES3.txt
@@ -40,14 +40,14 @@ vec4 Temp_0;
vec4 Temp_1;
vec4 Temp_2;
vec4 Temp_3;
-highp int tmpvar_1;
+highp ivec4 Temp_int_0;
void main ()
{
Temp_0 = (dcl_Input0_POSITION0.yyyy * glstate_matrix_mvp[1]);
Temp_0 = ((glstate_matrix_mvp[0] * dcl_Input0_POSITION0.xxxx) + Temp_0);
Temp_0 = ((glstate_matrix_mvp[2] * dcl_Input0_POSITION0.zzzz) + Temp_0);
- highp vec4 tmpvar_2;
- tmpvar_2 = ((glstate_matrix_mvp[3] * dcl_Input0_POSITION0.wwww) + Temp_0);
+ highp vec4 tmpvar_1;
+ tmpvar_1 = ((glstate_matrix_mvp[3] * dcl_Input0_POSITION0.wwww) + Temp_0);
VtxGeoOutput1_TEXCOORD0.xy = ((dcl_Input2_TEXCOORD0.xyxx * _MainTex_ST.xyxx) + _MainTex_ST.zwzz).xy;
Temp_0.xyz = (dcl_Input0_POSITION0.yyyy * glstate_matrix_modelview0[1].xyzx).xyz;
Temp_0.xyz = ((glstate_matrix_modelview0[0].xyzx * dcl_Input0_POSITION0.xxxx) + Temp_0.xyzx).xyz;
@@ -60,58 +60,30 @@ void main ()
Temp_0.w = inversesqrt(Temp_0.w);
Temp_1.xyz = (Temp_0.wwww * Temp_1.xyzx).xyz;
Temp_2.xyz = glstate_lightmodel_ambient.xyz;
- tmpvar_1 = 0;
- Temp_3.xyz = ((-(Temp_0.xyzx) * unity_LightPosition[tmpvar_1].wwww) + unity_LightPosition[tmpvar_1].xyzx).xyz;
- Temp_1.w = dot (Temp_3.xyz, Temp_3.xyz);
- Temp_2.w = ((Temp_1.w * unity_LightAtten[tmpvar_1].z) + 1.0);
- Temp_2.w = (1.0/(Temp_2.w));
- Temp_1.w = inversesqrt(Temp_1.w);
- Temp_3.xyz = (Temp_1.wwww * Temp_3.xyzx).xyz;
- Temp_1.w = dot (Temp_1.xyz, Temp_3.xyz);
- Temp_1.w = max (Temp_1.w, 0.0);
- Temp_1.w = (Temp_1.w * Temp_2.w);
- Temp_2.xyz = ((unity_LightColor[tmpvar_1].xyzx * Temp_1.wwww) + glstate_lightmodel_ambient.xyzx).xyz;
- tmpvar_1++;
- Temp_3.xyz = ((-(Temp_0.xyzx) * unity_LightPosition[tmpvar_1].wwww) + unity_LightPosition[tmpvar_1].xyzx).xyz;
- Temp_1.w = dot (Temp_3.xyz, Temp_3.xyz);
- Temp_2.w = ((Temp_1.w * unity_LightAtten[tmpvar_1].z) + 1.0);
- Temp_2.w = (1.0/(Temp_2.w));
- Temp_1.w = inversesqrt(Temp_1.w);
- Temp_3.xyz = (Temp_1.wwww * Temp_3.xyzx).xyz;
- Temp_1.w = dot (Temp_1.xyz, Temp_3.xyz);
- Temp_1.w = max (Temp_1.w, 0.0);
- Temp_1.w = (Temp_1.w * Temp_2.w);
- Temp_2.xyz = ((unity_LightColor[tmpvar_1].xyzx * Temp_1.wwww) + Temp_2.xyzx).xyz;
- tmpvar_1++;
- Temp_3.xyz = ((-(Temp_0.xyzx) * unity_LightPosition[tmpvar_1].wwww) + unity_LightPosition[tmpvar_1].xyzx).xyz;
- Temp_1.w = dot (Temp_3.xyz, Temp_3.xyz);
- Temp_2.w = ((Temp_1.w * unity_LightAtten[tmpvar_1].z) + 1.0);
- Temp_2.w = (1.0/(Temp_2.w));
- Temp_1.w = inversesqrt(Temp_1.w);
- Temp_3.xyz = (Temp_1.wwww * Temp_3.xyzx).xyz;
- Temp_1.w = dot (Temp_1.xyz, Temp_3.xyz);
- Temp_1.w = max (Temp_1.w, 0.0);
- Temp_1.w = (Temp_1.w * Temp_2.w);
- Temp_2.xyz = ((unity_LightColor[tmpvar_1].xyzx * Temp_1.wwww) + Temp_2.xyzx).xyz;
- tmpvar_1++;
- Temp_3.xyz = ((-(Temp_0.xyzx) * unity_LightPosition[tmpvar_1].wwww) + unity_LightPosition[tmpvar_1].xyzx).xyz;
- Temp_1.w = dot (Temp_3.xyz, Temp_3.xyz);
- Temp_2.w = ((Temp_1.w * unity_LightAtten[tmpvar_1].z) + 1.0);
- Temp_2.w = (1.0/(Temp_2.w));
- Temp_1.w = inversesqrt(Temp_1.w);
- Temp_3.xyz = (Temp_1.wwww * Temp_3.xyzx).xyz;
- Temp_1.w = dot (Temp_1.xyz, Temp_3.xyz);
- Temp_1.w = max (Temp_1.w, 0.0);
- Temp_1.w = (Temp_1.w * Temp_2.w);
- Temp_2.xyz = ((unity_LightColor[tmpvar_1].xyzx * Temp_1.wwww) + Temp_2.xyzx).xyz;
- tmpvar_1++;
+ Temp_int_0.w = 0;
+ while (true) {
+ if ((Temp_int_0.w >= 4)) {
+ break;
+ };
+ Temp_3.xyz = ((-(Temp_0.xyzx) * unity_LightPosition[Temp_int_0.w].wwww) + unity_LightPosition[Temp_int_0.w].xyzx).xyz;
+ Temp_1.w = dot (Temp_3.xyz, Temp_3.xyz);
+ Temp_2.w = ((Temp_1.w * unity_LightAtten[Temp_int_0.w].z) + 1.0);
+ Temp_2.w = (1.0/(Temp_2.w));
+ Temp_1.w = inversesqrt(Temp_1.w);
+ Temp_3.xyz = (Temp_1.wwww * Temp_3.xyzx).xyz;
+ Temp_1.w = dot (Temp_1.xyz, Temp_3.xyz);
+ Temp_1.w = max (Temp_1.w, 0.0);
+ Temp_1.w = (Temp_1.w * Temp_2.w);
+ Temp_2.xyz = ((unity_LightColor[Temp_int_0.w].xyzx * Temp_1.wwww) + Temp_2.xyzx).xyz;
+ Temp_int_0.w = (Temp_int_0.w + 1);
+ };
VtxGeoOutput2_COLOR0.xyz = (Temp_2.xyzx + Temp_2.xyzx).xyz;
VtxGeoOutput2_COLOR0.w = 1.0;
- gl_Position = tmpvar_2;
+ gl_Position = tmpvar_1;
}
-// stats: 87 alu 0 tex 0 flow
+// stats: 43 alu 0 tex 2 flow
// inputs: 3
// #0: dcl_Input0_POSITION0 (high float) 4x1 [-1]
// #1: dcl_Input1_NORMAL0 (high float) 4x1 [-1]
diff --git a/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/vertex/loops-for-withvec4-outES3Metal.txt b/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/vertex/loops-for-withvec4-outES3Metal.txt
index 748e6b5e632..8976a6750d2 100644
--- a/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/vertex/loops-for-withvec4-outES3Metal.txt
+++ b/3rdparty/bgfx/3rdparty/glsl-optimizer/tests/vertex/loops-for-withvec4-outES3Metal.txt
@@ -52,7 +52,7 @@ float4 Temp_0_2;
float4 Temp_1_3;
float4 Temp_2_4;
float4 Temp_3_5;
-int tmpvar_6;
+int4 Temp_int_0_6;
Temp_0_2 = (_mtl_i.dcl_Input0_POSITION0.yyyy * _mtl_u.glstate_matrix_mvp[1]);
Temp_0_2 = ((_mtl_u.glstate_matrix_mvp[0] * _mtl_i.dcl_Input0_POSITION0.xxxx) + Temp_0_2);
Temp_0_2 = ((_mtl_u.glstate_matrix_mvp[2] * _mtl_i.dcl_Input0_POSITION0.zzzz) + Temp_0_2);
@@ -69,51 +69,23 @@ int tmpvar_6;
Temp_0_2.w = rsqrt(Temp_0_2.w);
Temp_1_3.xyz = (Temp_0_2.wwww * Temp_1_3.xyzx).xyz;
Temp_2_4.xyz = _mtl_u.glstate_lightmodel_ambient.xyz;
- tmpvar_6 = 0;
- Temp_3_5.xyz = ((-(Temp_0_2.xyzx) * _mtl_u.unity_LightPosition[tmpvar_6].wwww) + _mtl_u.unity_LightPosition[tmpvar_6].xyzx).xyz;
- Temp_1_3.w = dot (Temp_3_5.xyz, Temp_3_5.xyz);
- Temp_2_4.w = ((Temp_1_3.w * _mtl_u.unity_LightAtten[tmpvar_6].z) + 1.0);
- Temp_2_4.w = (1.0/(Temp_2_4.w));
- Temp_1_3.w = rsqrt(Temp_1_3.w);
- Temp_3_5.xyz = (Temp_1_3.wwww * Temp_3_5.xyzx).xyz;
- Temp_1_3.w = dot (Temp_1_3.xyz, Temp_3_5.xyz);
- Temp_1_3.w = max (Temp_1_3.w, 0.0);
- Temp_1_3.w = (Temp_1_3.w * Temp_2_4.w);
- Temp_2_4.xyz = ((_mtl_u.unity_LightColor[tmpvar_6].xyzx * Temp_1_3.wwww) + _mtl_u.glstate_lightmodel_ambient.xyzx).xyz;
- tmpvar_6++;
- Temp_3_5.xyz = ((-(Temp_0_2.xyzx) * _mtl_u.unity_LightPosition[tmpvar_6].wwww) + _mtl_u.unity_LightPosition[tmpvar_6].xyzx).xyz;
- Temp_1_3.w = dot (Temp_3_5.xyz, Temp_3_5.xyz);
- Temp_2_4.w = ((Temp_1_3.w * _mtl_u.unity_LightAtten[tmpvar_6].z) + 1.0);
- Temp_2_4.w = (1.0/(Temp_2_4.w));
- Temp_1_3.w = rsqrt(Temp_1_3.w);
- Temp_3_5.xyz = (Temp_1_3.wwww * Temp_3_5.xyzx).xyz;
- Temp_1_3.w = dot (Temp_1_3.xyz, Temp_3_5.xyz);
- Temp_1_3.w = max (Temp_1_3.w, 0.0);
- Temp_1_3.w = (Temp_1_3.w * Temp_2_4.w);
- Temp_2_4.xyz = ((_mtl_u.unity_LightColor[tmpvar_6].xyzx * Temp_1_3.wwww) + Temp_2_4.xyzx).xyz;
- tmpvar_6++;
- Temp_3_5.xyz = ((-(Temp_0_2.xyzx) * _mtl_u.unity_LightPosition[tmpvar_6].wwww) + _mtl_u.unity_LightPosition[tmpvar_6].xyzx).xyz;
- Temp_1_3.w = dot (Temp_3_5.xyz, Temp_3_5.xyz);
- Temp_2_4.w = ((Temp_1_3.w * _mtl_u.unity_LightAtten[tmpvar_6].z) + 1.0);
- Temp_2_4.w = (1.0/(Temp_2_4.w));
- Temp_1_3.w = rsqrt(Temp_1_3.w);
- Temp_3_5.xyz = (Temp_1_3.wwww * Temp_3_5.xyzx).xyz;
- Temp_1_3.w = dot (Temp_1_3.xyz, Temp_3_5.xyz);
- Temp_1_3.w = max (Temp_1_3.w, 0.0);
- Temp_1_3.w = (Temp_1_3.w * Temp_2_4.w);
- Temp_2_4.xyz = ((_mtl_u.unity_LightColor[tmpvar_6].xyzx * Temp_1_3.wwww) + Temp_2_4.xyzx).xyz;
- tmpvar_6++;
- Temp_3_5.xyz = ((-(Temp_0_2.xyzx) * _mtl_u.unity_LightPosition[tmpvar_6].wwww) + _mtl_u.unity_LightPosition[tmpvar_6].xyzx).xyz;
- Temp_1_3.w = dot (Temp_3_5.xyz, Temp_3_5.xyz);
- Temp_2_4.w = ((Temp_1_3.w * _mtl_u.unity_LightAtten[tmpvar_6].z) + 1.0);
- Temp_2_4.w = (1.0/(Temp_2_4.w));
- Temp_1_3.w = rsqrt(Temp_1_3.w);
- Temp_3_5.xyz = (Temp_1_3.wwww * Temp_3_5.xyzx).xyz;
- Temp_1_3.w = dot (Temp_1_3.xyz, Temp_3_5.xyz);
- Temp_1_3.w = max (Temp_1_3.w, 0.0);
- Temp_1_3.w = (Temp_1_3.w * Temp_2_4.w);
- Temp_2_4.xyz = ((_mtl_u.unity_LightColor[tmpvar_6].xyzx * Temp_1_3.wwww) + Temp_2_4.xyzx).xyz;
- tmpvar_6++;
+ Temp_int_0_6.w = 0;
+ while (true) {
+ if ((Temp_int_0_6.w >= 4)) {
+ break;
+ };
+ Temp_3_5.xyz = ((-(Temp_0_2.xyzx) * _mtl_u.unity_LightPosition[Temp_int_0_6.w].wwww) + _mtl_u.unity_LightPosition[Temp_int_0_6.w].xyzx).xyz;
+ Temp_1_3.w = dot (Temp_3_5.xyz, Temp_3_5.xyz);
+ Temp_2_4.w = ((Temp_1_3.w * _mtl_u.unity_LightAtten[Temp_int_0_6.w].z) + 1.0);
+ Temp_2_4.w = (1.0/(Temp_2_4.w));
+ Temp_1_3.w = rsqrt(Temp_1_3.w);
+ Temp_3_5.xyz = (Temp_1_3.wwww * Temp_3_5.xyzx).xyz;
+ Temp_1_3.w = dot (Temp_1_3.xyz, Temp_3_5.xyz);
+ Temp_1_3.w = max (Temp_1_3.w, 0.0);
+ Temp_1_3.w = (Temp_1_3.w * Temp_2_4.w);
+ Temp_2_4.xyz = ((_mtl_u.unity_LightColor[Temp_int_0_6.w].xyzx * Temp_1_3.wwww) + Temp_2_4.xyzx).xyz;
+ Temp_int_0_6.w = (Temp_int_0_6.w + 1);
+ };
_mtl_o.VtxGeoOutput2_COLOR0.xyz = (Temp_2_4.xyzx + Temp_2_4.xyzx).xyz;
_mtl_o.VtxGeoOutput2_COLOR0.w = 1.0;
_mtl_o.gl_Position = phase0_Output0_1;
@@ -121,7 +93,7 @@ int tmpvar_6;
}
-// stats: 87 alu 0 tex 0 flow
+// stats: 43 alu 0 tex 2 flow
// inputs: 3
// #0: dcl_Input0_POSITION0 (high float) 4x1 [-1] loc 0
// #1: dcl_Input1_NORMAL0 (high float) 4x1 [-1] loc 1
diff --git a/3rdparty/bgfx/3rdparty/ocornut-imgui/imconfig.h b/3rdparty/bgfx/3rdparty/ocornut-imgui/imconfig.h
index 17cad4a4b43..f41c5660b3a 100644
--- a/3rdparty/bgfx/3rdparty/ocornut-imgui/imconfig.h
+++ b/3rdparty/bgfx/3rdparty/ocornut-imgui/imconfig.h
@@ -12,7 +12,8 @@
//#define ImVector MyVector
//---- Define assertion handler. Defaults to calling assert().
-//#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
+#include <assert.h>
+#define IM_ASSERT(_EXPR, ...) assert(_EXPR)
//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows.
//#define IMGUI_API __declspec( dllexport )
diff --git a/3rdparty/bgfx/3rdparty/ocornut-imgui/imgui.cpp b/3rdparty/bgfx/3rdparty/ocornut-imgui/imgui.cpp
index 4e777749544..80f4b6eaf03 100644
--- a/3rdparty/bgfx/3rdparty/ocornut-imgui/imgui.cpp
+++ b/3rdparty/bgfx/3rdparty/ocornut-imgui/imgui.cpp
@@ -19,7 +19,8 @@
- FREQUENTLY ASKED QUESTIONS (FAQ), TIPS
- How do I update to a newer version of ImGui?
- Can I have multiple widgets with the same label? Can I have widget without a label? (Yes)
- - Why is my text output blurry?
+ - I integrated ImGui in my engine and the text or lines are blurry..
+ - I integrated ImGui in my engine and some elements are disappearing when I move windows around..
- How can I load a different font than the default?
- How can I load multiple fonts?
- How can I display and input non-latin characters such as Chinese, Japanese, Korean, Cyrillic?
@@ -187,7 +188,7 @@
- 2015/03/17 (1.36) - renamed GetItemBoxMin()/GetItemBoxMax()/IsMouseHoveringBox() to GetItemRectMin()/GetItemRectMax()/IsMouseHoveringRect(). Kept inline redirection function (will obsolete).
- 2015/03/15 (1.36) - renamed style.TreeNodeSpacing to style.IndentSpacing, ImGuiStyleVar_TreeNodeSpacing to ImGuiStyleVar_IndentSpacing
- 2015/03/13 (1.36) - renamed GetWindowIsFocused() to IsWindowFocused(). Kept inline redirection function (will obsolete).
- - 2015/03/08 (1.35) - renamed style.ScrollBarWidth to style.ScrollbarWidth
+ - 2015/03/08 (1.35) - renamed style.ScrollBarWidth to style.ScrollbarWidth (casing)
- 2015/02/27 (1.34) - renamed OpenNextNode(bool) to SetNextTreeNodeOpened(bool, ImGuiSetCond). Kept inline redirection function (will obsolete).
- 2015/02/27 (1.34) - renamed ImGuiSetCondition_*** to ImGuiSetCond_***, and _FirstUseThisSession becomes _Once.
- 2015/02/11 (1.32) - changed text input callback ImGuiTextEditCallback return type from void-->int. reserved for future use, return 0 for now.
@@ -281,9 +282,9 @@
Button("Hello###ID"; // Label = "Hello", ID = hash of "ID"
Button("World###ID"; // Label = "World", ID = hash of "ID" (same as above)
-
- sprintf(buf, "My game (%f FPS)###MyGame");
- Begin(buf); // Variable label, ID = hash of "MyGame"
+
+ sprintf(buf, "My game (%f FPS)###MyGame");
+ Begin(buf); // Variable label, ID = hash of "MyGame"
- Use PushID() / PopID() to create scopes and avoid ID conflicts within the same Window.
This is the most convenient way of distinguishing ID if you are iterating and creating many UI elements.
@@ -336,8 +337,12 @@
e.g. when displaying a single object that may change over time (1-1 relationship), using a static string as ID will preserve your node open/closed state when the targeted object change.
e.g. when displaying a list of objects, using indices or pointers as ID will preserve the node open/closed state differently. experiment and see what makes more sense!
- Q: Why is my text output blurry?
- A: In your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f)
+ Q: I integrated ImGui in my engine and the text or lines are blurry..
+ A: In your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f).
+ Also make sure your orthographic projection matrix and io.DisplaySize matches your actual framebuffer dimension.
+
+ Q. I integrated ImGui in my engine and some elements are disappearing when I move windows around..
+ Most likely you are mishandling the clipping rectangles in your render function. Rectangles provided by ImGui are defined as (x1,y1,x2,y2) and NOT as (x1,y1,width,height).
Q: How can I load a different font than the default? (default is an embedded version of ProggyClean.ttf, rendered at size 13)
A: Use the font atlas to load the TTF file you want:
@@ -394,14 +399,19 @@
Issue numbers (#) refer to github issues.
The list below consist mostly of notes of things to do before they are requested/discussed by users (at that point it usually happens on the github)
- - window: autofit feedback loop when user relies on any dynamic layout (window width multiplier, column). maybe just clearly drop manual autofit?
- - window: add a way for very transient windows (non-saved, temporary overlay over hundreds of objects) to "clean" up from the global window list.
+ - window: maximum window size settings (per-axis). for large popups in particular user may not want the popup to fill all space.
+ - window: add a way for very transient windows (non-saved, temporary overlay over hundreds of objects) to "clean" up from the global window list. perhaps a lightweight explicit cleanup pass.
+ - window: auto-fit feedback loop when user relies on any dynamic layout (window width multiplier, column). clarify.
- window: allow resizing of child windows (possibly given min/max for each axis?)
- window: background options for child windows, border option (disable rounding)
+ - window: add a way to clear an existing window instead of appending (e.g. for tooltip override using a consistent api rather than the deferred tooltip)
- window: resizing from any sides? + mouse cursor directives for app.
+!- window: begin with *p_opened == false should return false.
- window: get size/pos helpers given names (see discussion in #249)
- window: a collapsed window can be stuck behind the main menu bar?
+ - window: detect extra End() call that pop the "Debug" window out and assert at call site instead of later.
!- scrolling: allow immediately effective change of scroll if we haven't appended items yet
+ - splitter: formalize the splitter idiom into an official api (we want to handle n-way split)
- widgets: display mode: widget-label, label-widget (aligned on column or using fixed size), label-newline-tab-widget etc.
- widgets: clean up widgets internal toward exposing everything.
- widgets: add disabled and read-only modes (#211)
@@ -416,6 +426,8 @@
- input number: use mouse wheel to step up/down
- input number: applying arithmetics ops (+,-,*,/) messes up with text edit undo stack.
- text: proper alignment options
+ - image/image button: misalignment on padded/bordered button?
+ - image/image button: parameters are confusing, image() has tint_col,border_col whereas imagebutton() has bg_col/tint_col. Even thou they are different parameters ordering could be more consistent. can we fix that?
- layout: horizontal layout helper (#97)
- layout: more generic alignment state (left/right/centered) for single items?
- layout: clean up the InputFloatN/SliderFloatN/ColorEdit4 layout code. item width should include frame padding.
@@ -426,23 +438,25 @@
- popup: border options. richer api like BeginChild() perhaps? (#197)
- combo: sparse combo boxes (via function call?)
- combo: contents should extends to fit label if combo widget is small
- - combo/listbox: keyboard control. need InputText-like non-active focus + key handling. considering keybord for custom listbox (pr #203)
+ - combo/listbox: keyboard control. need InputText-like non-active focus + key handling. considering keyboard for custom listbox (pr #203)
- listbox: multiple selection
- listbox: user may want to initial scroll to focus on the one selected value?
- listbox: keyboard navigation.
- listbox: scrolling should track modified selection.
+-! menus/popups: clarify usage of popups id, how MenuItem/Selectable closing parent popups affects the ID, etc. this is quite fishy needs improvement! (#331)
- menus: local shortcuts, global shortcuts (#126)
- menus: icons
- menus: menubars: some sort of priority / effect of main menu-bar on desktop size?
+ - statusbar: add a per-window status bar helper similar to what menubar does.
- tabs
- separator: separator on the initial position of a window is not visible (cursorpos.y <= clippos.y)
- gauge: various forms of gauge/loading bars widgets
- - color: add a better color picker (perhaps a popup).
- - plot: plotlines should use the polygon-stroke facilities (currently issues with averaging normals)
+ - color: add a better color picker
+ - plot: PlotLines() should use the polygon-stroke facilities (currently issues with averaging normals)
- plot: make it easier for user to draw extra stuff into the graph (e.g: draw basis, highlight certain points, 2d plots, multiple plots)
- plot: "smooth" automatic scale over time, user give an input 0.0(full user scale) 1.0(full derived from value)
- plot: add a helper e.g. Plot(char* label, float value, float time_span=2.0f) that stores values and Plot them for you - probably another function name. and/or automatically allow to plot ANY displayed value (more reliance on stable ID)
- - file selection widget -> build the tool in our codebase to improve model-dialog idioms
+ - applet: file selection widget (as an example)
- slider: allow using the [-]/[+] buttons used by InputFloat()/InputInt()
- slider: initial absolute click is imprecise. change to relative movement slider (same as scrollbar).
- slider: add dragging-based widgets to edit values with mouse (on 2 axises), saving screen real-estate.
@@ -453,13 +467,15 @@
- text edit: centered text for slider as input text so it matches typical positioning.
- text edit: flag to disable live update of the user buffer.
- text edit: field resize behavior - field could stretch when being edited? hover tooltip shows more text?
- - tree: add treenode/treepush int variants? because (void*) cast from int warns on some platforms/settings
+ - tree node / optimization: avoid formatting when clipped.
+ - tree node: tree-node/header right-most side doesn't take account of horizontal scrolling.
+ - tree node: add treenode/treepush int variants? because (void*) cast from int warns on some platforms/settings
- textwrapped: figure out better way to use TextWrapped() in an always auto-resize context (tooltip, etc.) (git issue #249)
- settings: write more decent code to allow saving/loading new fields
- settings: api for per-tool simple persistent data (bool,int,float,columns sizes,etc.) in .ini file
- style: store rounded corners in texture to use 1 quad per corner (filled and wireframe). so rounding have minor cost.
- style: color-box not always square?
- - style: a concept of "compact style" that the end-user can easily rely on (e.g. PushStyleCompact()?) that maps that other settings?
+ - style: a concept of "compact style" that the end-user can easily rely on (e.g. PushStyleCompact()?) that maps to other settings? avoid implementing duplicate helpers such as SmallCheckbox(), etc.
- text: simple markup language for color change?
- log: LogButtons() options for specifying depth and/or hiding depth slider
- log: have more control over the log scope (e.g. stop logging when leaving current tree node scope)
@@ -473,11 +489,12 @@
- focus: SetKeyboardFocusHere() on with >= 0 offset could be done on same frame (else latch and modulate on beginning of next frame)
- input: rework IO to be able to pass actual events to fix temporal aliasing issues.
- input: support track pad style scrolling & slider edit.
- - memory: add a way to discard allocs of unused/transient windows. with the current architecture new windows (including popup, opened combos, listbox) perform at least 3 allocs.
- misc: provide a way to compile out the entire implementation while providing a dummy API (e.g. #define IMGUI_DUMMY_IMPL)
- misc: double-clicking on title bar to minimize isn't consistent, perhaps move to single-click on left-most collapse icon?
- style editor: have a more global HSV setter (e.g. alter hue on all elements). consider replacing active/hovered by offset in HSV space?
- style editor: color child window height expressed in multiple of line height.
+!- examples: directx9/directx11: resizing window duplicate the font data :(
+ - optimization: use another hash function than crc32, e.g. FNV1a
- optimization/render: merge command-lists with same clip-rect into one even if they aren't sequential? (as long as in-between clip rectangle don't overlap)?
- optimization: turn some the various stack vectors into statically-sized arrays
- optimization: better clipping for multi-component widgets
@@ -698,6 +715,10 @@ ImGuiIO::ImGuiIO()
MouseDoubleClickTime = 0.30f;
MouseDoubleClickMaxDist = 6.0f;
MouseDragThreshold = 6.0f;
+ for (int i = 0; i < IM_ARRAYSIZE(MouseDownDuration); i++)
+ MouseDownDuration[i] = MouseDownDurationPrev[i] = -1.0f;
+ for (int i = 0; i < IM_ARRAYSIZE(KeysDownDuration); i++)
+ KeysDownDuration[i] = KeysDownDurationPrev[i] = -1.0f;
for (int i = 0; i < ImGuiKey_COUNT; i++)
KeyMap[i] = -1;
KeyRepeatDelay = 0.250f;
@@ -898,7 +919,7 @@ int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char*
if ((*str & 0xe0) == 0xc0)
{
*out_char = 0xFFFD; // will be invalid but not end of string
- if (in_text_end && in_text_end - (const char*)str < 2) return 0;
+ if (in_text_end && in_text_end - (const char*)str < 2) return 1;
if (*str < 0xc2) return 2;
c = (unsigned int)((*str++ & 0x1f) << 6);
if ((*str & 0xc0) != 0x80) return 2;
@@ -909,7 +930,7 @@ int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char*
if ((*str & 0xf0) == 0xe0)
{
*out_char = 0xFFFD; // will be invalid but not end of string
- if (in_text_end && in_text_end - (const char*)str < 3) return 0;
+ if (in_text_end && in_text_end - (const char*)str < 3) return 1;
if (*str == 0xe0 && (str[1] < 0xa0 || str[1] > 0xbf)) return 3;
if (*str == 0xed && str[1] > 0x9f) return 3; // str[1] < 0x80 is checked below
c = (unsigned int)((*str++ & 0x0f) << 12);
@@ -923,7 +944,7 @@ int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char*
if ((*str & 0xf8) == 0xf0)
{
*out_char = 0xFFFD; // will be invalid but not end of string
- if (in_text_end && in_text_end - (const char*)str < 4) return 0;
+ if (in_text_end && in_text_end - (const char*)str < 4) return 1;
if (*str > 0xf4) return 4;
if (*str == 0xf0 && (str[1] < 0x90 || str[1] > 0xbf)) return 4;
if (*str == 0xf4 && str[1] > 0x8f) return 4; // str[1] < 0x80 is checked below
@@ -1303,14 +1324,16 @@ ImGuiTextFilter::ImGuiTextFilter(const char* default_filter)
}
}
-void ImGuiTextFilter::Draw(const char* label, float width)
+bool ImGuiTextFilter::Draw(const char* label, float width)
{
if (width != 0.0f)
ImGui::PushItemWidth(width);
- ImGui::InputText(label, InputBuf, IM_ARRAYSIZE(InputBuf));
+ bool value_changed = ImGui::InputText(label, InputBuf, IM_ARRAYSIZE(InputBuf));
if (width != 0.0f)
ImGui::PopItemWidth();
- Build();
+ if (value_changed)
+ Build();
+ return value_changed;
}
void ImGuiTextFilter::TextRange::split(char separator, ImVector<TextRange>& out)
@@ -1564,11 +1587,18 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window = NULL)
{
ImGuiState& g = *GImGui;
g.ActiveId = id;
- g.ActiveIdIsFocusedOnly = false;
+ g.ActiveIdAllowHoveringOthers = false;
g.ActiveIdIsJustActivated = true;
g.ActiveIdWindow = window;
}
+void ImGui::SetHoveredID(ImGuiID id)
+{
+ ImGuiState& g = *GImGui;
+ g.HoveredId = id;
+ g.HoveredIdAllowHoveringOthers = false;
+}
+
void ImGui::KeepAliveID(ImGuiID id)
{
ImGuiState& g = *GImGui;
@@ -1627,7 +1657,7 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id)
window->DC.LastItemHoveredRect = true;
window->DC.LastItemHoveredAndUsable = false;
if (g.HoveredRootWindow == window->RootWindow)
- if (g.ActiveId == 0 || (id && g.ActiveId == *id) || g.ActiveIdIsFocusedOnly || (g.ActiveId == window->MoveID))
+ if (g.ActiveId == 0 || (id && g.ActiveId == *id) || g.ActiveIdAllowHoveringOthers || (g.ActiveId == window->MoveID))
if (IsWindowContentHoverable(window))
window->DC.LastItemHoveredAndUsable = true;
}
@@ -1656,11 +1686,11 @@ bool ImGui::IsClippedEx(const ImRect& bb, const ImGuiID* id, bool clip_even_when
bool ImGui::IsHovered(const ImRect& bb, ImGuiID id, bool flatten_childs)
{
ImGuiState& g = *GImGui;
- if (g.HoveredId == 0 || g.HoveredId == id)
+ if (g.HoveredId == 0 || g.HoveredId == id || g.HoveredIdAllowHoveringOthers)
{
ImGuiWindow* window = GetCurrentWindowRead();
if (g.HoveredWindow == window || (flatten_childs && g.HoveredRootWindow == window->RootWindow))
- if ((g.ActiveId == 0 || g.ActiveId == id || g.ActiveIdIsFocusedOnly) && ImGui::IsMouseHoveringRect(bb.Min, bb.Max))
+ if ((g.ActiveId == 0 || g.ActiveId == id || g.ActiveIdAllowHoveringOthers) && ImGui::IsMouseHoveringRect(bb.Min, bb.Max))
if (IsWindowContentHoverable(g.HoveredRootWindow))
return true;
}
@@ -1742,6 +1772,17 @@ void ImGui::MemFree(void* ptr)
return GImGui->IO.MemFreeFn(ptr);
}
+const char* ImGui::GetClipboardText()
+{
+ return GImGui->IO.GetClipboardTextFn ? GImGui->IO.GetClipboardTextFn() : "";
+}
+
+void ImGui::SetClipboardText(const char* text)
+{
+ if (GImGui->IO.SetClipboardTextFn)
+ GImGui->IO.SetClipboardTextFn(text);
+}
+
const char* ImGui::GetVersion()
{
return IMGUI_VERSION;
@@ -1839,10 +1880,10 @@ void ImGui::NewFrame()
g.IO.MousePosPrev = g.IO.MousePos;
for (int i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++)
{
+ g.IO.MouseClicked[i] = g.IO.MouseDown[i] && g.IO.MouseDownDuration[i] < 0.0f;
+ g.IO.MouseReleased[i] = !g.IO.MouseDown[i] && g.IO.MouseDownDuration[i] >= 0.0f;
g.IO.MouseDownDurationPrev[i] = g.IO.MouseDownDuration[i];
g.IO.MouseDownDuration[i] = g.IO.MouseDown[i] ? (g.IO.MouseDownDuration[i] < 0.0f ? 0.0f : g.IO.MouseDownDuration[i] + g.IO.DeltaTime) : -1.0f;
- g.IO.MouseClicked[i] = g.IO.MouseDownDuration[i] == 0.0f;
- g.IO.MouseReleased[i] = g.IO.MouseDownDurationPrev[i] >= 0.0f && !g.IO.MouseDown[i];
g.IO.MouseDoubleClicked[i] = false;
if (g.IO.MouseClicked[i])
{
@@ -1877,6 +1918,7 @@ void ImGui::NewFrame()
// Clear reference to active widget if the widget isn't alive anymore
g.HoveredIdPreviousFrame = g.HoveredId;
g.HoveredId = 0;
+ g.HoveredIdAllowHoveringOthers = false;
if (!g.ActiveIdIsAlive && g.ActiveIdPreviousFrame == g.ActiveId && g.ActiveId != 0)
SetActiveID(0);
g.ActiveIdPreviousFrame = g.ActiveId;
@@ -2259,78 +2301,86 @@ static void PopClipRect()
window->ClipRect = window->DrawList->_ClipRectStack.back();
}
-void ImGui::Render()
+// This is normally called by Render(). You may want to call it directly if you want to avoid calling Render() but the gain will be very minimal.
+void ImGui::EndFrame()
{
ImGuiState& g = *GImGui;
- IM_ASSERT(g.Initialized); // Forgot to call ImGui::NewFrame()
-
- const bool first_render_of_the_frame = (g.FrameCountRendered != g.FrameCount);
- g.FrameCountRendered = g.FrameCount;
+ IM_ASSERT(g.Initialized); // Forgot to call ImGui::NewFrame()
+ IM_ASSERT(g.FrameCountEnded != g.FrameCount); // ImGui::EndFrame() called multiple times, or forgot to call ImGui::NewFrame() again
- if (first_render_of_the_frame)
+ // Render tooltip
+ if (g.Tooltip[0])
{
- // Hide implicit "Debug" window if it hasn't been used
- IM_ASSERT(g.CurrentWindowStack.Size == 1); // Mismatched Begin/End
- if (g.CurrentWindow && !g.CurrentWindow->Accessed)
- g.CurrentWindow->Active = false;
- ImGui::End();
+ ImGui::BeginTooltip();
+ ImGui::TextUnformatted(g.Tooltip);
+ ImGui::EndTooltip();
+ }
+
+ // Hide implicit "Debug" window if it hasn't been used
+ IM_ASSERT(g.CurrentWindowStack.Size == 1); // Mismatched Begin/End
+ if (g.CurrentWindow && !g.CurrentWindow->Accessed)
+ g.CurrentWindow->Active = false;
+ ImGui::End();
- // Click to focus window and start moving (after we're done with all our widgets)
- if (!g.ActiveId)
- g.MovedWindow = NULL;
- if (g.ActiveId == 0 && g.HoveredId == 0 && g.IO.MouseClicked[0])
+ // Click to focus window and start moving (after we're done with all our widgets)
+ if (!g.ActiveId)
+ g.MovedWindow = NULL;
+ if (g.ActiveId == 0 && g.HoveredId == 0 && g.IO.MouseClicked[0])
+ {
+ if (!(g.FocusedWindow && !g.FocusedWindow->WasActive && g.FocusedWindow->Active)) // Unless we just made a popup appear
{
- if (!(g.FocusedWindow && !g.FocusedWindow->WasActive && g.FocusedWindow->Active)) // Unless we just made a popup appear
+ if (g.HoveredRootWindow != NULL)
{
- if (g.HoveredRootWindow != NULL)
- {
- FocusWindow(g.HoveredWindow);
- if (!(g.HoveredWindow->Flags & ImGuiWindowFlags_NoMove))
- {
- g.MovedWindow = g.HoveredWindow;
- SetActiveID(g.HoveredRootWindow->MoveID, g.HoveredRootWindow);
- }
- }
- else if (g.FocusedWindow != NULL && GetFrontMostModalRootWindow() == NULL)
+ FocusWindow(g.HoveredWindow);
+ if (!(g.HoveredWindow->Flags & ImGuiWindowFlags_NoMove))
{
- // Clicking on void disable focus
- FocusWindow(NULL);
+ g.MovedWindow = g.HoveredWindow;
+ SetActiveID(g.HoveredRootWindow->MoveID, g.HoveredRootWindow);
}
}
+ else if (g.FocusedWindow != NULL && GetFrontMostModalRootWindow() == NULL)
+ {
+ // Clicking on void disable focus
+ FocusWindow(NULL);
+ }
}
+ }
- // Sort the window list so that all child windows are after their parent
- // We cannot do that on FocusWindow() because childs may not exist yet
- g.WindowsSortBuffer.resize(0);
- g.WindowsSortBuffer.reserve(g.Windows.Size);
- for (int i = 0; i != g.Windows.Size; i++)
- {
- ImGuiWindow* window = g.Windows[i];
- if (window->Flags & ImGuiWindowFlags_ChildWindow) // if a child is active its parent will add it
- if (window->Active)
- continue;
- AddWindowToSortedBuffer(g.WindowsSortBuffer, window);
- }
- IM_ASSERT(g.Windows.Size == g.WindowsSortBuffer.Size); // we done something wrong
- g.Windows.swap(g.WindowsSortBuffer);
-
- // Clear Input data for next frame
- g.IO.MouseWheel = 0.0f;
- memset(g.IO.InputCharacters, 0, sizeof(g.IO.InputCharacters));
+ // Sort the window list so that all child windows are after their parent
+ // We cannot do that on FocusWindow() because childs may not exist yet
+ g.WindowsSortBuffer.resize(0);
+ g.WindowsSortBuffer.reserve(g.Windows.Size);
+ for (int i = 0; i != g.Windows.Size; i++)
+ {
+ ImGuiWindow* window = g.Windows[i];
+ if (window->Flags & ImGuiWindowFlags_ChildWindow) // if a child is active its parent will add it
+ if (window->Active)
+ continue;
+ AddWindowToSortedBuffer(g.WindowsSortBuffer, window);
}
+ IM_ASSERT(g.Windows.Size == g.WindowsSortBuffer.Size); // we done something wrong
+ g.Windows.swap(g.WindowsSortBuffer);
+
+ // Clear Input data for next frame
+ g.IO.MouseWheel = 0.0f;
+ memset(g.IO.InputCharacters, 0, sizeof(g.IO.InputCharacters));
+
+ g.FrameCountEnded = g.FrameCount;
+}
+
+void ImGui::Render()
+{
+ ImGuiState& g = *GImGui;
+ IM_ASSERT(g.Initialized); // Forgot to call ImGui::NewFrame()
+
+ if (g.FrameCountEnded != g.FrameCount)
+ ImGui::EndFrame();
+ g.FrameCountRendered = g.FrameCount;
// Skip render altogether if alpha is 0.0
- // Note that vertex buffers have been created and are wasted, so it is best practice that you don't create windows in the first place, or respond to Begin() returning false.
+ // Note that vertex buffers have been created and are wasted, so it is best practice that you don't create windows in the first place, or consistently respond to Begin() returning false.
if (g.Style.Alpha > 0.0f)
{
- // Render tooltip
- if (g.Tooltip[0])
- {
- ImGui::BeginTooltip();
- ImGui::TextUnformatted(g.Tooltip);
- ImGui::EndTooltip();
- }
-
// Gather windows to render
g.IO.MetricsRenderVertices = g.IO.MetricsRenderIndices = g.IO.MetricsActiveWindows = 0;
for (int i = 0; i < IM_ARRAYSIZE(g.RenderDrawLists); i++)
@@ -2360,13 +2410,13 @@ void ImGui::Render()
for (int i = 1; i < IM_ARRAYSIZE(g.RenderDrawLists); i++)
{
ImVector<ImDrawList*>& layer = g.RenderDrawLists[i];
- if (!layer.empty())
- {
- memcpy(&g.RenderDrawLists[0][n], &layer[0], layer.Size * sizeof(ImDrawList*));
- n += layer.Size;
- }
+ if (layer.empty())
+ continue;
+ memcpy(&g.RenderDrawLists[0][n], &layer[0], layer.Size * sizeof(ImDrawList*));
+ n += layer.Size;
}
+ // Draw software mouse cursor if requested
if (g.IO.MouseDrawCursor)
{
const ImGuiMouseCursorData& cursor_data = g.MouseCursorData[g.MouseCursor];
@@ -2392,9 +2442,7 @@ void ImGui::Render()
// Render. If user hasn't set a callback then they may retrieve the draw data via GetDrawData()
if (g.RenderDrawData.CmdListsCount > 0 && g.IO.RenderDrawListsFn != NULL)
- {
g.IO.RenderDrawListsFn(&g.RenderDrawData);
- }
}
}
@@ -3276,13 +3324,13 @@ void ImGui::EndChild()
}
// Helper to create a child window / scrolling region that looks like a normal widget frame.
-bool ImGui::BeginChildFrame(ImGuiID id, const ImVec2& size)
+bool ImGui::BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags extra_flags)
{
ImGuiState& g = *GImGui;
const ImGuiStyle& style = g.Style;
ImGui::PushStyleColor(ImGuiCol_ChildWindowBg, style.Colors[ImGuiCol_FrameBg]);
ImGui::PushStyleVar(ImGuiStyleVar_ChildWindowRounding, style.FrameRounding);
- return ImGui::BeginChild(id, size, false, ImGuiWindowFlags_NoMove);
+ return ImGui::BeginChild(id, size, false, ImGuiWindowFlags_NoMove | extra_flags);
}
void ImGui::EndChildFrame()
@@ -3430,8 +3478,9 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_
{
ImGuiState& g = *GImGui;
const ImGuiStyle& style = g.Style;
+ IM_ASSERT(name != NULL); // Window name required
IM_ASSERT(g.Initialized); // Forgot to call ImGui::NewFrame()
- IM_ASSERT(name != NULL); // Must pass a name
+ IM_ASSERT(g.FrameCountEnded != g.FrameCount); // Called ImGui::Render() or ImGui::EndFrame() and haven't called ImGui::NewFrame() again yet
if (flags & ImGuiWindowFlags_NoInputs)
flags |= ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize;
@@ -3839,7 +3888,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_
else if ((flags & ImGuiWindowFlags_Popup) != 0)
window->DrawList->AddRectFilled(window->Pos, window->Pos+window->Size, window->Color(ImGuiCol_WindowBg, bg_alpha), window_rounding);
else if ((flags & ImGuiWindowFlags_ChildWindow) != 0)
- window->DrawList->AddRectFilled(window->Pos, window->Pos+window->Size - window->ScrollbarSizes, window->Color(ImGuiCol_ChildWindowBg, bg_alpha), window_rounding, window->ScrollbarY ? (1|8) : (0xF));
+ window->DrawList->AddRectFilled(window->Pos, window->Pos+window->Size, window->Color(ImGuiCol_ChildWindowBg, bg_alpha), window_rounding);
else
window->DrawList->AddRectFilled(window->Pos, window->Pos+window->Size, window->Color(ImGuiCol_WindowBg, bg_alpha), window_rounding);
}
@@ -3958,7 +4007,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_
// We set this up after processing the resize grip so that our clip rectangle doesn't lag by a frame
// Note that if our window is collapsed we will end up with a null clipping rectangle which is the correct behavior.
const ImRect title_bar_rect = window->TitleBarRect();
- ImRect clip_rect(title_bar_rect.Min.x+0.5f+window->WindowPadding.x*0.5f, title_bar_rect.Max.y+window->MenuBarHeight()+0.5f, window->Pos.x+window->Size.x+0.5f-window->WindowPadding.x*0.5f, window->Pos.y+window->Size.y+0.5f);
+ ImRect clip_rect(title_bar_rect.Min.x+0.5f+window->WindowPadding.x*0.5f, title_bar_rect.Max.y+window->MenuBarHeight()+0.5f, window->Pos.x+window->Size.x-window->WindowPadding.x*0.5f, window->Pos.y+window->Size.y);
if ((flags & ImGuiWindowFlags_ChildWindow) && (flags & ImGuiWindowFlags_ShowBorders))
clip_rect.Min += ImVec2(1.0f,1.0f);
clip_rect.Max.x -= window->ScrollbarY ? style.ScrollbarSize : 0.0f;
@@ -4029,11 +4078,19 @@ static void Scrollbar(ImGuiWindow* window, bool horizontal)
bool other_scrollbar = (horizontal ? window->ScrollbarY : window->ScrollbarX);
float other_scrollbar_size_w = other_scrollbar ? style.ScrollbarSize : 0.0f;
const ImRect window_rect = window->Rect();
+ const float border_offset = (window->Flags & ImGuiWindowFlags_ShowBorders) ? 1.0f : 0.0f;
ImRect bb = horizontal
- ? ImRect(window->Pos.x + 1, window_rect.Max.y - style.ScrollbarSize, window_rect.Max.x - 1 - other_scrollbar_size_w, window_rect.Max.y)
- : ImRect(window_rect.Max.x - style.ScrollbarSize, window->Pos.y + window->TitleBarHeight()+1, window_rect.Max.x, window_rect.Max.y - 1 - other_scrollbar_size_w);
- window->DrawList->AddRectFilled(bb.Min, bb.Max, window->Color(ImGuiCol_ScrollbarBg));
- bb.Expand(-3.0f);
+ ? ImRect(window->Pos.x + border_offset, window_rect.Max.y - style.ScrollbarSize, window_rect.Max.x - other_scrollbar_size_w, window_rect.Max.y)
+ : ImRect(window_rect.Max.x - style.ScrollbarSize, window->Pos.y + window->TitleBarHeight() + border_offset, window_rect.Max.x, window_rect.Max.y - other_scrollbar_size_w);
+
+ float window_rounding = (window->Flags & ImGuiWindowFlags_ChildWindow) ? style.ChildWindowRounding : style.WindowRounding;
+ int window_rounding_corners;
+ if (horizontal)
+ window_rounding_corners = 8 | (other_scrollbar ? 0 : 4);
+ else
+ window_rounding_corners = ((window->Flags & ImGuiWindowFlags_NoTitleBar) ? 2 : 0) | (other_scrollbar ? 0 : 4);
+ window->DrawList->AddRectFilled(bb.Min, bb.Max, window->Color(ImGuiCol_ScrollbarBg), window_rounding, window_rounding_corners);
+ bb.Reduce(ImVec2(ImClamp((float)(int)((bb.Max.x - bb.Min.x - 2.0f) * 0.5f), 0.0f, 3.0f), ImClamp((float)(int)((bb.Max.y - bb.Min.y - 2.0f) * 0.5f), 0.0f, 3.0f)));
// V denote the main axis of the scrollbar
float scrollbar_size_v = horizontal ? bb.GetWidth() : bb.GetHeight();
@@ -4063,7 +4120,7 @@ static void Scrollbar(ImGuiWindow* window, bool horizontal)
// Click position in scrollbar normalized space (0.0f->1.0f)
const float clicked_v_norm = ImSaturate((mouse_pos_v - scrollbar_pos_v) / scrollbar_size_v);
- g.HoveredId = id;
+ ImGui::SetHoveredID(id);
bool seek_absolute = false;
if (!previously_held)
@@ -4127,9 +4184,9 @@ void ImGui::FocusWindow(ImGuiWindow* window)
if (g.ActiveId != 0 && g.ActiveIdWindow && g.ActiveIdWindow->RootWindow != window)
ImGui::SetActiveID(0);
- if (g.Windows.back() == window)
+ // Bring to front
+ if ((window->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus) || g.Windows.back() == window)
return;
-
for (int i = 0; i < g.Windows.Size; i++)
if (g.Windows[i] == window)
{
@@ -5085,7 +5142,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
const bool hovered = IsHovered(bb, id, (flags & ImGuiButtonFlags_FlattenChilds) != 0);
if (hovered)
{
- g.HoveredId = id;
+ SetHoveredID(id);
if (allow_key_modifiers || (!g.IO.KeyCtrl && !g.IO.KeyShift && !g.IO.KeyAlt))
{
if (g.IO.MouseClicked[0])
@@ -5799,8 +5856,8 @@ static void DataTypeApplyOpFromText(const char* buf, const char* initial_value_b
}
else if (data_type == ImGuiDataType_Float)
{
- if (!scalar_format)
- scalar_format = "%f";
+ // For floats we have to ignore format with precision (e.g. "%.2f") because sscanf doesn't take them in
+ scalar_format = "%f";
float* v = (float*)data_ptr;
float ref_v = *v;
if (op && sscanf(initial_value_buf, scalar_format, &ref_v) < 1)
@@ -5824,7 +5881,7 @@ bool ImGui::InputScalarAsWidgetReplacement(const ImRect& aabb, const char* label
// Our replacement widget will override the focus ID (registered previously to allow for a TAB focus to happen)
SetActiveID(g.ScalarAsInputTextId, window);
- g.HoveredId = 0;
+ SetHoveredID(0);
FocusableItemUnregister(window);
char buf[32];
@@ -5835,7 +5892,7 @@ bool ImGui::InputScalarAsWidgetReplacement(const ImRect& aabb, const char* label
// First frame
IM_ASSERT(g.ActiveId == id); // InputText ID expected to match the Slider ID (else we'd need to store them both, which is also possible)
g.ScalarAsInputTextId = g.ActiveId;
- g.HoveredId = id;
+ SetHoveredID(id);
}
else if (g.ActiveId != g.ScalarAsInputTextId)
{
@@ -6041,7 +6098,7 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c
const bool hovered = IsHovered(frame_bb, id);
if (hovered)
- g.HoveredId = id;
+ SetHoveredID(id);
if (!display_format)
display_format = "%.3f";
@@ -6100,7 +6157,7 @@ bool ImGui::VSliderFloat(const char* label, const ImVec2& size, float* v, float
const bool hovered = IsHovered(frame_bb, id);
if (hovered)
- g.HoveredId = id;
+ SetHoveredID(id);
if (!display_format)
display_format = "%.3f";
@@ -6341,7 +6398,7 @@ bool ImGui::DragFloat(const char* label, float* v, float v_speed, float v_min, f
const bool hovered = IsHovered(frame_bb, id);
if (hovered)
- g.HoveredId = id;
+ SetHoveredID(id);
if (!display_format)
display_format = "%.3f";
@@ -6565,16 +6622,15 @@ void ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_ge
RenderFrame(frame_bb.Min, frame_bb.Max, window->Color(ImGuiCol_FrameBg), true, style.FrameRounding);
- int res_w = ImMin((int)graph_size.x, values_count);
- if (plot_type == ImGuiPlotType_Lines)
- res_w -= 1;
+ int res_w = ImMin((int)graph_size.x, values_count) + ((plot_type == ImGuiPlotType_Lines) ? -1 : 0);
+ int item_count = values_count + ((plot_type == ImGuiPlotType_Lines) ? -1 : 0);
// Tooltip on hover
int v_hovered = -1;
if (IsHovered(inner_bb, 0))
{
const float t = ImClamp((g.IO.MousePos.x - inner_bb.Min.x) / (inner_bb.Max.x - inner_bb.Min.x), 0.0f, 0.9999f);
- const int v_idx = (int)(t * (values_count + ((plot_type == ImGuiPlotType_Lines) ? -1 : 0)));
+ const int v_idx = (int)(t * item_count);
IM_ASSERT(v_idx >= 0 && v_idx < values_count);
const float v0 = values_getter(data, (v_idx + values_offset) % values_count);
@@ -6590,7 +6646,7 @@ void ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_ge
float v0 = values_getter(data, (0 + values_offset) % values_count);
float t0 = 0.0f;
- ImVec2 p0 = ImVec2( t0, 1.0f - ImSaturate((v0 - scale_min) / (scale_max - scale_min)) );
+ ImVec2 tp0 = ImVec2( t0, 1.0f - ImSaturate((v0 - scale_min) / (scale_max - scale_min)) ); // Point in the normalized space of our target rectangle
const ImU32 col_base = window->Color((plot_type == ImGuiPlotType_Lines) ? ImGuiCol_PlotLines : ImGuiCol_PlotHistogram);
const ImU32 col_hovered = window->Color((plot_type == ImGuiPlotType_Lines) ? ImGuiCol_PlotLinesHovered : ImGuiCol_PlotHistogramHovered);
@@ -6598,19 +6654,27 @@ void ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_ge
for (int n = 0; n < res_w; n++)
{
const float t1 = t0 + t_step;
- const int v_idx = (int)(t0 * values_count);
- IM_ASSERT(v_idx >= 0 && v_idx < values_count);
- const float v1 = values_getter(data, (v_idx + values_offset + 1) % values_count);
- const ImVec2 p1 = ImVec2( t1, 1.0f - ImSaturate((v1 - scale_min) / (scale_max - scale_min)) );
-
- // NB- Draw calls are merged together by the DrawList system.
+ const int v1_idx = (int)(t0 * item_count + 0.5f);
+ IM_ASSERT(v1_idx >= 0 && v1_idx < values_count);
+ const float v1 = values_getter(data, (v1_idx + values_offset + 1) % values_count);
+ const ImVec2 tp1 = ImVec2( t1, 1.0f - ImSaturate((v1 - scale_min) / (scale_max - scale_min)) );
+
+ // NB: Draw calls are merged together by the DrawList system. Still, we should render our batch are lower level to save a bit of CPU.
+ ImVec2 pos0 = ImLerp(inner_bb.Min, inner_bb.Max, tp0);
+ ImVec2 pos1 = ImLerp(inner_bb.Min, inner_bb.Max, (plot_type == ImGuiPlotType_Lines) ? tp1 : ImVec2(tp1.x, 1.0f));
if (plot_type == ImGuiPlotType_Lines)
- window->DrawList->AddLine(ImLerp(inner_bb.Min, inner_bb.Max, p0), ImLerp(inner_bb.Min, inner_bb.Max, p1), v_hovered == v_idx ? col_hovered : col_base);
+ {
+ window->DrawList->AddLine(pos0, pos1, v_hovered == v1_idx ? col_hovered : col_base);
+ }
else if (plot_type == ImGuiPlotType_Histogram)
- window->DrawList->AddRectFilled(ImLerp(inner_bb.Min, inner_bb.Max, p0), ImLerp(inner_bb.Min, inner_bb.Max, ImVec2(p1.x, 1.0f))+ImVec2(-1,0), v_hovered == v_idx ? col_hovered : col_base);
+ {
+ if (pos1.x >= pos0.x + 2.0f)
+ pos1.x -= 1.0f;
+ window->DrawList->AddRectFilled(pos0, pos1, v_hovered == v1_idx ? col_hovered : col_base);
+ }
t0 = t1;
- p0 = p1;
+ tp0 = tp1;
}
// Text overlay
@@ -7079,7 +7143,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
const bool hovered = IsHovered(frame_bb, id);
if (hovered)
{
- g.HoveredId = id;
+ SetHoveredID(id);
g.MouseCursor = ImGuiMouseCursor_TextInput;
}
const bool user_clicked = hovered && io.MouseClicked[0];
@@ -7094,8 +7158,8 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
// Take a copy of the initial buffer value (both in original UTF-8 format and converted to wchar)
// From the moment we focused we are ignoring the content of 'buf'
const int prev_len_w = edit_state.CurLenW;
- edit_state.Text.resize(buf_size); // wchar count <= utf-8 count
- edit_state.InitialText.resize(buf_size); // utf-8
+ edit_state.Text.resize(buf_size+1); // wchar count <= utf-8 count. we use +1 to make sure that .Data isn't NULL so it doesn't crash.
+ edit_state.InitialText.resize(buf_size+1); // utf-8. we use +1 to make sure that .Data isn't NULL so it doesn't crash.
ImFormatString(edit_state.InitialText.Data, edit_state.InitialText.Size, "%s", buf);
const char* buf_end = NULL;
edit_state.CurLenW = ImTextStrFromUtf8(edit_state.Text.Data, edit_state.Text.Size, buf, NULL, &buf_end);
@@ -7117,7 +7181,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
else
{
edit_state.Id = id;
- edit_state.ScrollX = 0.f;
+ edit_state.ScrollX = 0.0f;
stb_textedit_initialize_state(&edit_state.StbState, !is_multiline);
if (!is_multiline && focus_requested_by_code)
select_all = true;
@@ -7147,7 +7211,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
// Although we are active we don't prevent mouse from hovering other elements unless we are interacting right now with the widget.
// Down the line we should have a cleaner concept of focused vs active in the library.
- g.ActiveIdIsFocusedOnly = !io.MouseDown[0];
+ g.ActiveIdAllowHoveringOthers = !io.MouseDown[0];
// Edit in progress
const float mouse_x = (g.IO.MousePos.x - frame_bb.Min.x - style.FramePadding.x) + edit_state.ScrollX;
@@ -7167,6 +7231,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
{
stb_textedit_drag(&edit_state, &edit_state.StbState, mouse_x, mouse_y);
edit_state.CursorAnimReset();
+ edit_state.CursorFollow = true;
}
if (edit_state.SelectedAllMouseLock && !io.MouseDown[0])
edit_state.SelectedAllMouseLock = false;
@@ -7174,7 +7239,8 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
if (g.IO.InputCharacters[0])
{
// Process text input (before we check for Return because using some IME will effectively send a Return?)
- if (!is_ctrl_down && !is_alt_down && is_editable)
+ // We ignore CTRL inputs, but need to allow CTRL+ALT as some keyboards (e.g. German) use AltGR - which is Alt+Ctrl - to input certain characters.
+ if (!(is_ctrl_down && !is_alt_down) && is_editable)
{
for (int n = 0; n < IM_ARRAYSIZE(g.IO.InputCharacters) && g.IO.InputCharacters[n]; n++)
if (unsigned int c = (unsigned int)g.IO.InputCharacters[n])
@@ -7436,9 +7502,9 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
{
const float scroll_increment_x = size.x * 0.25f;
if (cursor_offset.x < edit_state.ScrollX)
- edit_state.ScrollX = ImMax(0.0f, cursor_offset.x - scroll_increment_x);
+ edit_state.ScrollX = (float)(int)ImMax(0.0f, cursor_offset.x - scroll_increment_x);
else if (cursor_offset.x - size.x >= edit_state.ScrollX)
- edit_state.ScrollX = cursor_offset.x - size.x + scroll_increment_x;
+ edit_state.ScrollX = (float)(int)(cursor_offset.x - size.x + scroll_increment_x);
}
else
{
@@ -7619,7 +7685,7 @@ bool ImGui::InputFloat(const char* label, float* v, float step, float step_fast,
if (decimal_precision < 0)
strcpy(display_format, "%f"); // Ideally we'd have a minimum decimal precision of 1 to visually denote that this is a float, while hiding non-significant digits? %f doesn't have a minimum of 1
else
- ImFormatString(display_format, 16, "%%%df", decimal_precision);
+ ImFormatString(display_format, 16, "%%.%df", decimal_precision);
return InputScalarEx(label, ImGuiDataType_Float, (void*)v, (void*)(step>0.0f ? &step : NULL), (void*)(step_fast>0.0f ? &step_fast : NULL), display_format, extra_flags);
}
@@ -7805,7 +7871,7 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi
bool menu_toggled = false;
if (hovered)
{
- g.HoveredId = id;
+ SetHoveredID(id);
if (g.IO.MouseClicked[0])
{
SetActiveID(0);
@@ -8490,7 +8556,10 @@ void ImGui::Dummy(const ImVec2& size)
ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems)
return;
- ItemSize(size);
+
+ const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);
+ ItemSize(bb);
+ ItemAdd(bb, NULL);
}
bool ImGui::IsRectVisible(const ImVec2& size)
diff --git a/3rdparty/bgfx/3rdparty/ocornut-imgui/imgui.h b/3rdparty/bgfx/3rdparty/ocornut-imgui/imgui.h
index 160941d4c6a..7bb0aacc56a 100644
--- a/3rdparty/bgfx/3rdparty/ocornut-imgui/imgui.h
+++ b/3rdparty/bgfx/3rdparty/ocornut-imgui/imgui.h
@@ -22,7 +22,7 @@
// Define assertion handler.
#ifndef IM_ASSERT
#include <assert.h>
-#define IM_ASSERT(_EXPR) assert(_EXPR)
+#define IM_ASSERT(_EXPR, ...) assert(_EXPR)
#endif
// Define attributes of all API symbols declarations, e.g. for DLL under Windows.
@@ -115,11 +115,11 @@ namespace ImGui
IMGUI_API void ShowMetricsWindow(bool* opened = NULL); // metrics window for debugging imgui
// Window
- IMGUI_API bool Begin(const char* name, bool* p_opened = NULL, ImGuiWindowFlags flags = 0); // see .cpp for details. return false when window is collapsed, so you can early out in your code. 'bool* p_opened' creates a widget on the upper-right to close the window (which sets your bool to false).
- IMGUI_API bool Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_use, float bg_alpha = -1.0f, ImGuiWindowFlags flags = 0); // this is the older/longer API. call SetNextWindowSize() instead if you want to set a window size. For regular windows, 'size_on_first_use' only applies to the first time EVER the window is created and probably not what you want! maybe obsolete this API eventually.
+ IMGUI_API bool Begin(const char* name, bool* p_opened = NULL, ImGuiWindowFlags flags = 0); // see .cpp for details. return false when window is collapsed, so you can early out in your code. 'bool* p_opened' creates a widget on the upper-right to close the window (which sets your bool to false).
+ IMGUI_API bool Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_use, float bg_alpha = -1.0f, ImGuiWindowFlags flags = 0); // this is the older/longer API. the extra parameters aren't very relevant. call SetNextWindowSize() instead if you want to set a window size. For regular windows, 'size_on_first_use' only applies to the first time EVER the window is created and probably not what you want! maybe obsolete this API eventually.
IMGUI_API void End();
- IMGUI_API bool BeginChild(const char* str_id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags extra_flags = 0); // begin a scrolling region. size==0.0f: use remaining window size, size<0.0f: use remaining window size minus abs(size). size>0.0f: fixed size. each axis can use a different mode, e.g. ImVec2(0,400).
- IMGUI_API bool BeginChild(ImGuiID id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags extra_flags = 0); // "
+ IMGUI_API bool BeginChild(const char* str_id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags extra_flags = 0); // begin a scrolling region. size==0.0f: use remaining window size, size<0.0f: use remaining window size minus abs(size). size>0.0f: fixed size. each axis can use a different mode, e.g. ImVec2(0,400).
+ IMGUI_API bool BeginChild(ImGuiID id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags extra_flags = 0); // "
IMGUI_API void EndChild();
IMGUI_API ImVec2 GetContentRegionMax(); // current content boundaries (typically window boundaries including scrolling, or current column boundaries), in windows coordinates
IMGUI_API ImVec2 GetContentRegionAvail(); // == GetContentRegionMax() - GetCursorPos()
@@ -386,7 +386,7 @@ namespace ImGui
IMGUI_API ImVec2 CalcTextSize(const char* text, const char* text_end = NULL, bool hide_text_after_double_hash = false, float wrap_width = -1.0f);
IMGUI_API void CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end); // calculate coarse clipping for large list of evenly sized items. Prefer using the ImGuiListClipper higher-level helper if you can.
- IMGUI_API bool BeginChildFrame(ImGuiID id, const ImVec2& size); // helper to create a child window / scrolling region that looks like a normal widget frame
+ IMGUI_API bool BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags extra_flags = 0); // helper to create a child window / scrolling region that looks like a normal widget frame
IMGUI_API void EndChildFrame();
IMGUI_API ImVec4 ColorConvertU32ToFloat4(ImU32 in);
@@ -416,9 +416,11 @@ namespace ImGui
IMGUI_API void CaptureKeyboardFromApp(); // manually enforce imgui setting the io.WantCaptureKeyboard flag next frame (your application needs to handle it). e.g. capture keyboard when your widget is being hovered.
IMGUI_API void CaptureMouseFromApp(); // manually enforce imgui setting the io.WantCaptureMouse flag next frame (your application needs to handle it).
- // Helpers functions to access the MemAllocFn/MemFreeFn pointers in ImGui::GetIO()
+ // Helpers functions to access functions pointers in ImGui::GetIO()
IMGUI_API void* MemAlloc(size_t sz);
IMGUI_API void MemFree(void* ptr);
+ IMGUI_API const char* GetClipboardText();
+ IMGUI_API void SetClipboardText(const char* text);
// Internal state/context access - if you want to use multiple ImGui context, or share context between modules (e.g. DLL), or allocate the memory yourself
IMGUI_API const char* GetVersion();
@@ -458,6 +460,7 @@ enum ImGuiWindowFlags_
ImGuiWindowFlags_MenuBar = 1 << 10, // Has a menu-bar
ImGuiWindowFlags_HorizontalScrollbar = 1 << 11, // Enable horizontal scrollbar (off by default). You need to use SetNextWindowContentSize(ImVec2(width,0.0f)); prior to calling Begin() to specify width. Read code in imgui_demo in the "Horizontal Scrolling" section.
ImGuiWindowFlags_NoFocusOnAppearing = 1 << 12, // Disable taking focus when transitioning from hidden to visible state
+ ImGuiWindowFlags_NoBringToFrontOnFocus = 1 << 13, // Disable bringing window to front when taking focus (e.g. clicking on it or programatically giving it focus)
// [Internal]
ImGuiWindowFlags_ChildWindow = 1 << 20, // Don't use! For internal use by BeginChild()
ImGuiWindowFlags_ChildWindowAutoFitX = 1 << 21, // Don't use! For internal use by BeginChild()
@@ -867,11 +870,11 @@ struct ImGuiTextFilter
int CountGrep;
ImGuiTextFilter(const char* default_filter = "");
- void Clear() { InputBuf[0] = 0; Build(); }
- void Draw(const char* label = "Filter (inc,-exc)", float width = 0.0f); // Helper calling InputText+Build
- bool PassFilter(const char* text, const char* text_end = NULL) const;
- bool IsActive() const { return !Filters.empty(); }
- IMGUI_API void Build();
+ void Clear() { InputBuf[0] = 0; Build(); }
+ bool Draw(const char* label = "Filter (inc,-exc)", float width = 0.0f); // Helper calling InputText+Build
+ bool PassFilter(const char* text, const char* text_end = NULL) const;
+ bool IsActive() const { return !Filters.empty(); }
+ IMGUI_API void Build();
};
// Helper: Text buffer for logging/accumulating text
@@ -886,6 +889,7 @@ struct ImGuiTextBuffer
int size() const { return Buf.Size - 1; }
bool empty() { return Buf.Size >= 2; }
void clear() { Buf.clear(); Buf.push_back(0); }
+ const char* c_str() const { return Buf.Data; }
IMGUI_API void append(const char* fmt, ...) IM_PRINTFARGS(2);
IMGUI_API void appendv(const char* fmt, va_list args);
};
@@ -955,9 +959,9 @@ struct ImGuiTextEditCallbackData
int SelectionEnd; // // Read-write
// NB: calling those function loses selection.
- void DeleteChars(int pos, int bytes_count);
- void InsertChars(int pos, const char* text, const char* text_end = NULL);
- bool HasSelection() const { return SelectionStart != SelectionEnd; }
+ void DeleteChars(int pos, int bytes_count);
+ void InsertChars(int pos, const char* text, const char* text_end = NULL);
+ bool HasSelection() const { return SelectionStart != SelectionEnd; }
};
// ImColor() is just a helper that implicity converts to either ImU32 (packed 4x1 byte) or ImVec4 (4x1 float)
@@ -1111,7 +1115,7 @@ struct ImDrawList
IMGUI_API void AddCircleFilled(const ImVec2& centre, float radius, ImU32 col, int num_segments = 12);
IMGUI_API void AddText(const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL);
IMGUI_API void AddText(const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL, float wrap_width = 0.0f, const ImVec4* cpu_fine_clip_rect = NULL);
- IMGUI_API void AddImage(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv0, const ImVec2& uv1, ImU32 col = 0xFFFFFFFF);
+ IMGUI_API void AddImage(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv0 = ImVec2(0,0), const ImVec2& uv1 = ImVec2(1,1), ImU32 col = 0xFFFFFFFF);
IMGUI_API void AddPolyline(const ImVec2* points, const int num_points, ImU32 col, bool closed, float thickness, bool anti_aliased);
IMGUI_API void AddConvexPolyFilled(const ImVec2* points, const int num_points, ImU32 col, bool anti_aliased);
IMGUI_API void AddBezierCurve(const ImVec2& pos0, const ImVec2& cp0, const ImVec2& cp1, const ImVec2& pos1, ImU32 col, float thickness, int num_segments = 0);
@@ -1160,7 +1164,7 @@ struct ImDrawData
int TotalIdxCount; // For convenience, sum of all cmd_lists idx_buffer.Size
// Functions
- IMGUI_API ImDrawData() { Valid = false; CmdLists = NULL; CmdListsCount = TotalVtxCount = TotalIdxCount = 0; }
+ ImDrawData() { Valid = false; CmdLists = NULL; CmdListsCount = TotalVtxCount = TotalIdxCount = 0; }
IMGUI_API void DeIndexAllBuffers(); // For backward compatibility: convert all buffers from indexed to de-indexed, in case you cannot render indexed. Note: this is slow and most likely a waste of resources. Always prefer indexed rendering!
IMGUI_API void ScaleClipRects(const ImVec2& sc); // Helper to scale the ClipRect field of each ImDrawCmd. Use if your final output buffer is at a different scale than ImGui expects, or if there is a difference between your window resolution and framebuffer resolution.
};
@@ -1216,11 +1220,12 @@ struct ImFontAtlas
// Pitch = Width * BytesPerPixels
IMGUI_API void GetTexDataAsAlpha8(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel = NULL); // 1 byte per-pixel
IMGUI_API void GetTexDataAsRGBA32(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel = NULL); // 4 bytes-per-pixel
- IMGUI_API void SetTexID(void* id) { TexID = id; }
+ void SetTexID(void* id) { TexID = id; }
// Helpers to retrieve list of common Unicode ranges (2 value per range, values are inclusive, zero-terminated list)
// (Those functions could be static but aren't so most users don't have to refer to the ImFontAtlas:: name ever if in their code; just using io.Fonts->)
IMGUI_API const ImWchar* GetGlyphRangesDefault(); // Basic Latin, Extended Latin
+ IMGUI_API const ImWchar* GetGlyphRangesKorean(); // Default + Korean characters
IMGUI_API const ImWchar* GetGlyphRangesJapanese(); // Default + Hiragana, Katakana, Half-Width, Selection of 1946 Ideographs
IMGUI_API const ImWchar* GetGlyphRangesChinese(); // Japanese + full set of about 21000 CJK Unified Ideographs
IMGUI_API const ImWchar* GetGlyphRangesCyrillic(); // Default + about 400 Cyrillic characters
@@ -1267,18 +1272,18 @@ struct ImFont
ImVector<Glyph> Glyphs;
const Glyph* FallbackGlyph; // == FindGlyph(FontFallbackChar)
float FallbackXAdvance; //
- ImVector<float> IndexXAdvance; // Sparse. Glyphs->XAdvance directly indexable (for CalcTextSize functions which are often bottleneck in large UI)
- ImVector<int> IndexLookup; // Sparse. Index glyphs by Unicode code-point
+ ImVector<float> IndexXAdvance; // Sparse. Glyphs->XAdvance directly indexable (more cache-friendly that reading from Glyphs, for CalcTextSize functions which are often bottleneck in large UI)
+ ImVector<int> IndexLookup; // Sparse. Index glyphs by Unicode code-point.
// Methods
IMGUI_API ImFont();
IMGUI_API ~ImFont();
IMGUI_API void Clear();
IMGUI_API void BuildLookupTable();
- IMGUI_API float GetCharAdvance(unsigned short c) const { return ((int)c < IndexXAdvance.Size) ? IndexXAdvance[(int)c] : FallbackXAdvance; }
IMGUI_API const Glyph* FindGlyph(unsigned short c) const;
IMGUI_API void SetFallbackChar(ImWchar c);
- IMGUI_API bool IsLoaded() const { return ContainerAtlas != NULL; }
+ float GetCharAdvance(unsigned short c) const { return ((int)c < IndexXAdvance.Size) ? IndexXAdvance[(int)c] : FallbackXAdvance; }
+ bool IsLoaded() const { return ContainerAtlas != NULL; }
// 'max_width' stops rendering after a certain width (could be turned into a 2d size). FLT_MAX to disable.
// 'wrap_width' enable automatic word-wrapping across multiple lines to fit into given width. 0.0f to disable.
diff --git a/3rdparty/bgfx/3rdparty/ocornut-imgui/imgui_demo.cpp b/3rdparty/bgfx/3rdparty/ocornut-imgui/imgui_demo.cpp
index ba8b8d787a3..d78630ee5a1 100644
--- a/3rdparty/bgfx/3rdparty/ocornut-imgui/imgui_demo.cpp
+++ b/3rdparty/bgfx/3rdparty/ocornut-imgui/imgui_demo.cpp
@@ -13,6 +13,7 @@
#include <ctype.h> // toupper, isprint
#include <math.h> // sqrtf, fabsf, fmodf, powf, cosf, sinf, floorf, ceilf
#include <stdio.h> // vsnprintf, sscanf, printf
+#include <stdint.h> // intptr_t
#ifdef _MSC_VER
#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
@@ -216,7 +217,7 @@ void ImGui::ShowTestWindow(bool* opened)
{
ImFont* font = atlas->Fonts[i];
ImGui::BulletText("Font %d: \'%s\', %.2f px, %d glyphs", i, font->ConfigData ? font->ConfigData[0].Name : "", font->FontSize, font->Glyphs.Size);
- ImGui::TreePush((void*)i);
+ ImGui::TreePush((void*)intptr_t(i));
if (i > 0) { ImGui::SameLine(); if (ImGui::SmallButton("Set as default")) { atlas->Fonts[i] = atlas->Fonts[0]; atlas->Fonts[0] = font; } }
ImGui::PushFont(font);
ImGui::Text("The quick brown fox jumps over the lazy dog");
@@ -254,7 +255,7 @@ void ImGui::ShowTestWindow(bool* opened)
{
for (int i = 0; i < 5; i++)
{
- if (ImGui::TreeNode((void*)i, "Child %d", i))
+ if (ImGui::TreeNode((void*)intptr_t(i), "Child %d", i))
{
ImGui::Text("blah blah");
ImGui::SameLine();
@@ -684,13 +685,29 @@ void ImGui::ShowTestWindow(bool* opened)
phase += 0.10f*values_offset;
}
}
- ImGui::PlotLines("##Graph", values.Data, values.Size, values_offset, "avg 0.0", -1.0f, 1.0f, ImVec2(0,80));
+ ImGui::PlotLines("##Lines", values.Data, values.Size, values_offset, "avg 0.0", -1.0f, 1.0f, ImVec2(0,80));
ImGui::SameLine(0, ImGui::GetStyle().ItemInnerSpacing.x);
ImGui::BeginGroup();
- ImGui::Text("Graph");
+ ImGui::Text("Lines");
ImGui::Checkbox("pause", &pause);
ImGui::EndGroup();
ImGui::PlotHistogram("Histogram", arr, IM_ARRAYSIZE(arr), 0, NULL, 0.0f, 1.0f, ImVec2(0,80));
+
+ // Use functions to generate output
+ // FIXME: This is rather awkward because current plot API only pass in indices. We probably want an API passing floats and user provide sample rate/count.
+ struct Funcs
+ {
+ static float Sin(void*, int i) { return sinf(i * 0.1f); }
+ static float Saw(void*, int i) { return (i & 1) ? 1.0f : 0.0f; }
+ };
+ static int func_type = 0, display_count = 70;
+ ImGui::Separator();
+ ImGui::PushItemWidth(100); ImGui::Combo("func", &func_type, "Sin\0Saw\0"); ImGui::PopItemWidth();
+ ImGui::SameLine();
+ ImGui::SliderInt("Sample count", &display_count, 1, 500);
+ float (*func)(void*, int) = (func_type == 0) ? Funcs::Sin : Funcs::Saw;
+ ImGui::PlotLines("Lines", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0,80));
+ ImGui::PlotHistogram("Histogram", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0,80));
}
if (ImGui::CollapsingHeader("Layout"))
@@ -925,7 +942,7 @@ void ImGui::ShowTestWindow(bool* opened)
if (i > 0) ImGui::SameLine();
ImGui::BeginGroup();
ImGui::Text("%s", i == 0 ? "Top" : i == 1 ? "25%" : i == 2 ? "Center" : i == 3 ? "75%" : "Bottom");
- ImGui::BeginChild(ImGui::GetID((void*)i), ImVec2(ImGui::GetWindowWidth() * 0.17f, 200.0f), true);
+ ImGui::BeginChild(ImGui::GetID((void*)intptr_t(i)), ImVec2(ImGui::GetWindowWidth() * 0.17f, 200.0f), true);
if (scroll_to)
ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + scroll_to_px, i * 0.25f);
for (int line = 0; line < 100; line++)
@@ -950,10 +967,12 @@ void ImGui::ShowTestWindow(bool* opened)
{
ImGui::Bullet(); ImGui::TextWrapped("Horizontal scrolling for a window has to be enabled explicitly via the ImGuiWindowFlags_HorizontalScrollbar flag.");
ImGui::Bullet(); ImGui::TextWrapped("You may want to explicitly specify content width by calling SetNextWindowContentWidth() before Begin().");
+ static int lines = 7;
+ ImGui::SliderInt("Lines", &lines, 1, 15);
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2.0f, 1.0f));
ImGui::BeginChild("scrolling", ImVec2(0, ImGui::GetItemsLineHeightWithSpacing()*7 + 30), true, ImGuiWindowFlags_HorizontalScrollbar);
- for (int line = 0; line < 7; line++)
+ for (int line = 0; line < lines; line++)
{
// Display random stuff
int num_buttons = 10 + ((line & 1) ? line * 9 : line * 3);
@@ -1382,9 +1401,10 @@ void ImGui::ShowTestWindow(bool* opened)
ImGuiIO& io = ImGui::GetIO();
ImGui::Text("MousePos: (%g, %g)", io.MousePos.x, io.MousePos.y);
- ImGui::Text("Mouse down:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (io.MouseDownDuration[i] >= 0.0f) { ImGui::SameLine(); ImGui::Text("%d (%.02f secs)", i, io.MouseDownDuration[i]); }
- ImGui::Text("Mouse clicked:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseClicked(i)) { ImGui::SameLine(); ImGui::Text("%d", i); }
- ImGui::Text("Mouse released:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseReleased(i)) { ImGui::SameLine(); ImGui::Text("%d", i); }
+ ImGui::Text("Mouse down:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (io.MouseDownDuration[i] >= 0.0f) { ImGui::SameLine(); ImGui::Text("b%d (%.02f secs)", i, io.MouseDownDuration[i]); }
+ ImGui::Text("Mouse clicked:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseClicked(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); }
+ ImGui::Text("Mouse dbl-clicked:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseDoubleClicked(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); }
+ ImGui::Text("Mouse released:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseReleased(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); }
ImGui::Text("MouseWheel: %.1f", io.MouseWheel);
ImGui::Text("Keys down:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (io.KeysDownDuration[i] >= 0.0f) { ImGui::SameLine(); ImGui::Text("%d (%.02f secs)", i, io.KeysDownDuration[i]); }
@@ -1462,7 +1482,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
ImGui::SliderFloat2("ItemInnerSpacing", (float*)&style.ItemInnerSpacing, 0.0f, 20.0f, "%.0f");
ImGui::SliderFloat2("TouchExtraPadding", (float*)&style.TouchExtraPadding, 0.0f, 10.0f, "%.0f");
ImGui::SliderFloat("IndentSpacing", &style.IndentSpacing, 0.0f, 30.0f, "%.0f");
- ImGui::SliderFloat("ScrollbarWidth", &style.ScrollbarSize, 1.0f, 20.0f, "%.0f");
+ ImGui::SliderFloat("ScrollbarSize", &style.ScrollbarSize, 1.0f, 20.0f, "%.0f");
ImGui::SliderFloat("ScrollbarRounding", &style.ScrollbarRounding, 0.0f, 16.0f, "%.0f");
ImGui::SliderFloat("GrabMinSize", &style.GrabMinSize, 1.0f, 20.0f, "%.0f");
ImGui::SliderFloat("GrabRounding", &style.GrabRounding, 0.0f, 16.0f, "%.0f");
diff --git a/3rdparty/bgfx/3rdparty/ocornut-imgui/imgui_draw.cpp b/3rdparty/bgfx/3rdparty/ocornut-imgui/imgui_draw.cpp
index 2c053f9cda6..09fcf015430 100644
--- a/3rdparty/bgfx/3rdparty/ocornut-imgui/imgui_draw.cpp
+++ b/3rdparty/bgfx/3rdparty/ocornut-imgui/imgui_draw.cpp
@@ -291,6 +291,7 @@ void ImDrawList::ChannelsMerge()
void ImDrawList::ChannelsSetCurrent(int idx)
{
+ IM_ASSERT(idx < _ChannelsCount);
if (_ChannelsCurrent == idx) return;
memcpy(&_Channels.Data[_ChannelsCurrent].CmdBuffer, &CmdBuffer, sizeof(CmdBuffer)); // copy 12 bytes, four times
memcpy(&_Channels.Data[_ChannelsCurrent].IdxBuffer, &IdxBuffer, sizeof(IdxBuffer));
@@ -713,7 +714,7 @@ void ImDrawList::PathRect(const ImVec2& a, const ImVec2& b, float rounding, int
r = ImMin(r, fabsf(b.x-a.x) * ( ((rounding_corners&(1|2))==(1|2)) || ((rounding_corners&(4|8))==(4|8)) ? 0.5f : 1.0f ) - 1.0f);
r = ImMin(r, fabsf(b.y-a.y) * ( ((rounding_corners&(1|8))==(1|8)) || ((rounding_corners&(2|4))==(2|4)) ? 0.5f : 1.0f ) - 1.0f);
- if (r == 0.0f || rounding_corners == 0)
+ if (r <= 0.0f || rounding_corners == 0)
{
PathLineTo(a);
PathLineTo(ImVec2(b.x,a.y));
@@ -1079,7 +1080,16 @@ static unsigned int stb_decompress_length(unsigned char *input);
static unsigned int stb_decompress(unsigned char *output, unsigned char *i, unsigned int length);
static const char* GetDefaultCompressedFontDataTTFBase85();
static unsigned int Decode85Byte(char c) { return c >= '\\' ? c-36 : c-35; }
-static void Decode85(const unsigned char* src, unsigned int* dst) { for (; *src; src += 5) *dst++ = Decode85Byte(src[0]) + 85*(Decode85Byte(src[1]) + 85*(Decode85Byte(src[2]) + 85*(Decode85Byte(src[3]) + 85*Decode85Byte(src[4])))); }
+static void Decode85(const unsigned char* src, unsigned char* dst)
+{
+ while (*src)
+ {
+ unsigned int tmp = Decode85Byte(src[0]) + 85*(Decode85Byte(src[1]) + 85*(Decode85Byte(src[2]) + 85*(Decode85Byte(src[3]) + 85*Decode85Byte(src[4]))));
+ dst[0] = ((tmp >> 0) & 0xFF); dst[1] = ((tmp >> 8) & 0xFF); dst[2] = ((tmp >> 16) & 0xFF); dst[3] = ((tmp >> 24) & 0xFF); // We can't assume little-endianess.
+ src += 5;
+ dst += 4;
+ }
+}
// Load embedded ProggyClean.ttf at size 13, disable oversampling
ImFont* ImFontAtlas::AddFontDefault(const ImFontConfig* font_cfg_template)
@@ -1146,7 +1156,7 @@ ImFont* ImFontAtlas::AddFontFromMemoryCompressedBase85TTF(const char* compressed
{
int compressed_ttf_size = (((int)strlen(compressed_ttf_data_base85) + 4) / 5) * 4;
void* compressed_ttf = ImGui::MemAlloc(compressed_ttf_size);
- Decode85((const unsigned char*)compressed_ttf_data_base85, (unsigned int*)compressed_ttf);
+ Decode85((const unsigned char*)compressed_ttf_data_base85, (unsigned char*)compressed_ttf);
ImFont* font = AddFontFromMemoryCompressedTTF(compressed_ttf, compressed_ttf_size, size_pixels, font_cfg, glyph_ranges);
ImGui::MemFree(compressed_ttf);
return font;
@@ -1458,6 +1468,18 @@ const ImWchar* ImFontAtlas::GetGlyphRangesDefault()
return &ranges[0];
}
+const ImWchar* ImFontAtlas::GetGlyphRangesKorean()
+{
+ static const ImWchar ranges[] =
+ {
+ 0x0020, 0x00FF, // Basic Latin + Latin Supplement
+ 0x3131, 0x3163, // Korean alphabets
+ 0xAC00, 0xD79D, // Korean characters
+ 0,
+ };
+ return &ranges[0];
+}
+
const ImWchar* ImFontAtlas::GetGlyphRangesChinese()
{
static const ImWchar ranges[] =
diff --git a/3rdparty/bgfx/3rdparty/ocornut-imgui/imgui_internal.h b/3rdparty/bgfx/3rdparty/ocornut-imgui/imgui_internal.h
index 42e18212572..1fac4326916 100644
--- a/3rdparty/bgfx/3rdparty/ocornut-imgui/imgui_internal.h
+++ b/3rdparty/bgfx/3rdparty/ocornut-imgui/imgui_internal.h
@@ -14,6 +14,11 @@
#include <stdio.h> // FILE*
#include <math.h> // sqrtf()
+#ifdef _MSC_VER
+#pragma warning (push)
+#pragma warning (disable: 4251) // class 'xxx' needs to have dll-interface to be used by clients of struct 'xxx' // when IMGUI_API is set to__declspec(dllexport)
+#endif
+
//-----------------------------------------------------------------------------
// Forward Declarations
//-----------------------------------------------------------------------------
@@ -331,6 +336,7 @@ struct ImGuiState
float Time;
int FrameCount;
+ int FrameCountEnded;
int FrameCountRendered;
ImVector<ImGuiWindow*> Windows;
ImVector<ImGuiWindow*> WindowsSortBuffer;
@@ -340,12 +346,13 @@ struct ImGuiState
ImGuiWindow* HoveredWindow; // Will catch mouse inputs
ImGuiWindow* HoveredRootWindow; // Will catch mouse inputs (for focus/move only)
ImGuiID HoveredId; // Hovered widget
+ bool HoveredIdAllowHoveringOthers;
ImGuiID HoveredIdPreviousFrame;
ImGuiID ActiveId; // Active widget
ImGuiID ActiveIdPreviousFrame;
bool ActiveIdIsAlive;
bool ActiveIdIsJustActivated; // Set at the time of activation for one frame
- bool ActiveIdIsFocusedOnly; // Set only by active widget. Denote focus but no active interaction
+ bool ActiveIdAllowHoveringOthers; // Set only by active widget
ImGuiWindow* ActiveIdWindow;
ImGuiWindow* MovedWindow; // Track the child window we clicked on to move a window. Pointer is only valid if ActiveID is the "#MOVE" identifier of a window.
ImVector<ImGuiIniData> Settings; // .ini Settings
@@ -416,18 +423,19 @@ struct ImGuiState
Time = 0.0f;
FrameCount = 0;
- FrameCountRendered = -1;
+ FrameCountEnded = FrameCountRendered = -1;
CurrentWindow = NULL;
FocusedWindow = NULL;
HoveredWindow = NULL;
HoveredRootWindow = NULL;
HoveredId = 0;
+ HoveredIdAllowHoveringOthers = false;
HoveredIdPreviousFrame = 0;
ActiveId = 0;
ActiveIdPreviousFrame = 0;
ActiveIdIsAlive = false;
ActiveIdIsJustActivated = false;
- ActiveIdIsFocusedOnly = false;
+ ActiveIdAllowHoveringOthers = false;
ActiveIdWindow = NULL;
MovedWindow = NULL;
SettingsDirtyTimer = 0.0f;
@@ -473,7 +481,7 @@ struct ImGuiState
// Transient per-window data, reset at the beginning of the frame
// FIXME: That's theory, in practice the delimitation between ImGuiWindow and ImGuiDrawContext is quite tenuous and could be reconsidered.
-struct ImGuiDrawContext
+struct IMGUI_API ImGuiDrawContext
{
ImVec2 CursorPos;
ImVec2 CursorPosPrevLine;
@@ -631,14 +639,21 @@ public:
namespace ImGui
{
- inline ImGuiWindow* GetCurrentWindowRead() { ImGuiState& g = *GImGui; return g.CurrentWindow; } // If this ever crash it means that ImGui::NewFrame() has never been called (which is illegal). We should always have a CurrentWindow in the stack (there is an implicit "Debug" window)
+ // We should always have a CurrentWindow in the stack (there is an implicit "Debug" window)
+ // If this ever crash because g.CurrentWindow is NULL it means that either
+ // - ImGui::NewFrame() has never been called, which is illegal.
+ // - You are calling ImGui functions after ImGui::Render() and before the next ImGui::NewFrame(), which is also illegal.
+ inline ImGuiWindow* GetCurrentWindowRead() { ImGuiState& g = *GImGui; return g.CurrentWindow; }
inline ImGuiWindow* GetCurrentWindow() { ImGuiState& g = *GImGui; g.CurrentWindow->Accessed = true; return g.CurrentWindow; }
IMGUI_API ImGuiWindow* GetParentWindow();
IMGUI_API void FocusWindow(ImGuiWindow* window);
IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window);
+ IMGUI_API void SetHoveredID(ImGuiID id);
IMGUI_API void KeepAliveID(ImGuiID id);
+ IMGUI_API void EndFrame(); // This automatically called by Render()
+
IMGUI_API void ItemSize(const ImVec2& size, float text_offset_y = 0.0f);
IMGUI_API void ItemSize(const ImRect& bb, float text_offset_y = 0.0f);
IMGUI_API bool ItemAdd(const ImRect& bb, const ImGuiID* id);
@@ -683,3 +698,6 @@ namespace ImGui
} // namespace ImGuiP
+#ifdef _MSC_VER
+#pragma warning (pop)
+#endif
diff --git a/3rdparty/bgfx/3rdparty/ocornut-imgui/imgui_wm.cpp b/3rdparty/bgfx/3rdparty/ocornut-imgui/imgui_wm.cpp
new file mode 100644
index 00000000000..2f27fc192d9
--- /dev/null
+++ b/3rdparty/bgfx/3rdparty/ocornut-imgui/imgui_wm.cpp
@@ -0,0 +1,1686 @@
+/*
+ * Copyright 2011-2015 Branimir Karadzic. All rights reserved.
+ * License: http://www.opensource.org/licenses/BSD-2-Clause
+ */
+
+/*
+ * Based on ImWindow code from:
+ * https://github.com/thennequin/ImWindow
+ *
+ * MIT license:
+ * https://github.com/thennequin/ImWindow/blob/master/LICENSE
+ */
+
+#include "imgui_wm.h"
+#include "imgui_internal.h"
+#include <algorithm>
+
+#define IMGUI_NEW(type) new (ImGui::MemAlloc(sizeof(type) ) ) type
+#define IMGUI_DELETE(type, obj) reinterpret_cast<type*>(obj)->~type(), ImGui::MemFree(obj)
+#define IMGUI_DELETE_NULL(type, obj) for (;;) { if (NULL != obj) { IMGUI_DELETE(type, obj); obj = NULL; } break; }
+
+namespace ImGuiWM
+{
+ enum EPlatformWindowAction
+ {
+ E_PLATFORM_WINDOW_ACTION_DESTOY = 1,
+ E_PLATFORM_WINDOW_ACTION_SHOW = 2,
+ E_PLATFORM_WINDOW_ACTION_HIDE = 4,
+ E_PLATFORM_WINDOW_ACTION_SET_POSITION = 8,
+ E_PLATFORM_WINDOW_ACTION_SET_SIZE = 16,
+ };
+
+ static const ImVec2 IM_VEC2_0 = ImVec2(0, 0);
+ static const ImVec2 IM_VEC2_N1 = ImVec2(-1, -1);
+
+ int Id::s_iNextId = 0;
+
+ Id::Id()
+ {
+ m_iId = s_iNextId++;
+ ImFormatString(m_pId, 11, "0x%8X", m_iId);
+ }
+
+ ImU32 Id::GetId() const
+ {
+ return m_iId;
+ }
+
+ const char* Id::GetStr() const
+ {
+ return m_pId;
+ }
+
+ Window::Window()
+ {
+ m_pTitle = NULL;
+ WindowManager::GetInstance()->AddWindow(this);
+ }
+
+ Window::~Window()
+ {
+ WindowManager::GetInstance()->RemoveWindow(this);
+ ImGui::MemFree(m_pTitle);
+ }
+
+ void Window::Destroy()
+ {
+ WindowManager::GetInstance()->DestroyWindow(this);
+ }
+
+ void Window::SetTitle(const char* pTitle)
+ {
+ ImGui::MemFree(m_pTitle);
+ m_pTitle = ImStrdup(pTitle);
+ }
+
+ const char* Window::GetTitle() const
+ {
+ return m_pTitle;
+ }
+
+ const ImVec2& Window::GetLastPosition() const
+ {
+ return m_oLastPosition;
+ }
+
+ const ImVec2& Window::GetLastSize() const
+ {
+ return m_oLastSize;
+ }
+
+ Container::Container(Container* pParent)
+ {
+ IM_ASSERT(NULL != pParent);
+ m_pSplits[0] = NULL;
+ m_pSplits[1] = NULL;
+ m_bVerticalSplit = false;
+ m_iActiveWindow = 0;
+ m_fSplitRatio = 0.5f;
+ m_bIsDrag = false;
+ m_pParent = pParent;
+ m_pParentWindow = (NULL != pParent) ? pParent->m_pParentWindow : NULL;
+ }
+
+ Container::Container(PlatformWindow* pParent)
+ {
+ IM_ASSERT(NULL != pParent);
+ m_pSplits[0] = NULL;
+ m_pSplits[1] = NULL;
+ m_bVerticalSplit = false;
+ m_iActiveWindow = 0;
+ m_fSplitRatio = 0.5f;
+ m_bIsDrag = false;
+ m_pParent = NULL;
+ m_pParentWindow = pParent;
+ }
+
+ Container::~Container()
+ {
+ while (m_lWindows.begin() != m_lWindows.end())
+ {
+ Window* window = *m_lWindows.begin();
+ WindowManager::GetInstance()->RemoveWindow(window);
+ IMGUI_DELETE(Window, window);
+ m_lWindows.erase(m_lWindows.begin());
+ }
+
+ IMGUI_DELETE_NULL(Container, m_pSplits[0]);
+ IMGUI_DELETE_NULL(Container, m_pSplits[1]);
+ }
+
+ void Container::CreateSplits()
+ {
+ m_pSplits[0] = IMGUI_NEW(Container)(this);
+ m_pSplits[1] = IMGUI_NEW(Container)(this);
+ }
+
+ void Container::Dock(Window* pWindow, EDockOrientation eOrientation)
+ {
+ IM_ASSERT(NULL != pWindow);
+
+ if (NULL != pWindow)
+ {
+ IM_ASSERT(eOrientation != E_DOCK_ORIENTATION_CENTER || !IsSplit());
+
+ if (!IsSplit())
+ {
+ if (m_lWindows.size() == 0)
+ {
+ eOrientation = E_DOCK_ORIENTATION_CENTER;
+ }
+
+ switch (eOrientation)
+ {
+ case E_DOCK_ORIENTATION_CENTER:
+ {
+ m_lWindows.push_back(pWindow);
+ m_iActiveWindow = int(m_lWindows.size() - 1);
+ }
+ break;
+ case E_DOCK_ORIENTATION_TOP:
+ {
+ m_bVerticalSplit = true;
+ CreateSplits();
+ m_pSplits[0]->Dock(pWindow);
+ m_pSplits[1]->m_lWindows.insert(m_pSplits[1]->m_lWindows.begin(), m_lWindows.begin(), m_lWindows.end());
+ m_lWindows.clear();
+ m_iActiveWindow = 0;
+ }
+ break;
+ case E_DOCK_ORIENTATION_LEFT:
+ {
+ m_bVerticalSplit = false;
+ CreateSplits();
+ m_pSplits[0]->Dock(pWindow);
+ m_pSplits[1]->m_lWindows.insert(m_pSplits[1]->m_lWindows.begin(), m_lWindows.begin(), m_lWindows.end());
+ m_lWindows.clear();
+ m_iActiveWindow = 0;
+ }
+ break;
+ case E_DOCK_ORIENTATION_RIGHT:
+ {
+ m_bVerticalSplit = false;
+ CreateSplits();
+ m_pSplits[0]->m_lWindows.insert(m_pSplits[0]->m_lWindows.begin(), m_lWindows.begin(), m_lWindows.end());
+ m_pSplits[1]->Dock(pWindow);
+ m_lWindows.clear();
+ m_iActiveWindow = 0;
+ }
+ break;
+ case E_DOCK_ORIENTATION_BOTTOM:
+ {
+ m_bVerticalSplit = true;
+ CreateSplits();
+ m_pSplits[0]->m_lWindows.insert(m_pSplits[0]->m_lWindows.begin(), m_lWindows.begin(), m_lWindows.end());
+ m_pSplits[1]->Dock(pWindow);
+ m_lWindows.clear();
+ m_iActiveWindow = 0;
+ }
+ break;
+ }
+ }
+ else
+ {
+ switch (eOrientation)
+ {
+ case E_DOCK_ORIENTATION_CENTER:
+ IM_ASSERT(false);
+ break;
+ case E_DOCK_ORIENTATION_TOP:
+ {
+ Container* pSplit0 = m_pSplits[0];
+ Container* pSplit1 = m_pSplits[1];
+ CreateSplits();
+ m_pSplits[0]->m_lWindows.push_back(pWindow);
+ m_pSplits[1]->m_bVerticalSplit = m_bVerticalSplit;
+ m_pSplits[1]->m_fSplitRatio = m_fSplitRatio;
+ m_pSplits[1]->m_pSplits[0] = pSplit0;
+ m_pSplits[1]->m_pSplits[1] = pSplit1;
+ m_pSplits[1]->m_pSplits[0]->m_pParent = m_pSplits[1];
+ m_pSplits[1]->m_pSplits[1]->m_pParent = m_pSplits[1];
+ m_fSplitRatio = WindowManager::GetInstance()->GetConfig().m_fDragMarginSizeRatio;
+ m_bVerticalSplit = true;
+ }
+ break;
+ case E_DOCK_ORIENTATION_LEFT:
+ {
+ Container* pSplit0 = m_pSplits[0];
+ Container* pSplit1 = m_pSplits[1];
+ CreateSplits();
+ m_pSplits[0]->m_lWindows.push_back(pWindow);
+ m_pSplits[1]->m_bVerticalSplit = m_bVerticalSplit;
+ m_pSplits[1]->m_fSplitRatio = m_fSplitRatio;
+ m_pSplits[1]->m_pSplits[0] = pSplit0;
+ m_pSplits[1]->m_pSplits[1] = pSplit1;
+ m_pSplits[1]->m_pSplits[0]->m_pParent = m_pSplits[1];
+ m_pSplits[1]->m_pSplits[1]->m_pParent = m_pSplits[1];
+ m_fSplitRatio = WindowManager::GetInstance()->GetConfig().m_fDragMarginSizeRatio;
+ m_bVerticalSplit = false;
+ }
+ break;
+ case E_DOCK_ORIENTATION_RIGHT:
+ {
+ Container* pSplit0 = m_pSplits[0];
+ Container* pSplit1 = m_pSplits[1];
+ CreateSplits();
+ m_pSplits[1]->m_lWindows.push_back(pWindow);
+ m_pSplits[0]->m_bVerticalSplit = m_bVerticalSplit;
+ m_pSplits[0]->m_fSplitRatio = m_fSplitRatio;
+ m_pSplits[0]->m_pSplits[0] = pSplit0;
+ m_pSplits[0]->m_pSplits[1] = pSplit1;
+ m_pSplits[0]->m_pSplits[0]->m_pParent = m_pSplits[0];
+ m_pSplits[0]->m_pSplits[1]->m_pParent = m_pSplits[0];
+ m_fSplitRatio = 1.f - WindowManager::GetInstance()->GetConfig().m_fDragMarginSizeRatio;
+ m_bVerticalSplit = false;
+ }
+ break;
+ case E_DOCK_ORIENTATION_BOTTOM:
+ {
+ Container* pSplit0 = m_pSplits[0];
+ Container* pSplit1 = m_pSplits[1];
+ CreateSplits();
+ m_pSplits[1]->m_lWindows.push_back(pWindow);
+ m_pSplits[0]->m_bVerticalSplit = m_bVerticalSplit;
+ m_pSplits[0]->m_fSplitRatio = m_fSplitRatio;
+ m_pSplits[0]->m_pSplits[0] = pSplit0;
+ m_pSplits[0]->m_pSplits[1] = pSplit1;
+ m_pSplits[0]->m_pSplits[0]->m_pParent = m_pSplits[0];
+ m_pSplits[0]->m_pSplits[1]->m_pParent = m_pSplits[0];
+ m_fSplitRatio = 1.f - WindowManager::GetInstance()->GetConfig().m_fDragMarginSizeRatio;
+ m_bVerticalSplit = true;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ bool Container::UnDock(Window* pWindow)
+ {
+ if (std::find(m_lWindows.begin(), m_lWindows.end(), pWindow) != m_lWindows.end())
+ {
+ m_lWindows.remove(pWindow);
+ if (m_iActiveWindow >= int(m_lWindows.size()))
+ {
+ m_iActiveWindow = int(m_lWindows.size() - 1);
+ }
+ return true;
+ }
+
+ if (NULL != m_pSplits[0] && NULL != m_pSplits[1])
+ {
+ if (m_pSplits[0]->UnDock(pWindow))
+ {
+ if (m_pSplits[0]->IsEmpty())
+ {
+ if (m_pSplits[1]->IsSplit())
+ {
+ Container* pSplit = m_pSplits[1];
+ m_bVerticalSplit = pSplit->m_bVerticalSplit;
+ IMGUI_DELETE_NULL(Container, m_pSplits[0]);
+ m_pSplits[0] = pSplit->m_pSplits[0];
+ m_pSplits[1] = pSplit->m_pSplits[1];
+ pSplit->m_pSplits[0] = NULL;
+ pSplit->m_pSplits[1] = NULL;
+ m_pSplits[0]->m_pParent = this;
+ m_pSplits[1]->m_pParent = this;
+ IMGUI_DELETE_NULL(Container, pSplit);
+ }
+ else
+ {
+ m_lWindows.insert(m_lWindows.end(), m_pSplits[1]->m_lWindows.begin(), m_pSplits[1]->m_lWindows.end());
+ m_pSplits[1]->m_lWindows.clear();
+ m_pSplits[1]->m_iActiveWindow = 0;
+ IMGUI_DELETE_NULL(Container, m_pSplits[0]);
+ IMGUI_DELETE_NULL(Container, m_pSplits[1]);
+ }
+ }
+ return true;
+ }
+
+ if (m_pSplits[1]->UnDock(pWindow))
+ {
+ if (m_pSplits[1]->IsEmpty())
+ {
+ if (m_pSplits[0]->IsSplit())
+ {
+ Container* pSplit = m_pSplits[0];
+ m_bVerticalSplit = pSplit->m_bVerticalSplit;
+ IMGUI_DELETE_NULL(Container, m_pSplits[1]);
+ m_pSplits[0] = pSplit->m_pSplits[0];
+ m_pSplits[1] = pSplit->m_pSplits[1];
+ pSplit->m_pSplits[0] = NULL;
+ pSplit->m_pSplits[1] = NULL;
+ m_pSplits[0]->m_pParent = this;
+ m_pSplits[1]->m_pParent = this;
+ IMGUI_DELETE_NULL(Container, pSplit);
+ }
+ else
+ {
+ m_lWindows.insert(m_lWindows.end(), m_pSplits[0]->m_lWindows.begin(), m_pSplits[0]->m_lWindows.end());
+ m_pSplits[0]->m_lWindows.clear();
+ m_pSplits[0]->m_iActiveWindow = 0;
+ IMGUI_DELETE_NULL(Container, m_pSplits[0]);
+ IMGUI_DELETE_NULL(Container, m_pSplits[1]);
+ }
+ }
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ bool Container::IsEmpty()
+ {
+ //IM_ASSERT(IsSplit() != HasWindowTabbed());
+ return !(IsSplit() || HasWindowTabbed());
+ }
+
+ bool Container::IsSplit()
+ {
+ IM_ASSERT((NULL == m_pSplits[0]) == (NULL == m_pSplits[1]));
+ return (NULL != m_pSplits[0] && NULL != m_pSplits[1]);
+ }
+
+ bool Container::HasWindowTabbed()
+ {
+ return m_lWindows.size() > 0;
+ }
+
+ Container* Container::HasWindow(const Window* pWindow)
+ {
+ if (std::find(m_lWindows.begin(), m_lWindows.end(), pWindow) != m_lWindows.end())
+ {
+ return this;
+ }
+ else
+ {
+ if (NULL != m_pSplits[0])
+ {
+ Container* pContainer = m_pSplits[0]->HasWindow(pWindow);
+ if (NULL != pContainer)
+ {
+ return pContainer;
+ }
+ }
+ if (NULL != m_pSplits[1])
+ {
+ Container* pContainer = m_pSplits[1]->HasWindow(pWindow);
+ if (NULL != pContainer)
+ {
+ return pContainer;
+ }
+ }
+ }
+ return NULL;
+ }
+
+ PlatformWindow* Container::GetPlatformWindowParent() const
+ {
+ return m_pParentWindow;
+ }
+
+ void Container::Paint()
+ {
+ WindowManager* pWindowManager = WindowManager::GetInstance();
+ ImGuiWindow* pWindow = ImGui::GetCurrentWindow();
+ const ImGuiStyle& oStyle = ImGui::GetStyle();
+ ImDrawList* pDrawList = ImGui::GetWindowDrawList();
+
+ const ImVec2 oPos = ImGui::GetWindowPos();
+ const ImVec2 oSize = ImGui::GetWindowSize();
+ const ImVec2 oMin = ImVec2(oPos.x + 1, oPos.y + 1);
+ const ImVec2 oMax = ImVec2(oPos.x + oSize.x - 2, oPos.y + oSize.y - 2);
+
+ m_oLastPosition = oPos;
+ m_oLastSize = oSize;
+
+ const int iSeparatorHalfSize = 2;
+ const int iSeparatorSize = iSeparatorHalfSize * 2;
+
+ if (IsSplit())
+ {
+ if (m_bVerticalSplit)
+ {
+ float iFirstHeight = oSize.y * m_fSplitRatio - iSeparatorHalfSize - pWindow->WindowPadding.x;
+
+ ImGui::BeginChild("Split1", ImVec2(0, iFirstHeight), false, ImGuiWindowFlags_NoScrollbar);
+ m_pSplits[0]->Paint();
+ ImGui::EndChild();
+
+ ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f));
+ ImRect oSeparatorRect(0, iFirstHeight, oSize.x, iFirstHeight + iSeparatorSize);
+ ImGui::Button("", oSeparatorRect.GetSize());
+ if (ImGui::IsItemHovered() || m_bIsDrag)
+ {
+ ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeNS);
+ }
+ ImGui::PopStyleVar(1);
+
+ if (ImGui::IsItemActive())
+ {
+ if (!m_bIsDrag)
+ {
+ m_bIsDrag = true;
+ }
+ m_fSplitRatio += ImGui::GetIO().MouseDelta.y / oSize.y;
+ m_fSplitRatio = ImClamp(m_fSplitRatio, 0.05f, 0.95f);
+
+ }
+ else
+ {
+ m_bIsDrag = false;
+ }
+
+ ImGui::BeginChild("Split2", ImVec2(0, 0), false, ImGuiWindowFlags_NoScrollbar);
+ m_pSplits[1]->Paint(/*iX, iY + iFirstHeight, iWidth, iSecondHeight*/);
+ ImGui::EndChild();
+ }
+ else
+ {
+ float iFirstWidth = oSize.x * m_fSplitRatio - iSeparatorHalfSize - pWindow->WindowPadding.y;
+ ImGui::BeginChild("Split1", ImVec2(iFirstWidth, 0), false, ImGuiWindowFlags_NoScrollbar);
+ m_pSplits[0]->Paint();
+ ImGui::EndChild();
+
+ ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f));
+ ImGui::SameLine();
+
+ ImRect oSeparatorRect(iFirstWidth, 0, iFirstWidth + iSeparatorSize, oSize.y);
+ ImGui::Button("", oSeparatorRect.GetSize());
+
+ if (ImGui::IsItemHovered() || m_bIsDrag)
+ {
+ ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW);
+ }
+ ImGui::PopStyleVar(1);
+
+ if (ImGui::IsItemActive())
+ {
+ if (!m_bIsDrag)
+ {
+ m_bIsDrag = true;
+ }
+
+ m_fSplitRatio += ImGui::GetIO().MouseDelta.x / oSize.x;
+ m_fSplitRatio = ImClamp(m_fSplitRatio, 0.05f, 0.95f);
+ }
+ else
+ {
+ m_bIsDrag = false;
+ }
+
+ ImGui::SameLine();
+
+ ImGui::BeginChild("Split2", ImVec2(0, 0), false, ImGuiWindowFlags_NoScrollbar);
+ m_pSplits[1]->Paint();
+ ImGui::EndChild();
+ }
+ }
+ else if (HasWindowTabbed())
+ {
+ ImGui::InvisibleButton("TabListButton", ImVec2(16, 16));
+ ImGui::SameLine();
+
+ if (ImGui::BeginPopupContextItem("TabListMenu", 0))
+ {
+ int iIndex = 0;
+ for (WindowList::const_iterator itWindow = m_lWindows.begin(); itWindow != m_lWindows.end(); ++itWindow, ++iIndex)
+ {
+ if (ImGui::Selectable((*itWindow)->GetTitle()))
+ {
+ m_iActiveWindow = iIndex;
+ }
+ }
+ ImGui::EndPopup();
+ }
+
+ ImColor oLinesColor = ImColor(160, 160, 160, 255);
+ if (ImGui::IsItemHovered())
+ {
+ oLinesColor = ImColor(255, 255, 255, 255);
+ }
+ ImVec2 oButtonMin = ImGui::GetItemRectMin();
+ ImVec2 oButtonMax = ImGui::GetItemRectMax();
+ ImVec2 oButtonSize = ImVec2(oButtonMax.x - oButtonMin.x, oButtonMax.y - oButtonMin.y);
+ pDrawList->AddLine(
+ ImVec2(oButtonMin.x + 1, oButtonMin.y + oButtonSize.y / 2),
+ ImVec2(oButtonMax.x - 1, oButtonMin.y + oButtonSize.y / 2),
+ oLinesColor);
+
+ pDrawList->AddLine(
+ ImVec2(oButtonMin.x + 1, oButtonMin.y + oButtonSize.y / 2 - 4),
+ ImVec2(oButtonMax.x - 1, oButtonMin.y + oButtonSize.y / 2 - 4),
+ oLinesColor);
+
+ pDrawList->AddLine(
+ ImVec2(oButtonMin.x + 1, oButtonMin.y + oButtonSize.y / 2 + 4),
+ ImVec2(oButtonMax.x - 1, oButtonMin.y + oButtonSize.y / 2 + 4),
+ oLinesColor);
+
+ pDrawList->ChannelsSplit(2);
+
+ //Tabs
+ int iIndex = 0;
+ int iNewActive = m_iActiveWindow;
+ int iSize = int(m_lWindows.size());
+ for (WindowList::iterator it = m_lWindows.begin(); it != m_lWindows.end(); ++it)
+ {
+ const ImVec2 oTextSize = ImGui::CalcTextSize((*it)->GetTitle());
+ ImVec2 oRectSize(oTextSize.x + 15, 25);
+
+ ImGui::PushID(iIndex);
+
+ bool bSelected = iIndex == m_iActiveWindow;
+ if (ImGui::InvisibleButton((*it)->GetId(), oRectSize))
+ {
+ iNewActive = iIndex;
+ }
+ if (iIndex < (iSize - 1))
+ {
+ ImGui::SameLine();
+ }
+
+ if (ImGui::IsItemActive())
+ {
+ if (ImGui::IsMouseDragging())
+ {
+ pWindowManager->StartDragWindow(*it);
+ }
+ }
+
+ ImColor oNormalTab(50, 50, 50, 255); // normal
+ ImColor oSelectedTab(37, 37, 37, 255); // selected
+ ImColor oBorderColor(72, 72, 72, 255); // border
+
+ ImVec2 oRectMin = ImGui::GetItemBoxMin();
+ ImVec2 oRectMax = ImGui::GetItemBoxMax();
+
+ const float fOverlap = 10.f;
+ const float fSlopWidth = 30.f;
+ const float sSlopP1Ratio = 0.6f;
+ const float fSlopP2Ratio = 0.4f;
+ const float fSlopHRatio = 0.f;
+ const float fShadowDropSize = 15.f;
+ const float fShadowSlopRatio = 0.6f;
+ const float fShadowAlpha = 0.75f;
+
+ pDrawList->PathClear();
+ if (bSelected)
+ {
+ pDrawList->ChannelsSetCurrent(1);
+ }
+ else
+ {
+ pDrawList->ChannelsSetCurrent(0);
+ }
+
+ //Drop shadows
+ const ImVec2 uv = GImGui->FontTexUvWhitePixel;
+ pDrawList->PrimReserve(3, 3);
+ pDrawList->PrimWriteIdx((ImDrawIdx)(pDrawList->_VtxCurrentIdx)); pDrawList->PrimWriteIdx((ImDrawIdx)(pDrawList->_VtxCurrentIdx + 1)); pDrawList->PrimWriteIdx((ImDrawIdx)(pDrawList->_VtxCurrentIdx + 2));
+ pDrawList->PrimWriteVtx(ImVec2(oRectMin.x - fOverlap - fShadowDropSize, oRectMax.y), uv, ImColor(0.f, 0.f, 0.f, 0.f));
+ pDrawList->PrimWriteVtx(ImVec2(oRectMin.x - fOverlap + fSlopWidth * fShadowSlopRatio, oRectMin.y), uv, ImColor(0.f, 0.f, 0.f, 0.f));
+ pDrawList->PrimWriteVtx(ImVec2(oRectMin.x - fOverlap + fSlopWidth * fShadowSlopRatio, oRectMax.y), uv, ImColor(0.f, 0.f, 0.f, fShadowAlpha));
+ if (bSelected)
+ {
+ pDrawList->PrimReserve(3, 3);
+ pDrawList->PrimWriteIdx((ImDrawIdx)(pDrawList->_VtxCurrentIdx)); pDrawList->PrimWriteIdx((ImDrawIdx)(pDrawList->_VtxCurrentIdx + 1)); pDrawList->PrimWriteIdx((ImDrawIdx)(pDrawList->_VtxCurrentIdx + 2));
+ pDrawList->PrimWriteVtx(ImVec2(oRectMax.x + fOverlap + fShadowDropSize, oRectMax.y), uv, ImColor(0.f, 0.f, 0.f, 0.f));
+ pDrawList->PrimWriteVtx(ImVec2(oRectMax.x + fOverlap - fSlopWidth * fShadowSlopRatio, oRectMin.y), uv, ImColor(0.f, 0.f, 0.f, 0.f));
+ pDrawList->PrimWriteVtx(ImVec2(oRectMax.x + fOverlap - fSlopWidth * fShadowSlopRatio, oRectMax.y), uv, ImColor(0.f, 0.f, 0.f, fShadowAlpha));
+ }
+
+ // Draw tab and border
+ if (bSelected)
+ {
+ pDrawList->PathLineTo(ImVec2(oMin.x, oRectMax.y));
+ }
+ pDrawList->PathLineTo(ImVec2(oRectMin.x - fOverlap, oRectMax.y));
+ pDrawList->PathBezierCurveTo(
+ ImVec2(oRectMin.x + fSlopWidth * sSlopP1Ratio - fOverlap, oRectMin.y + (oRectMax.y - oRectMin.y) * fSlopHRatio),
+ ImVec2(oRectMin.x + fSlopWidth * fSlopP2Ratio - fOverlap, oRectMin.y),
+ ImVec2(oRectMin.x + fSlopWidth - fOverlap, oRectMin.y)
+ );
+ pDrawList->PathLineTo(ImVec2(oRectMax.x - fSlopWidth + fOverlap, oRectMin.y));
+ pDrawList->PathBezierCurveTo(
+ ImVec2(oRectMax.x - fSlopWidth * fSlopP2Ratio + fOverlap, oRectMin.y),
+ ImVec2(oRectMax.x - fSlopWidth * sSlopP1Ratio + fOverlap, oRectMin.y + (oRectMax.y - oRectMin.y) * fSlopHRatio),
+ ImVec2(oRectMax.x + fOverlap, oRectMax.y)
+ );
+
+ if (bSelected)
+ {
+ pDrawList->AddConvexPolyFilled(pDrawList->_Path.Data + 1, pDrawList->_Path.Size - 1, bSelected ? oSelectedTab : oNormalTab, true);
+ if (oMax.x > (oRectMax.x + fOverlap))
+ {
+ pDrawList->PathLineTo(ImVec2(oMax.x, oRectMax.y));
+ }
+ pDrawList->AddPolyline(pDrawList->_Path.Data, pDrawList->_Path.Size, oBorderColor, false, 1.5f, true);
+ }
+ else
+ {
+ pDrawList->AddConvexPolyFilled(pDrawList->_Path.Data, pDrawList->_Path.Size, bSelected ? oSelectedTab : oNormalTab, true);
+ }
+
+ pDrawList->PathClear();
+
+ ImGui::RenderTextClipped(oRectMin, ImVec2(oRectMax.x, oRectMax.y), (*it)->GetTitle(), NULL, &oTextSize, ImGuiAlign_Center | ImGuiAlign_VCenter);
+
+ if (ImGui::BeginPopupContextItem("TabMenu"))
+ {
+ if (ImGui::Selectable("Close"))
+ {
+ (*it)->Destroy();
+ }
+ if (ImGui::BeginMenu("Dock to"))
+ {
+ int iIndex1 = 0;
+
+ if (pWindowManager->GetMainPlatformWindow()->GetContainer()->IsEmpty())
+ {
+ ImGui::PushID(0);
+ if (ImGui::Selectable("Main")) pWindowManager->Dock((*it));
+ ImGui::PopID();
+ ++iIndex1;
+ }
+ const WindowList& lWindows = pWindowManager->GetWindowList();
+ for (WindowList::const_iterator itWindow = lWindows.begin(); itWindow != lWindows.end(); ++itWindow)
+ {
+ if ((*it) != (*itWindow))
+ {
+ ImGui::PushID(iIndex1);
+ if (ImGui::BeginMenu((*itWindow)->GetTitle()))
+ {
+ bool bHovered = false;
+ PlatformWindow* pPlatformWindow = pWindowManager->GetWindowParent((*itWindow));
+
+ ImVec2 oLastWinPos = (*itWindow)->GetLastPosition();
+ ImVec2 oLastWinSize = (*itWindow)->GetLastSize();
+
+ ImGui::PushID(0);
+ if (ImGui::Selectable("Tab")) pWindowManager->DockWith((*it), (*itWindow), E_DOCK_ORIENTATION_CENTER);
+ if (ImGui::IsItemHovered() && NULL != pPlatformWindow)
+ {
+ bHovered = true;
+ pWindowManager->DrawWindowArea(pPlatformWindow, oLastWinPos, oLastWinSize, ImColor(0.f, 0.5f, 1.f, 0.5f));
+ }
+ ImGui::PopID();
+
+ ImGui::PushID(1);
+ if (ImGui::Selectable("Top")) pWindowManager->DockWith((*it), (*itWindow), E_DOCK_ORIENTATION_TOP);
+ if (ImGui::IsItemHovered() && NULL != pPlatformWindow)
+ {
+ bHovered = true;
+ pWindowManager->DrawWindowArea(pPlatformWindow, oLastWinPos, ImVec2(oLastWinSize.x, oLastWinSize.y / 2.f), ImColor(0.f, 0.5f, 1.f, 0.5f));
+ }
+ ImGui::PopID();
+
+ ImGui::PushID(2);
+ if (ImGui::Selectable("Left")) pWindowManager->DockWith((*it), (*itWindow), E_DOCK_ORIENTATION_LEFT);
+ if (ImGui::IsItemHovered() && NULL != pPlatformWindow)
+ {
+ bHovered = true;
+ pWindowManager->DrawWindowArea(pPlatformWindow, oLastWinPos, ImVec2(oLastWinSize.x / 2.f, oLastWinSize.y), ImColor(0.f, 0.5f, 1.f, 0.5f));
+ }
+ ImGui::PopID();
+
+ ImGui::PushID(3);
+ if (ImGui::Selectable("Right")) pWindowManager->DockWith((*it), (*itWindow), E_DOCK_ORIENTATION_RIGHT);
+ if (ImGui::IsItemHovered() && NULL != pPlatformWindow)
+ {
+ bHovered = true;
+ pWindowManager->DrawWindowArea(pPlatformWindow, ImVec2(oLastWinPos.x + oLastWinSize.x / 2.f, oLastWinPos.y), ImVec2(oLastWinSize.x / 2.f, oLastWinSize.y), ImColor(0.f, 0.5f, 1.f, 0.5f));
+ }
+ ImGui::PopID();
+
+ ImGui::PushID(4);
+ if (ImGui::Selectable("Bottom")) pWindowManager->DockWith((*it), (*itWindow), E_DOCK_ORIENTATION_BOTTOM);
+ if (ImGui::IsItemHovered() && NULL != pPlatformWindow)
+ {
+ bHovered = true;
+ pWindowManager->DrawWindowArea(pPlatformWindow, ImVec2(oLastWinPos.x, oLastWinPos.y + oLastWinSize.y / 2.f), ImVec2(oLastWinSize.x, oLastWinSize.y / 2.f), ImColor(0.f, 0.5f, 1.f, 0.5f));
+ }
+ ImGui::PopID();
+
+ if (!bHovered)
+ {
+ if (NULL != pPlatformWindow)
+ {
+ pWindowManager->DrawWindowArea(pPlatformWindow, oLastWinPos, oLastWinSize, ImColor(0.f, 0.5f, 1.f, 0.5f));
+ }
+ }
+
+ ImGui::EndMenu();
+ }
+ ImGui::PopID();
+ }
+ ++iIndex1;
+ }
+
+ ImGui::EndMenu();
+ }
+ if (ImGui::Selectable("Float"))
+ {
+ pWindowManager->Float((*it));
+ }
+
+ ImGui::EndPopup();
+ }
+
+ ImGui::PopID();
+
+ ++iIndex;
+ }
+ m_iActiveWindow = iNewActive;
+ pDrawList->ChannelsMerge();
+
+ WindowList::iterator itActiveWindow = m_lWindows.begin();
+ std::advance(itActiveWindow, m_iActiveWindow);
+
+ //Draw active
+ IM_ASSERT(itActiveWindow != m_lWindows.end());
+ if (itActiveWindow != m_lWindows.end())
+ {
+ ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, oStyle.WindowPadding);
+ //ImGui::PushStyleColor(ImGuiCol_ChildWindowBg, ImColor(59, 59, 59, 255));
+ ImGui::BeginChild((*itActiveWindow)->GetId(), ImVec2(0, 0), false, ImGuiWindowFlags_HorizontalScrollbar);
+
+
+ ImVec2 oWinPos = ImGui::GetWindowPos();
+ ImVec2 oWinSize = ImGui::GetWindowSize();
+
+ for (WindowList::iterator it = m_lWindows.begin(); it != m_lWindows.end(); ++it)
+ {
+ (*it)->m_oLastPosition = oWinPos;
+ (*it)->m_oLastSize = oWinSize;
+ }
+ (*itActiveWindow)->OnGui();
+
+ ImGui::EndChild();
+ //ImGui::PopStyleColor(1);
+ ImGui::PopStyleVar(1);
+ }
+ }
+ else
+ {
+ // This case can happened only where it's main container
+ IM_ASSERT(m_pParent == NULL);
+ }
+ }
+
+ Container* Container::GetBestDocking(const ImVec2 oCursorPos, EDockOrientation& oOutOrientation, ImVec2& oOutAreaPos, ImVec2& oOutAreaSize)
+ {
+ if (m_pParent == NULL ||
+ (oCursorPos.x >= m_oLastPosition.x && oCursorPos.x <= (m_oLastPosition.x + m_oLastSize.x) &&
+ oCursorPos.y >= m_oLastPosition.y && oCursorPos.y <= (m_oLastPosition.y + m_oLastSize.y)))
+ {
+ if (IsSplit())
+ {
+ Container* pBestContainer = NULL;
+ pBestContainer = m_pSplits[0]->GetBestDocking(oCursorPos, oOutOrientation, oOutAreaPos, oOutAreaSize);
+ if (NULL != pBestContainer)
+ {
+ return pBestContainer;
+ }
+ pBestContainer = m_pSplits[1]->GetBestDocking(oCursorPos, oOutOrientation, oOutAreaPos, oOutAreaSize);
+ if (NULL != pBestContainer)
+ {
+ return pBestContainer;
+ }
+ }
+ else
+ {
+ const float c_fBoxHalfSize = 20.f;
+ const float c_fBoxSize = c_fBoxHalfSize * 2.f;
+ const float c_fMinSize = c_fBoxSize * 4.f;
+ const float c_fSplitRatio = 0.5f;
+ //const float c_fSplitRatio = oConfig.m_fDragMarginSizeRatio;
+ const ImColor oBoxColor(200, 200, 255, 255);
+ const ImColor oBoxHightlightColor(100, 100, 255, 255);
+
+ if (m_oLastSize.x < c_fMinSize && m_oLastSize.y < c_fMinSize)
+ {
+ oOutOrientation = E_DOCK_ORIENTATION_CENTER;
+ oOutAreaPos = m_oLastPosition;
+ oOutAreaSize = m_oLastSize;
+ return this;
+ }
+ else
+ {
+ ImVec2 oCenter = ImVec2(m_oLastPosition.x + m_oLastSize.x / 2.f, m_oLastPosition.y + m_oLastSize.y / 2.f);
+
+ bool bIsInCenter = false;
+ bool bIsInTop = false;
+ bool bIsInLeft = false;
+ bool bIsInRight = false;
+ bool bIsInBottom = false;
+
+ //Center
+ ImRect oRectCenter(ImVec2(oCenter.x - c_fBoxHalfSize, oCenter.y - c_fBoxHalfSize), ImVec2(oCenter.x + c_fBoxHalfSize, oCenter.y + c_fBoxHalfSize));
+ bIsInCenter = oRectCenter.Contains(oCursorPos);
+ WindowManager::GetInstance()->DrawWindowArea(m_pParentWindow, oRectCenter.Min, oRectCenter.GetSize(), bIsInCenter ? oBoxHightlightColor : oBoxColor);
+
+ if (m_oLastSize.y >= c_fMinSize)
+ {
+ //Top
+ ImRect oRectTop(ImVec2(oCenter.x - c_fBoxHalfSize, oCenter.y - c_fBoxHalfSize * 4.f), ImVec2(oCenter.x + c_fBoxHalfSize, oCenter.y - c_fBoxHalfSize * 2.f));
+ bIsInTop = oRectTop.Contains(oCursorPos);
+ WindowManager::GetInstance()->DrawWindowArea(m_pParentWindow, oRectTop.Min, oRectTop.GetSize(), bIsInTop ? oBoxHightlightColor : oBoxColor);
+
+ //Bottom
+ ImRect oRectBottom(ImVec2(oCenter.x - c_fBoxHalfSize, oCenter.y + c_fBoxHalfSize * 2.f), ImVec2(oCenter.x + c_fBoxHalfSize, oCenter.y + c_fBoxHalfSize * 4.f));
+ bIsInBottom = oRectBottom.Contains(oCursorPos);
+ WindowManager::GetInstance()->DrawWindowArea(m_pParentWindow, oRectBottom.Min, oRectBottom.GetSize(), bIsInBottom ? oBoxHightlightColor : oBoxColor);
+ }
+
+ if (m_oLastSize.x >= c_fMinSize)
+ {
+ //Left
+ ImRect oRectLeft(ImVec2(oCenter.x - c_fBoxHalfSize * 4.f, oCenter.y - c_fBoxHalfSize), ImVec2(oCenter.x - c_fBoxHalfSize * 2.f, oCenter.y + c_fBoxHalfSize));
+ bIsInLeft = oRectLeft.Contains(oCursorPos);
+ WindowManager::GetInstance()->DrawWindowArea(m_pParentWindow, oRectLeft.Min, oRectLeft.GetSize(), bIsInLeft ? oBoxHightlightColor : oBoxColor);
+
+ //Right
+ ImRect oRectRight(ImVec2(oCenter.x + c_fBoxHalfSize * 2.f, oCenter.y - c_fBoxHalfSize), ImVec2(oCenter.x + c_fBoxHalfSize * 4.f, oCenter.y + c_fBoxHalfSize));
+ bIsInRight = oRectRight.Contains(oCursorPos);
+ WindowManager::GetInstance()->DrawWindowArea(m_pParentWindow, oRectRight.Min, oRectRight.GetSize(), bIsInRight ? oBoxHightlightColor : oBoxColor);
+ }
+
+ if (bIsInCenter)
+ {
+ oOutOrientation = E_DOCK_ORIENTATION_CENTER;
+ oOutAreaPos = m_oLastPosition;
+ oOutAreaSize = m_oLastSize;
+ return this;
+ }
+ else if (bIsInTop)
+ {
+ oOutOrientation = E_DOCK_ORIENTATION_TOP;
+ oOutAreaPos = m_oLastPosition;
+ oOutAreaSize = ImVec2(m_oLastSize.x, m_oLastSize.y * c_fSplitRatio);
+ return this;
+ }
+ else if (bIsInLeft)
+ {
+ oOutOrientation = E_DOCK_ORIENTATION_LEFT;
+ oOutAreaPos = m_oLastPosition;
+ oOutAreaSize = ImVec2(m_oLastSize.x * c_fSplitRatio, m_oLastSize.y);
+ return this;
+ }
+ else if (bIsInRight)
+ {
+ oOutOrientation = E_DOCK_ORIENTATION_RIGHT;
+ oOutAreaPos = ImVec2(m_oLastPosition.x + m_oLastSize.x * (1.f - c_fSplitRatio), m_oLastPosition.y);
+ oOutAreaSize = ImVec2(m_oLastSize.x * c_fSplitRatio, m_oLastSize.y);
+ return this;
+ }
+ else if (bIsInBottom)
+ {
+ oOutOrientation = E_DOCK_ORIENTATION_BOTTOM;
+ oOutAreaPos = ImVec2(m_oLastPosition.x, m_oLastPosition.y + m_oLastSize.y * (1.f - c_fSplitRatio));
+ oOutAreaSize = ImVec2(m_oLastSize.x, m_oLastSize.y * c_fSplitRatio);
+ return this;
+ }
+ }
+ }
+ }
+
+ return NULL;
+ }
+
+ PlatformWindow::PlatformWindow(bool bMain, bool bIsDragWindow)
+ {
+ m_bMain = bMain;
+ m_bIsDragWindow = bIsDragWindow;
+ m_pContainer = IMGUI_NEW(Container)(this);
+ m_pState = NULL;
+ m_pPreviousState = NULL;
+
+ void* pTemp = ImGui::GetInternalState();
+ m_pState = ImGui::MemAlloc(ImGui::GetInternalStateSize());
+ ImGui::SetInternalState(m_pState, true);
+ ImGui::GetIO().IniFilename = NULL;
+ ImGui::SetInternalState(pTemp);
+ }
+
+ PlatformWindow::~PlatformWindow()
+ {
+ IMGUI_DELETE_NULL(Container, m_pContainer);
+
+ SetState();
+ if (!IsMain())
+ {
+ ImGui::GetIO().Fonts = NULL;
+ }
+ ImGui::Shutdown();
+ RestoreState();
+ ImGui::MemFree(m_pState);
+ }
+
+ void PlatformWindow::OnClose()
+ {
+ WindowManager::GetInstance()->OnClosePlatformWindow(this);
+ }
+
+ static bool s_bStatePush = false;
+
+ bool PlatformWindow::IsStateSet()
+ {
+ return s_bStatePush;
+ }
+
+ void PlatformWindow::SetState()
+ {
+ IM_ASSERT(s_bStatePush == false);
+ s_bStatePush = true;
+ m_pPreviousState = ImGui::GetInternalState();
+ ImGui::SetInternalState(m_pState);
+ memcpy(&((ImGuiState*)m_pState)->Style, &((ImGuiState*)m_pPreviousState)->Style, sizeof(ImGuiStyle));
+ }
+
+ void PlatformWindow::RestoreState()
+ {
+ IM_ASSERT(s_bStatePush == true);
+ s_bStatePush = false;
+ memcpy(&((ImGuiState*)m_pPreviousState)->Style, &((ImGuiState*)m_pState)->Style, sizeof(ImGuiStyle));
+ ImGui::SetInternalState(m_pPreviousState);
+ }
+
+ void PlatformWindow::OnLoseFocus()
+ {
+ ImGuiState& g = *((ImGuiState*)m_pState);
+ g.SetNextWindowPosCond = g.SetNextWindowSizeCond = g.SetNextWindowContentSizeCond = g.SetNextWindowCollapsedCond = g.SetNextWindowFocus = 0;
+ }
+
+ void PlatformWindow::Paint()
+ {
+ WindowManager::GetInstance()->Paint(this);
+ }
+
+ bool PlatformWindow::IsMain()
+ {
+ return m_bMain;
+ }
+
+ void PlatformWindow::Dock(Window* pWindow)
+ {
+ m_pContainer->Dock(pWindow);
+ }
+
+ bool PlatformWindow::UnDock(Window* pWindow)
+ {
+ return m_pContainer->UnDock(pWindow);
+ }
+
+ Container* PlatformWindow::GetContainer()
+ {
+ return m_pContainer;
+ }
+
+ Container* PlatformWindow::HasWindow(Window* pWindow)
+ {
+ return m_pContainer->HasWindow(pWindow);
+ }
+
+ void PlatformWindow::PaintContainer()
+ {
+ m_pContainer->Paint();
+ }
+
+ WindowManager::DrawWindowAreaAction::DrawWindowAreaAction(PlatformWindow* pWindow, const ImVec2& oRectPos, const ImVec2& oRectSize, const ImColor& oColor)
+ : m_oColor(oColor)
+ {
+ m_pWindow = pWindow;
+ m_oRectPos = oRectPos;
+ m_oRectSize = oRectSize;
+ }
+
+ WindowManager* WindowManager::s_pInstance = 0;
+
+ //////////////////////////////////////////////////////////////////////////
+
+ WindowManager::Config::Config()
+ : m_fDragMarginRatio(0.1f)
+ , m_fDragMarginSizeRatio(0.25f)
+ , m_oHightlightAreaColor(0.f, 0.5f, 1.f, 0.5f)
+ {
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+
+ WindowManager::WindowManager()
+ {
+ s_pInstance = this;
+ m_pMainPlatformWindow = NULL;
+ m_pDragPlatformWindow = NULL;
+ m_pCurrentPlatformWindow = NULL;
+ m_pDraggedWindow = NULL;
+ m_oDragPreviewOffset = ImVec2(-20, -10);
+ }
+
+ WindowManager::~WindowManager()
+ {
+ IMGUI_DELETE_NULL(PlatformWindow, m_pMainPlatformWindow);
+ IMGUI_DELETE_NULL(PlatformWindow, m_pDragPlatformWindow);
+ s_pInstance = 0;
+ ImGui::Shutdown();
+ }
+
+ bool WindowManager::Init()
+ {
+ m_pMainPlatformWindow = CreatePlatformWindow(true, NULL, false);
+ if (NULL != m_pMainPlatformWindow)
+ {
+ m_pMainPlatformWindow->Show();
+
+ m_pDragPlatformWindow = CreatePlatformWindow(false, m_pMainPlatformWindow, true);
+ return true;
+ }
+ return false;
+ }
+
+ bool WindowManager::Run()
+ {
+ if (m_pMainPlatformWindow != NULL)
+ {
+ ImGuiIO& io = ImGui::GetIO();
+ m_pMainPlatformWindow->SetSize(io.DisplaySize);
+ }
+ InternalRun();
+ return m_pMainPlatformWindow != NULL;
+ }
+
+ void WindowManager::Exit()
+ {
+ //TODO : Manual exit
+ }
+
+ PlatformWindow* WindowManager::GetMainPlatformWindow()
+ {
+ return m_pMainPlatformWindow;
+ }
+
+ WindowManager::Config& WindowManager::GetConfig()
+ {
+ return m_oConfig;
+ }
+
+ void WindowManager::SetMainTitle(const char* pTitle)
+ {
+ if (NULL != m_pMainPlatformWindow)
+ {
+ m_pMainPlatformWindow->SetTitle(pTitle);
+ }
+ }
+
+ void WindowManager::Dock(Window* pWindow, EDockOrientation eOrientation, PlatformWindow* pToPlatformWindow)
+ {
+ DockAction* pAction = IMGUI_NEW(DockAction);
+ pAction->m_bFloat = false;
+ pAction->m_pWindow = pWindow;
+ pAction->m_pWith = NULL;
+ pAction->m_eOrientation = eOrientation;
+ pAction->m_pToPlatformWindow = (pToPlatformWindow != NULL) ? pToPlatformWindow : m_pMainPlatformWindow;
+ pAction->m_pToContainer = NULL;
+ m_lDockActions.push_back(pAction);
+ }
+
+ void WindowManager::DockTo(Window* pWindow, EDockOrientation eOrientation, Container* pContainer)
+ {
+ IM_ASSERT(NULL != pContainer);
+ if (NULL != pContainer)
+ {
+ DockAction* pAction = IMGUI_NEW(DockAction);
+ pAction->m_bFloat = false;
+ pAction->m_pWindow = pWindow;
+ pAction->m_pWith = NULL;
+ pAction->m_eOrientation = eOrientation;
+ pAction->m_pToPlatformWindow = NULL;
+ pAction->m_pToContainer = pContainer;
+ m_lDockActions.push_back(pAction);
+ }
+ }
+
+ void WindowManager::DockWith(Window* pWindow, Window* pWithWindow, EDockOrientation eOrientation)
+ {
+ DockAction* pAction = IMGUI_NEW(DockAction);
+ pAction->m_bFloat = false;
+ pAction->m_pWindow = pWindow;
+ pAction->m_pWith = pWithWindow;
+ pAction->m_eOrientation = eOrientation;
+ m_lDockActions.push_back(pAction);
+ }
+
+ void WindowManager::Float(Window* pWindow, const ImVec2& oPosition, const ImVec2& oSize)
+ {
+ DockAction* pAction = IMGUI_NEW(DockAction);
+ pAction->m_bFloat = true;
+ pAction->m_pWindow = pWindow;
+ pAction->m_oPosition = oPosition;
+ pAction->m_oSize = oSize;
+ m_lDockActions.push_back(pAction);
+ }
+
+ const WindowList& WindowManager::GetWindowList() const
+ {
+ return m_lWindows;
+ }
+
+ PlatformWindow* WindowManager::GetCurrentPlatformWindow()
+ {
+ return m_pCurrentPlatformWindow;
+ }
+
+ PlatformWindow* WindowManager::GetWindowParent(Window* pWindow)
+ {
+ Container* pContainer = m_pMainPlatformWindow->HasWindow(pWindow);
+ if (NULL != pContainer)
+ {
+ return m_pMainPlatformWindow;
+ }
+
+ for (PlatformWindowList::iterator it = m_lPlatformWindows.begin(); it != m_lPlatformWindows.end(); ++it)
+ {
+ pContainer = (*it)->HasWindow(pWindow);
+ if (NULL != pContainer)
+ {
+ return *it;
+ }
+ }
+ IM_ASSERT(false);
+ return NULL;
+ }
+
+ void WindowManager::Log(const char* pFormat, ...)
+ {
+ char pBuffer[32768];
+ va_list argptr;
+ va_start(argptr, pFormat);
+ ImFormatStringV(pBuffer, sizeof(char) * 32767, pFormat, argptr);
+ va_end(argptr);
+ LogFormatted(pBuffer);
+ }
+
+ void WindowManager::PreUpdate()
+ {
+ if (NULL != m_pMainPlatformWindow)
+ {
+ m_pMainPlatformWindow->PreUpdate();
+ }
+
+ for (PlatformWindowList::iterator it = m_lPlatformWindows.begin(); it != m_lPlatformWindows.end(); ++it)
+ {
+ (*it)->PreUpdate();
+ }
+ }
+
+ void WindowManager::Update()
+ {
+ UpdatePlatformwWindowActions();
+ UpdateDockActions();
+ UpdateOrphans();
+
+ while (m_lToDestroyWindows.begin() != m_lToDestroyWindows.end())
+ {
+ Window* pWindow = *m_lToDestroyWindows.begin();
+
+ m_lToDestroyWindows.remove(pWindow);
+ m_lOrphanWindows.remove(pWindow);
+ m_lWindows.remove(pWindow);
+
+ InternalUnDock(pWindow);
+
+ IMGUI_DELETE(Window, pWindow);
+ }
+
+ while (m_lToDestroyPlatformWindows.begin() != m_lToDestroyPlatformWindows.end())
+ {
+ PlatformWindow* pPlatformWindow = *m_lToDestroyPlatformWindows.begin();
+ m_lToDestroyPlatformWindows.remove(pPlatformWindow);
+ m_lPlatformWindows.remove(pPlatformWindow);
+ IMGUI_DELETE(PlatformWindow, pPlatformWindow);
+ }
+
+ UpdateDragWindow();
+
+ m_pCurrentPlatformWindow = m_pMainPlatformWindow;
+ if (NULL != m_pMainPlatformWindow)
+ {
+ m_pMainPlatformWindow->Paint();
+ }
+
+ for (PlatformWindowList::iterator it = m_lPlatformWindows.begin(); it != m_lPlatformWindows.end(); ++it)
+ {
+ m_pCurrentPlatformWindow = (*it);
+ (*it)->Paint();
+ }
+
+ m_pCurrentPlatformWindow = NULL;
+ }
+
+ void WindowManager::UpdatePlatformwWindowActions()
+ {
+ while (m_lPlatformWindowActions.begin() != m_lPlatformWindowActions.end())
+ {
+ PlatformWindowAction* pAction = *m_lPlatformWindowActions.begin();
+
+ IM_ASSERT((pAction->m_iFlags & E_PLATFORM_WINDOW_ACTION_SHOW & E_PLATFORM_WINDOW_ACTION_HIDE) == 0); // Can't show and hide
+
+ if (pAction->m_iFlags & E_PLATFORM_WINDOW_ACTION_DESTOY)
+ {
+ //pAction->m_pPlatformWindow->Show();
+ //todo destroy
+ bool bFound = false;
+ if (m_pMainPlatformWindow == pAction->m_pPlatformWindow)
+ {
+ while (m_lPlatformWindows.begin() != m_lPlatformWindows.end())
+ {
+ IMGUI_DELETE(PlatformWindow, *m_lPlatformWindows.begin());
+ m_lPlatformWindows.erase(m_lPlatformWindows.begin());
+ }
+ IMGUI_DELETE(PlatformWindow, m_pMainPlatformWindow);
+ m_pMainPlatformWindow = NULL;
+ bFound = true;
+ }
+ else
+ {
+ for (PlatformWindowList::iterator it = m_lPlatformWindows.begin(); it != m_lPlatformWindows.end(); ++it)
+ {
+ if (*it == pAction->m_pPlatformWindow)
+ {
+ IMGUI_DELETE(PlatformWindow, *it);
+ m_lPlatformWindows.erase(it);
+ bFound = true;
+ break;
+ }
+ }
+ }
+
+ if (!bFound)
+ {
+ IM_ASSERT(false, "ImwPlatformWindow not found, maybe already closed");
+ }
+ }
+
+ if (pAction->m_iFlags & E_PLATFORM_WINDOW_ACTION_SHOW)
+ {
+ pAction->m_pPlatformWindow->Show();
+ }
+
+ if (pAction->m_iFlags & E_PLATFORM_WINDOW_ACTION_HIDE)
+ {
+ pAction->m_pPlatformWindow->Hide();
+ }
+
+ if (pAction->m_iFlags & E_PLATFORM_WINDOW_ACTION_SET_POSITION)
+ {
+ pAction->m_pPlatformWindow->SetPosition(pAction->m_oPosition);
+ }
+
+ if (pAction->m_iFlags & E_PLATFORM_WINDOW_ACTION_SET_SIZE)
+ {
+ pAction->m_pPlatformWindow->SetSize(pAction->m_oSize);
+ }
+
+ IMGUI_DELETE(PlatformWindowAction, *m_lPlatformWindowActions.begin());
+ m_lPlatformWindowActions.erase(m_lPlatformWindowActions.begin());
+ }
+ }
+
+ void WindowManager::UpdateDockActions()
+ {
+ while (m_lDockActions.begin() != m_lDockActions.end())
+ {
+ DockAction* pAction = *m_lDockActions.begin();
+
+ InternalUnDock(pAction->m_pWindow);
+
+ if (pAction->m_bFloat)
+ {
+ if (!InternalFloat(pAction->m_pWindow, pAction->m_oPosition, pAction->m_oSize) )
+ {
+ InternalDock(pAction->m_pWindow, E_DOCK_ORIENTATION_LEFT, m_pMainPlatformWindow);
+ }
+ }
+ else
+ {
+ if (NULL != pAction->m_pWith)
+ {
+ InternalDockWith(pAction->m_pWindow, pAction->m_pWith, pAction->m_eOrientation);
+ }
+ else if (NULL != pAction->m_pToContainer)
+ {
+ InternalDockTo(pAction->m_pWindow, pAction->m_eOrientation, pAction->m_pToContainer);
+ }
+ else
+ {
+ InternalDock(pAction->m_pWindow, pAction->m_eOrientation, pAction->m_pToPlatformWindow);
+ }
+ }
+
+ m_lOrphanWindows.remove(pAction->m_pWindow);
+
+ IMGUI_DELETE(PlatformWindowAction, pAction);
+ m_lDockActions.erase(m_lDockActions.begin());
+ }
+ }
+
+ void WindowManager::UpdateOrphans()
+ {
+ while (m_lOrphanWindows.begin() != m_lOrphanWindows.end())
+ {
+ if (m_pMainPlatformWindow->m_pContainer->IsEmpty())
+ {
+ InternalDock(*m_lOrphanWindows.begin(), E_DOCK_ORIENTATION_CENTER, m_pMainPlatformWindow);
+ }
+ else
+ {
+ ImVec2 oSize = ImVec2(300, 300);
+ ImVec2 oPos = m_pMainPlatformWindow->GetPosition();
+ ImVec2 oMainSize = m_pMainPlatformWindow->GetSize();
+ oPos.x += (oMainSize.x - oSize.x) / 2;
+ oPos.y += (oMainSize.y - oSize.y) / 2;
+ InternalFloat(*m_lOrphanWindows.begin(), oPos, oSize);
+ }
+ m_lOrphanWindows.erase(m_lOrphanWindows.begin());
+ }
+ }
+
+ void WindowManager::Paint(PlatformWindow* pWindow)
+ {
+ if (!pWindow->GetContainer()->IsEmpty() )
+ {
+ float fY = 0.f;
+
+ ImGui::SetNextWindowPos(ImVec2(0, fY), ImGuiSetCond_Always);
+ ImGui::SetNextWindowSize(ImVec2(pWindow->GetSize().x, pWindow->GetSize().y - fY), ImGuiSetCond_Always);
+ int iFlags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse;
+
+ if (NULL != m_pDraggedWindow)
+ {
+ iFlags += ImGuiWindowFlags_NoInputs;
+ }
+
+ ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(5.0f, 5.0f));
+
+ char name[64];
+ ImFormatString(name, sizeof(name), "Window %p", pWindow);
+ ImGui::Begin(name, NULL, iFlags);
+ pWindow->PaintBegin();
+ pWindow->PaintContainer();
+ pWindow->PaintEnd();
+ ImGui::End();
+ ImGui::PopStyleVar(1);
+
+ ImGui::Begin("##Overlay", NULL, ImVec2(0, 0), 0.f, ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_AlwaysAutoResize);
+ ImDrawList* pDrawList = ImGui::GetWindowDrawList();
+ for (ImwList<DrawWindowAreaAction>::iterator it = m_lDrawWindowAreas.begin(); it != m_lDrawWindowAreas.end();)
+ {
+ const DrawWindowAreaAction& oAction = *it;
+
+ if (pWindow == oAction.m_pWindow)
+ {
+ ImVec2 oPosA = oAction.m_oRectPos;
+ ImVec2 oPosB = oAction.m_oRectSize;
+ oPosB.x += oPosA.x;
+ oPosB.y += oPosA.y;
+
+ pDrawList->PushClipRectFullScreen();
+ pDrawList->AddRectFilled(oPosA, oPosB, oAction.m_oColor);
+ pDrawList->PopClipRect();
+ ImwList<DrawWindowAreaAction>::iterator toRemove = it;
+ ++it;
+ m_lDrawWindowAreas.erase(toRemove);
+ }
+ else
+ {
+ ++it;
+ }
+ }
+
+ ImGui::End();
+ }
+ }
+
+ static ImVec2 GetCursorPos()
+ {
+ ImGuiIO& io = ImGui::GetIO();
+ return io.MousePos;
+ }
+
+ void WindowManager::StartDragWindow(Window* pWindow)
+ {
+ if (NULL == m_pDraggedWindow)
+ {
+ m_pDraggedWindow = pWindow;
+
+ PlatformWindowAction* pAction = IMGUI_NEW(PlatformWindowAction);
+ pAction->m_pPlatformWindow = m_pDragPlatformWindow;
+ pAction->m_iFlags = E_PLATFORM_WINDOW_ACTION_SHOW | E_PLATFORM_WINDOW_ACTION_SET_POSITION | E_PLATFORM_WINDOW_ACTION_SET_SIZE;
+ ImVec2 oCursorPos = GetCursorPos();
+ pAction->m_oPosition = ImVec2(oCursorPos.x + m_oDragPreviewOffset.x, oCursorPos.y + m_oDragPreviewOffset.y);
+ pAction->m_oSize = ImVec2(pWindow->GetLastSize().x, pWindow->GetLastSize().y);
+ m_lPlatformWindowActions.push_back(pAction);
+
+ Dock(pWindow, E_DOCK_ORIENTATION_CENTER, m_pDragPlatformWindow);
+ ((ImGuiState*)m_pDragPlatformWindow->m_pState)->IO.MouseDown[0] = true;
+ }
+ }
+
+ void WindowManager::StopDragWindow()
+ {
+ PlatformWindowAction* pAction = IMGUI_NEW(PlatformWindowAction);
+ pAction->m_pPlatformWindow = m_pDragPlatformWindow;
+ pAction->m_iFlags = E_PLATFORM_WINDOW_ACTION_HIDE;
+ m_pDragPlatformWindow->Hide();
+ m_lPlatformWindowActions.push_back(pAction);
+ m_pDraggedWindow = NULL;
+ }
+
+ void WindowManager::UpdateDragWindow()
+ {
+ if (NULL != m_pDraggedWindow)
+ {
+ m_pCurrentPlatformWindow = m_pDragPlatformWindow;
+ m_pDragPlatformWindow->Paint();
+ m_pCurrentPlatformWindow = NULL;
+
+ ImVec2 oCursorPos = GetCursorPos();
+ m_pDragPlatformWindow->SetPosition(ImVec2(oCursorPos.x + m_oDragPreviewOffset.x, oCursorPos.y + m_oDragPreviewOffset.y));
+
+ //Search best dock area
+ EDockOrientation eBestDockOrientation;
+ ImVec2 oHightlightPos;
+ ImVec2 oHightlightSize;
+ Container* pBestContainer = GetBestDocking(m_pMainPlatformWindow, oCursorPos, eBestDockOrientation, oHightlightPos, oHightlightSize);
+ if (NULL == pBestContainer)
+ {
+ for (PlatformWindowList::iterator it = m_lPlatformWindows.begin(); it != m_lPlatformWindows.end() && NULL == pBestContainer; ++it)
+ {
+ pBestContainer = GetBestDocking(*it, oCursorPos, eBestDockOrientation, oHightlightPos, oHightlightSize);
+ }
+ }
+ if (pBestContainer)
+ {
+ DrawWindowArea(pBestContainer->GetPlatformWindowParent(), oHightlightPos, oHightlightSize, m_oConfig.m_oHightlightAreaColor);
+ }
+
+ //if (!((ImGuiState*)m_pDragPlatformWindow->m_pState)->IO.MouseDown[0])
+ ImGuiIO& io = ImGui::GetIO();
+ if (!io.MouseDown[0])
+ {
+ if (NULL != pBestContainer)
+ {
+ DockTo(m_pDraggedWindow, eBestDockOrientation, pBestContainer);
+ }
+ else
+ {
+ Float(m_pDraggedWindow, m_pDragPlatformWindow->GetPosition(), m_pDragPlatformWindow->GetSize());
+ }
+
+ StopDragWindow();
+ }
+ }
+ }
+
+ Container* WindowManager::GetBestDocking(PlatformWindow* pPlatformWindow, const ImVec2 oCursorPos, EDockOrientation& oOutOrientation, ImVec2& oOutAreaPos, ImVec2& oOutAreaSize)
+ {
+ ImVec2 oPos = pPlatformWindow->GetPosition();
+ ImVec2 oSize = pPlatformWindow->GetSize();
+ if (oCursorPos.x >= oPos.x && oCursorPos.x <= (oPos.x + oSize.x) &&
+ oCursorPos.y >= oPos.y && oCursorPos.y <= (oPos.y + oSize.y))
+ {
+ ImVec2 oRectPos(oCursorPos.x - oPos.x, oCursorPos.y - oPos.y);
+
+ Container* pBestContainer = pPlatformWindow->GetContainer()->GetBestDocking(oRectPos, oOutOrientation, oOutAreaPos, oOutAreaSize);
+ if (NULL != pBestContainer)
+ {
+ return pBestContainer;
+ }
+
+ //Left
+ if (oRectPos.x <= oSize.x * m_oConfig.m_fDragMarginRatio)
+ {
+ oOutOrientation = E_DOCK_ORIENTATION_LEFT;
+ oOutAreaPos = IM_VEC2_0;
+ oOutAreaSize = ImVec2(oSize.x * m_oConfig.m_fDragMarginSizeRatio, oSize.y);
+ }
+ //Right
+ else if (oRectPos.x >= oSize.x * (1.f - m_oConfig.m_fDragMarginRatio))
+ {
+ oOutOrientation = E_DOCK_ORIENTATION_RIGHT;
+ oOutAreaPos = ImVec2(oSize.x * (1.f - m_oConfig.m_fDragMarginSizeRatio), 0.f);
+ oOutAreaSize = ImVec2(oSize.x * m_oConfig.m_fDragMarginSizeRatio, oSize.y);
+ }
+ //Top
+ else if (oRectPos.y <= oSize.y * m_oConfig.m_fDragMarginRatio)
+ {
+ oOutOrientation = E_DOCK_ORIENTATION_TOP;
+ oOutAreaPos = IM_VEC2_0;
+ oOutAreaSize = ImVec2(oSize.x, oSize.y * m_oConfig.m_fDragMarginSizeRatio);
+ }
+ //Bottom
+ else if (oRectPos.y >= oSize.y * (1.f - m_oConfig.m_fDragMarginRatio))
+ {
+ oOutOrientation = E_DOCK_ORIENTATION_BOTTOM;
+ oOutAreaPos = ImVec2(0.f, oSize.y * (1.f - m_oConfig.m_fDragMarginSizeRatio));
+ oOutAreaSize = ImVec2(oSize.x, oSize.y * m_oConfig.m_fDragMarginSizeRatio);
+ }
+ else
+ {
+ oOutOrientation = E_DOCK_ORIENTATION_CENTER;
+ oOutAreaPos = IM_VEC2_0;
+ oOutAreaSize = ImVec2(oSize.x, oSize.y);
+ //IM_ASSERT(false); //Best dock orientation not found
+ return NULL;
+ }
+ return pPlatformWindow->GetContainer();
+ }
+ return NULL;
+ }
+
+ void WindowManager::AddWindow(Window* pWindow)
+ {
+ m_lWindows.push_back(pWindow);
+
+ m_lOrphanWindows.push_back(pWindow);
+ }
+
+ void WindowManager::RemoveWindow(Window* pWindow)
+ {
+ m_lWindows.remove(pWindow);
+ m_lOrphanWindows.remove(pWindow);
+ }
+
+ void WindowManager::DestroyWindow(Window* pWindow)
+ {
+ if (NULL != pWindow && std::find(m_lToDestroyWindows.begin(), m_lToDestroyWindows.end(), pWindow) == m_lToDestroyWindows.end())
+ {
+ m_lToDestroyWindows.push_back(pWindow);
+ }
+ }
+
+ void WindowManager::InternalDock(Window* pWindow, EDockOrientation eOrientation, PlatformWindow* pToPlatformWindow)
+ {
+ pToPlatformWindow->m_pContainer->Dock(pWindow, eOrientation);
+ }
+
+ void WindowManager::InternalDockTo(Window* pWindow, EDockOrientation eOrientation, Container* pToContainer)
+ {
+ pToContainer->Dock(pWindow, eOrientation);
+ }
+
+ void WindowManager::InternalDockWith(Window* pWindow, Window* pWithWindow, EDockOrientation eOrientation)
+ {
+ Container* pContainer = m_pMainPlatformWindow->HasWindow(pWithWindow);
+ if (NULL != pContainer)
+ {
+ pContainer->Dock(pWindow, eOrientation);
+ }
+
+ for (PlatformWindowList::iterator it = m_lPlatformWindows.begin(); it != m_lPlatformWindows.end(); ++it)
+ {
+ pContainer = (*it)->HasWindow(pWithWindow);
+ if (NULL != pContainer)
+ {
+ pContainer->Dock(pWindow, eOrientation);
+ break;
+ }
+ }
+ }
+
+ bool WindowManager::InternalFloat(Window* pWindow, ImVec2 oPosition, ImVec2 oSize)
+ {
+ PlatformWindow* pPlatformWindow = CreatePlatformWindow(false, m_pMainPlatformWindow, false);
+ if (NULL == pPlatformWindow)
+ {
+ return false;
+ }
+
+ m_lPlatformWindows.push_back(pPlatformWindow);
+
+ if (oSize.x == IM_VEC2_N1.x && oSize.y == IM_VEC2_N1.y)
+ {
+ oSize = pWindow->GetLastSize();
+ }
+
+ if (oPosition.x == IM_VEC2_N1.x && oPosition.y == IM_VEC2_N1.y)
+ {
+ oPosition = GetCursorPos();
+ oPosition.x -= 20;
+ oPosition.x -= 10;
+ }
+ pPlatformWindow->Dock(pWindow);
+ pPlatformWindow->SetSize(oSize);
+ pPlatformWindow->SetPosition(oPosition);
+ pPlatformWindow->Show();
+
+ return true;
+ }
+
+ void WindowManager::InternalUnDock(Window* pWindow)
+ {
+ if (m_pMainPlatformWindow->UnDock(pWindow))
+ {
+ return;
+ }
+
+ for (PlatformWindowList::iterator it = m_lPlatformWindows.begin(); it != m_lPlatformWindows.end(); ++it)
+ {
+ if ((*it)->UnDock(pWindow))
+ {
+ //Destroy empty platform window if not main window
+ if (!(*it)->IsMain() && (*it)->GetContainer()->IsEmpty())
+ {
+ m_lToDestroyPlatformWindows.push_back(*it);
+ }
+ return;
+ }
+ }
+
+ m_pDragPlatformWindow->UnDock(pWindow);
+ }
+
+ void WindowManager::OnClosePlatformWindow(PlatformWindow* pWindow)
+ {
+ PlatformWindowAction* pAction = IMGUI_NEW(PlatformWindowAction);
+ pAction->m_iFlags = E_PLATFORM_WINDOW_ACTION_DESTOY;
+ pAction->m_pPlatformWindow = pWindow;
+ m_lPlatformWindowActions.push_back(pAction);
+ }
+
+ void WindowManager::DrawWindowArea(PlatformWindow* pWindow, const ImVec2& oPos, const ImVec2& oSize, const ImColor& oColor)
+ {
+ m_lDrawWindowAreas.push_back(DrawWindowAreaAction(pWindow, oPos, oSize, oColor));
+ }
+
+ // Static
+ WindowManager* WindowManager::GetInstance()
+ {
+ return s_pInstance;
+ }
+
+} // namespace ImWindow
diff --git a/3rdparty/bgfx/3rdparty/ocornut-imgui/imgui_wm.h b/3rdparty/bgfx/3rdparty/ocornut-imgui/imgui_wm.h
new file mode 100644
index 00000000000..797f4a3f17f
--- /dev/null
+++ b/3rdparty/bgfx/3rdparty/ocornut-imgui/imgui_wm.h
@@ -0,0 +1,310 @@
+/*
+ * Copyright 2011-2015 Branimir Karadzic. All rights reserved.
+ * License: http://www.opensource.org/licenses/BSD-2-Clause
+ */
+
+/*
+ * Based on ImWindow code from:
+ * https://github.com/thennequin/ImWindow
+ *
+ * MIT license:
+ * https://github.com/thennequin/ImWindow/blob/master/LICENSE
+ */
+
+#ifndef IMGUI_WM_H_HEADER_GUARD
+#define IMGUI_WM_H_HEADER_GUARD
+
+#include "imgui.h"
+
+typedef unsigned int ImU32;
+
+#ifndef ImwList
+# include <list>
+# define ImwList std::list
+#endif // ImList
+
+#ifndef ImwMap
+# include <unordered_map>
+# define ImwMap std::unordered_map
+#endif // ImMap
+
+namespace ImGuiWM
+{
+ enum EDockOrientation
+ {
+ E_DOCK_ORIENTATION_CENTER,
+ E_DOCK_ORIENTATION_TOP,
+ E_DOCK_ORIENTATION_LEFT,
+ E_DOCK_ORIENTATION_RIGHT,
+ E_DOCK_ORIENTATION_BOTTOM,
+ };
+
+ class Id
+ {
+ public:
+ Id();
+ ImU32 GetId() const;
+ const char* GetStr() const;
+
+ private:
+ ImU32 m_iId;
+ char m_pId[11];
+ static int s_iNextId;
+ };
+
+ class Window
+ {
+ friend class WindowManager;
+ friend class Container;
+
+ public:
+ virtual void OnGui() = 0;
+ virtual void OnMenu() {};
+
+ const char* GetId() const { return m_oId.GetStr(); }
+
+ void Destroy();
+
+ void SetTitle(const char* pTitle);
+ const char* GetTitle() const;
+
+ const ImVec2& GetLastPosition() const;
+ const ImVec2& GetLastSize() const;
+
+ protected:
+ Window();
+ virtual ~Window();
+
+ char* m_pTitle;
+ Id m_oId;
+
+ ImVec2 m_oLastPosition;
+ ImVec2 m_oLastSize;
+ };
+
+ typedef ImwList<Window*> WindowList;
+
+ class PlatformWindow;
+
+ class Container
+ {
+ friend class PlatformWindow;
+
+ public:
+ void Dock(Window* pWindow,EDockOrientation eOrientation = E_DOCK_ORIENTATION_CENTER);
+ bool UnDock(Window* pWindow);
+
+ bool IsEmpty();
+ bool IsSplit();
+ bool HasWindowTabbed();
+ Container* HasWindow(const Window* pWindow);
+ PlatformWindow* GetPlatformWindowParent() const;
+ Container* GetBestDocking(const ImVec2 oCursorPosInContainer,EDockOrientation& oOutOrientation,ImVec2& oOutAreaPos,ImVec2& oOutAreaSize);
+
+ protected:
+ Container(Container* pParent);
+ Container(PlatformWindow* pParent);
+ ~Container();
+
+ void CreateSplits();
+ void Paint();
+
+ Container* m_pParent;
+ PlatformWindow* m_pParentWindow;
+ WindowList m_lWindows;
+ Container* m_pSplits[2];
+
+ float m_fSplitRatio;
+ bool m_bVerticalSplit;
+ int m_iActiveWindow;
+
+ bool m_bIsDrag;
+
+ ImVec2 m_oLastPosition;
+ ImVec2 m_oLastSize;
+ };
+
+ class PlatformWindow
+ {
+ friend class WindowManager;
+
+ public:
+ PlatformWindow(bool bMainWindow,bool bIsDragWindow);
+ virtual ~PlatformWindow();
+
+ virtual bool Init(PlatformWindow* pParent) = 0;
+
+ virtual const ImVec2& GetPosition() const = 0;
+ virtual const ImVec2& GetSize() const = 0;
+
+ virtual void Show() = 0;
+ virtual void Hide() = 0;
+ virtual void SetSize(const ImVec2& size) = 0;
+ virtual void SetPosition(const ImVec2& pos) = 0;
+ virtual void SetTitle(const char* pTitle) = 0;
+
+ bool IsMain();
+
+ void Dock(Window* pWindow);
+ bool UnDock(Window* pWindow);
+
+ Container* GetContainer();
+ Container* HasWindow(Window* pWindow);
+ bool IsStateSet();
+
+ protected:
+ void SetState();
+ void RestoreState();
+ void OnLoseFocus();
+ virtual void PreUpdate() = 0;
+ virtual void PaintBegin() = 0;
+ virtual void Paint();
+ virtual void PaintEnd() = 0;
+ virtual void Destroy() = 0;
+ virtual void StartDrag() = 0;
+ virtual void StopDrag() = 0;
+ virtual bool IsDraging() = 0;
+
+ void PaintContainer();
+ void OnClose();
+
+ Id m_oId;
+ bool m_bMain;
+ bool m_bIsDragWindow;
+ Container* m_pContainer;
+ void* m_pState;
+ void* m_pPreviousState;
+ };
+
+ typedef ImwList<PlatformWindow*> PlatformWindowList;
+
+ class WindowManager
+ {
+ friend class Window;
+ friend class PlatformWindow;
+ friend class Container;
+
+ struct PlatformWindowAction
+ {
+ PlatformWindow* m_pPlatformWindow;
+ unsigned int m_iFlags;
+ ImVec2 m_oPosition;
+ ImVec2 m_oSize;
+ };
+
+ struct DockAction
+ {
+ Window* m_pWindow;
+
+ // Is Dock or Float
+ bool m_bFloat;
+
+ //For Docking
+ Window* m_pWith;
+ EDockOrientation m_eOrientation;
+ PlatformWindow* m_pToPlatformWindow;
+ Container* m_pToContainer;
+
+ //For Floating
+ ImVec2 m_oPosition;
+ ImVec2 m_oSize;
+ };
+
+ struct DrawWindowAreaAction
+ {
+ DrawWindowAreaAction(PlatformWindow* pWindow,const ImVec2& oRectPos,const ImVec2& oRectSize,const ImColor& oColor);
+ PlatformWindow* m_pWindow;
+ ImVec2 m_oRectPos;
+ ImVec2 m_oRectSize;
+ ImColor m_oColor;
+ };
+
+ public:
+ struct Config
+ {
+ Config();
+ float m_fDragMarginRatio;
+ float m_fDragMarginSizeRatio;
+ ImColor m_oHightlightAreaColor;
+ };
+
+ WindowManager();
+ virtual ~WindowManager();
+
+ bool Init();
+ bool Run();
+ void Exit();
+
+ PlatformWindow* GetMainPlatformWindow();
+ Config& GetConfig();
+
+ void SetMainTitle(const char* pTitle);
+
+ void Dock(Window* pWindow, EDockOrientation eOrientation = E_DOCK_ORIENTATION_CENTER, PlatformWindow* pToPlatformWindow = NULL);
+ void DockTo(Window* pWindow, EDockOrientation eOrientation = E_DOCK_ORIENTATION_CENTER, Container* pContainer = NULL);
+ void DockWith(Window* pWindow, Window* pWithWindow,EDockOrientation eOrientation = E_DOCK_ORIENTATION_CENTER);
+ void Float(Window* pWindow, const ImVec2& oPosition = ImVec2(-1,-1), const ImVec2& oSize = ImVec2(-1,-1));
+
+ const WindowList& GetWindowList() const;
+ PlatformWindow* GetCurrentPlatformWindow();
+ PlatformWindow* GetWindowParent(Window* pWindow);
+
+ void Log(const char* pFormat, ...);
+ virtual void LogFormatted(const char* pStr) = 0;;
+
+ static WindowManager* GetInstance();
+
+ protected:
+ virtual PlatformWindow* CreatePlatformWindow(bool bMain,PlatformWindow* pParent,bool bDragWindow) = 0;
+ virtual void InternalRun() = 0;
+
+ void AddWindow(Window* pWindow);
+ void RemoveWindow(Window* pWindow);
+ void DestroyWindow(Window* pWindow);
+
+ void InternalDock(Window* pWindow,EDockOrientation eOrientation,PlatformWindow* pToPlatformWindow);
+ void InternalDockTo(Window* pWindow,EDockOrientation eOrientation,Container* pToContainer);
+ void InternalDockWith(Window* pWindow,Window* pWithWindow,EDockOrientation eOrientation);
+ bool InternalFloat(Window* pWindow,ImVec2 oPosition,ImVec2 oSize);
+ void InternalUnDock(Window* pWindow);
+ void InternalDrag(Window* pWindow);
+
+ void OnClosePlatformWindow(PlatformWindow* pWindow);
+
+ void DrawWindowArea(PlatformWindow* pWindow,const ImVec2& oPos,const ImVec2& oSize,const ImColor& oColor);
+
+ void PreUpdate();
+ void Update();
+ void UpdatePlatformwWindowActions();
+ void UpdateDockActions();
+ void UpdateOrphans();
+
+ void Paint(PlatformWindow* pWindow);
+
+ void StartDragWindow(Window* pWindow);
+ void StopDragWindow();
+ void UpdateDragWindow();
+ Container* GetBestDocking(PlatformWindow* pPlatformWindow,const ImVec2 oCursorPos,EDockOrientation& oOutOrientation,ImVec2& oOutAreaPos,ImVec2& oOutAreaSize);
+
+ Config m_oConfig;
+ PlatformWindow* m_pMainPlatformWindow;
+ PlatformWindowList m_lPlatformWindows;
+ PlatformWindow* m_pDragPlatformWindow;
+ WindowList m_lWindows;
+ WindowList m_lOrphanWindows;
+ WindowList m_lToDestroyWindows;
+ PlatformWindowList m_lToDestroyPlatformWindows;
+ ImwList<PlatformWindowAction*> m_lPlatformWindowActions;
+ ImwList<DockAction*> m_lDockActions;
+ ImwList<DrawWindowAreaAction> m_lDrawWindowAreas;
+
+ PlatformWindow* m_pCurrentPlatformWindow;
+ Window* m_pDraggedWindow;
+
+ ImVec2 m_oDragPreviewOffset;
+
+ static WindowManager* s_pInstance;
+ };
+}
+
+#endif // IMGUI_WM_H_HEADER_GUARD
diff --git a/3rdparty/bgfx/3rdparty/renderdoc/renderdoc_app.h b/3rdparty/bgfx/3rdparty/renderdoc/renderdoc_app.h
index 77c17848ed4..4666d1e4c5b 100644
--- a/3rdparty/bgfx/3rdparty/renderdoc/renderdoc_app.h
+++ b/3rdparty/bgfx/3rdparty/renderdoc/renderdoc_app.h
@@ -1,7 +1,7 @@
/******************************************************************************
* The MIT License (MIT)
*
- * Copyright (c) 2014 Crytek
+ * Copyright (c) 2015 Baldur Karlsson
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,275 +22,494 @@
* THE SOFTWARE.
******************************************************************************/
-
#pragma once
+#if !defined(RENDERDOC_NO_STDINT)
#include <stdint.h>
-
-#ifdef WIN32
-
-#ifdef RENDERDOC_EXPORTS
-#define RENDERDOC_API __declspec(dllexport)
-#else
-#define RENDERDOC_API __declspec(dllimport)
#endif
-#define RENDERDOC_CC __cdecl
+#if defined(WIN32)
+ #define RENDERDOC_CC __cdecl
#elif defined(__linux__)
-
-#ifdef RENDERDOC_EXPORTS
-#define RENDERDOC_API __attribute__ ((visibility ("default")))
+ #define RENDERDOC_CC
#else
-#define RENDERDOC_API
+ #error "Unknown platform"
#endif
-#define RENDERDOC_CC
-
-#else
-
-#error "Unknown platform"
-
+#ifdef __cplusplus
+extern "C" {
#endif
+
+//////////////////////////////////////////////////////////////////////////////////////////////////
+// RenderDoc capture options
+//
-struct CaptureOptions
+typedef enum
{
- CaptureOptions()
- : AllowVSync(true),
- AllowFullscreen(true),
- DebugDeviceMode(false),
- CaptureCallstacks(false),
- CaptureCallstacksOnlyDraws(false),
- DelayForDebugger(0),
- VerifyMapWrites(false),
- HookIntoChildren(false),
- RefAllResources(false),
- SaveAllInitials(false),
- CaptureAllCmdLists(false)
- {}
-
- // Whether or not to allow the application to enable vsync
+ // Allow the application to enable vsync
+ //
+ // Default - enabled
//
- // 1 - allows the application to enable or disable vsync at will
+ // 1 - The application can enable or disable vsync at will
// 0 - vsync is force disabled
- uint32_t AllowVSync;
+ eRENDERDOC_Option_AllowVSync = 0,
- // Whether or not to allow the application to enable fullscreen
+ // Allow the application to enable fullscreen
+ //
+ // Default - enabled
//
- // 1 - allows the application to enable or disable fullscreen at will
+ // 1 - The application can enable or disable fullscreen at will
// 0 - fullscreen is force disabled
- uint32_t AllowFullscreen;
+ eRENDERDOC_Option_AllowFullscreen = 1,
- // 1 - in-built API debugging features and records the results into the
- // capture logfile, which is matched up with events on replay
- // 0 - no API debugging is enabled
- uint32_t DebugDeviceMode;
-
- // 1 - Captures callstacks for every API event during capture
+ // Record API debugging events and messages
+ //
+ // Default - disabled
+ //
+ // 1 - Enable built-in API debugging features and records the results into
+ // the capture logfile, which is matched up with events on replay
+ // 0 - no API debugging is forcibly enabled
+ eRENDERDOC_Option_DebugDeviceMode = 2,
+
+ // Capture CPU callstacks for API events
+ //
+ // Default - disabled
+ //
+ // 1 - Enables capturing of callstacks
// 0 - no callstacks are captured
- uint32_t CaptureCallstacks;
-
+ eRENDERDOC_Option_CaptureCallstacks = 3,
+
+ // When capturing CPU callstacks, only capture them from drawcalls.
+ // This option does nothing without the above option being enabled
+ //
+ // Default - disabled
+ //
// 1 - Only captures callstacks for drawcall type API events.
// Ignored if CaptureCallstacks is disabled
// 0 - Callstacks, if enabled, are captured for every event.
- uint32_t CaptureCallstacksOnlyDraws;
+ eRENDERDOC_Option_CaptureCallstacksOnlyDraws = 4,
- // Specify a delay in seconds to wait for a debugger to attach after
+ // Specify a delay in seconds to wait for a debugger to attach, after
// creating or injecting into a process, before continuing to allow it to run.
+ //
// 0 indicates no delay, and the process will run immediately after injection
- uint32_t DelayForDebugger;
-
- // 1 - Verify any writes to mapped buffers, to check that they don't overwrite the
- // bounds of the pointer returned.
- // 0 - No verification is performed, and overwriting bounds may cause crashes or
- // corruption in RenderDoc
- uint32_t VerifyMapWrites;
-
- // 1 - Hooks any system API events that create child processes, and injects
- // renderdoc into them recursively with the same options.
+ //
+ // Default - 0 seconds
+ //
+ eRENDERDOC_Option_DelayForDebugger = 5,
+
+ // Verify any writes to mapped buffers, by checking the memory after the
+ // bounds of the returned pointer to detect any modification.
+ //
+ // Default - disabled
+ //
+ // 1 - Verify any writes to mapped buffers
+ // 0 - No verification is performed, and overwriting bounds may cause
+ // crashes or corruption in RenderDoc
+ eRENDERDOC_Option_VerifyMapWrites = 6,
+
+ // Hooks any system API calls that create child processes, and injects
+ // RenderDoc into them recursively with the same options.
+ //
+ // Default - disabled
+ //
+ // 1 - Hooks into spawned child processes
// 0 - Child processes are not hooked by RenderDoc
- uint32_t HookIntoChildren;
+ eRENDERDOC_Option_HookIntoChildren = 7,
- // By default renderdoc only includes resources in the final logfile necessary
- // for that frame, this allows you to override that behaviour
+ // By default RenderDoc only includes resources in the final logfile necessary
+ // for that frame, this allows you to override that behaviour.
+ //
+ // Default - disabled
//
// 1 - all live resources at the time of capture are included in the log
// and available for inspection
// 0 - only the resources referenced by the captured frame are included
- uint32_t RefAllResources;
+ eRENDERDOC_Option_RefAllResources = 8,
- // By default renderdoc skips saving initial states for resources where the
+ // By default RenderDoc skips saving initial states for resources where the
// previous contents don't appear to be used, assuming that writes before
// reads indicate previous contents aren't used.
//
+ // Default - disabled
+ //
// 1 - initial contents at the start of each captured frame are saved, even if
// they are later overwritten or cleared before being used.
// 0 - unless a read is detected, initial contents will not be saved and will
// appear as black or empty data.
- uint32_t SaveAllInitials;
+ eRENDERDOC_Option_SaveAllInitials = 9,
// In APIs that allow for the recording of command lists to be replayed later,
- // renderdoc may choose to not capture command lists before a frame capture is
+ // RenderDoc may choose to not capture command lists before a frame capture is
// triggered, to reduce overheads. This means any command lists recorded once
// and replayed many times will not be available and may cause a failure to
// capture.
//
- // Note this is typically only true for APIs where multithreading is difficult
- // or discouraged. Newer APIs like Vulkan and D3D12 will ignore this option and
- // always capture all command lists since the API is heavily oriented around it,
- // and the overheads have been reduced by API design.
+ // Note this is only true for APIs where multithreading is difficult or
+ // discouraged. Newer APIs like Vulkan and D3D12 will ignore this option
+ // and always capture all command lists since the API is heavily oriented
+ // around it and the overheads have been reduced by API design.
//
// 1 - All command lists are captured from the start of the application
// 0 - Command lists are only captured if their recording begins during
// the period when a frame capture is in progress.
- uint32_t CaptureAllCmdLists;
-};
+ eRENDERDOC_Option_CaptureAllCmdLists = 10,
-enum KeyButton
+ // Mute API debugging output when the debug device mode option is enabled
+ //
+ // Default - enabled
+ //
+ // 1 - Mute any API debug messages from being displayed or passed through
+ // 0 - API debugging is displayed as normal
+ eRENDERDOC_Option_DebugOutputMute = 11,
+
+} RENDERDOC_CaptureOption;
+
+// Sets an option that controls how RenderDoc behaves on capture.
+//
+// Returns 1 if the option and value are valid
+// Returns 0 if either is invalid and the option is unchanged
+typedef int (RENDERDOC_CC *pRENDERDOC_SetCaptureOptionU32)(RENDERDOC_CaptureOption opt, uint32_t val);
+typedef int (RENDERDOC_CC *pRENDERDOC_SetCaptureOptionF32)(RENDERDOC_CaptureOption opt, float val);
+
+// Gets the current value of an option as a uint32_t
+//
+// If the option is invalid, 0xffffffff is returned
+typedef uint32_t (RENDERDOC_CC *pRENDERDOC_GetCaptureOptionU32)(RENDERDOC_CaptureOption opt);
+
+// Gets the current value of an option as a float
+//
+// If the option is invalid, -FLT_MAX is returned
+typedef float (RENDERDOC_CC *pRENDERDOC_GetCaptureOptionF32)(RENDERDOC_CaptureOption opt);
+
+typedef enum
{
- eKey_0 = 0x30, // '0'
- // ...
- eKey_9 = 0x39, // '9'
- eKey_A = 0x41, // 'A'
- // ...
- eKey_Z = 0x5A, // 'Z'
-
- eKey_Divide,
- eKey_Multiply,
- eKey_Subtract,
- eKey_Plus,
-
- eKey_F1,
- eKey_F2,
- eKey_F3,
- eKey_F4,
- eKey_F5,
- eKey_F6,
- eKey_F7,
- eKey_F8,
- eKey_F9,
- eKey_F10,
- eKey_F11,
- eKey_F12,
-
- eKey_Home,
- eKey_End,
- eKey_Insert,
- eKey_Delete,
- eKey_PageUp,
- eKey_PageDn,
-
- eKey_Backspace,
- eKey_Tab,
- eKey_PrtScrn,
- eKey_Pause,
-
- eKey_Max,
-};
-
-enum InAppOverlay
+ // '0' - '9' matches ASCII values
+ eRENDERDOC_Key_0 = 0x30,
+ eRENDERDOC_Key_1 = 0x31,
+ eRENDERDOC_Key_2 = 0x32,
+ eRENDERDOC_Key_3 = 0x33,
+ eRENDERDOC_Key_4 = 0x34,
+ eRENDERDOC_Key_5 = 0x35,
+ eRENDERDOC_Key_6 = 0x36,
+ eRENDERDOC_Key_7 = 0x37,
+ eRENDERDOC_Key_8 = 0x38,
+ eRENDERDOC_Key_9 = 0x39,
+
+ // 'A' - 'Z' matches ASCII values
+ eRENDERDOC_Key_A = 0x41,
+ eRENDERDOC_Key_B = 0x42,
+ eRENDERDOC_Key_C = 0x43,
+ eRENDERDOC_Key_D = 0x44,
+ eRENDERDOC_Key_E = 0x45,
+ eRENDERDOC_Key_F = 0x46,
+ eRENDERDOC_Key_G = 0x47,
+ eRENDERDOC_Key_H = 0x48,
+ eRENDERDOC_Key_I = 0x49,
+ eRENDERDOC_Key_J = 0x4A,
+ eRENDERDOC_Key_K = 0x4B,
+ eRENDERDOC_Key_L = 0x4C,
+ eRENDERDOC_Key_M = 0x4D,
+ eRENDERDOC_Key_N = 0x4E,
+ eRENDERDOC_Key_O = 0x4F,
+ eRENDERDOC_Key_P = 0x50,
+ eRENDERDOC_Key_Q = 0x51,
+ eRENDERDOC_Key_R = 0x52,
+ eRENDERDOC_Key_S = 0x53,
+ eRENDERDOC_Key_T = 0x54,
+ eRENDERDOC_Key_U = 0x55,
+ eRENDERDOC_Key_V = 0x56,
+ eRENDERDOC_Key_W = 0x57,
+ eRENDERDOC_Key_X = 0x58,
+ eRENDERDOC_Key_Y = 0x59,
+ eRENDERDOC_Key_Z = 0x5A,
+
+ // leave the rest of the ASCII range free
+ // in case we want to use it later
+ eRENDERDOC_Key_NonPrintable = 0x100,
+
+ eRENDERDOC_Key_Divide,
+ eRENDERDOC_Key_Multiply,
+ eRENDERDOC_Key_Subtract,
+ eRENDERDOC_Key_Plus,
+
+ eRENDERDOC_Key_F1,
+ eRENDERDOC_Key_F2,
+ eRENDERDOC_Key_F3,
+ eRENDERDOC_Key_F4,
+ eRENDERDOC_Key_F5,
+ eRENDERDOC_Key_F6,
+ eRENDERDOC_Key_F7,
+ eRENDERDOC_Key_F8,
+ eRENDERDOC_Key_F9,
+ eRENDERDOC_Key_F10,
+ eRENDERDOC_Key_F11,
+ eRENDERDOC_Key_F12,
+
+ eRENDERDOC_Key_Home,
+ eRENDERDOC_Key_End,
+ eRENDERDOC_Key_Insert,
+ eRENDERDOC_Key_Delete,
+ eRENDERDOC_Key_PageUp,
+ eRENDERDOC_Key_PageDn,
+
+ eRENDERDOC_Key_Backspace,
+ eRENDERDOC_Key_Tab,
+ eRENDERDOC_Key_PrtScrn,
+ eRENDERDOC_Key_Pause,
+
+ eRENDERDOC_Key_Max,
+} RENDERDOC_InputButton;
+
+// Sets which key or keys can be used to toggle focus between multiple windows
+//
+// If keys is NULL or num is 0, toggle keys will be disabled
+typedef void (RENDERDOC_CC *pRENDERDOC_SetFocusToggleKeys)(RENDERDOC_InputButton *keys, int num);
+
+// Sets which key or keys can be used to capture the next frame
+//
+// If keys is NULL or num is 0, captures keys will be disabled
+typedef void (RENDERDOC_CC *pRENDERDOC_SetCaptureKeys)(RENDERDOC_InputButton *keys, int num);
+
+typedef enum
{
- eOverlay_Enabled = 0x1,
- eOverlay_FrameRate = 0x2,
- eOverlay_FrameNumber = 0x4,
- eOverlay_CaptureList = 0x8,
-
- eOverlay_Default = (eOverlay_Enabled|eOverlay_FrameRate|eOverlay_FrameNumber|eOverlay_CaptureList),
- eOverlay_All = ~0U,
- eOverlay_None = 0,
-};
-
-////////////////////////////////////////////////
-// !!!! IMPORTANT NOTE !!!! //
-// //
-// This API is pretty much experimental and //
-// still in flux. The only thing guaranteed //
-// to remain compatible is a call to //
-// RENDERDOC_GetAPIVersion which must exactly //
-// match the version you expect. //
-// It will be bumped on breaking changes. //
-////////////////////////////////////////////////
-
-// API breaking change history:
-// Version 1 -> 2 - strings changed from wchar_t* to char* (UTF-8)
-// Version 2 -> 3 - StartFrameCapture, EndFrameCapture and SetActiveWindow take
-// 'device' pointer as well as window handles.
-// This is either ID3D11Device* or the GL context (HGLRC/GLXContext)
-// You can still pass NULL to both to capture the default, as long as
-// there's only one device/window pair alive.
-#define RENDERDOC_API_VERSION 3
-
-//////////////////////////////////////////////////////////////////////////
-// In-program functions
-//////////////////////////////////////////////////////////////////////////
-
-extern "C" RENDERDOC_API int RENDERDOC_CC RENDERDOC_GetAPIVersion();
-typedef int (RENDERDOC_CC *pRENDERDOC_GetAPIVersion)();
-
-extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_Shutdown();
-typedef void (RENDERDOC_CC *pRENDERDOC_Shutdown)();
-
-extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_SetLogFile(const char *logfile);
-typedef void (RENDERDOC_CC *pRENDERDOC_SetLogFile)(const char *logfile);
+ // This single bit controls whether the overlay is enabled or disabled globally
+ eRENDERDOC_Overlay_Enabled = 0x1,
-extern "C" RENDERDOC_API const char* RENDERDOC_CC RENDERDOC_GetLogFile();
-typedef const char* (RENDERDOC_CC *pRENDERDOC_GetLogFile)();
+ // Show the average framerate over several seconds as well as min/max
+ eRENDERDOC_Overlay_FrameRate = 0x2,
-extern "C" RENDERDOC_API uint32_t RENDERDOC_CC RENDERDOC_GetNumCaptures();
-typedef uint32_t (RENDERDOC_CC *pRENDERDOC_GetNumCaptures)();
-
-extern "C" RENDERDOC_API uint32_t RENDERDOC_CC RENDERDOC_GetCapture(uint32_t idx, char *logfile, uint32_t *pathlength, uint64_t *timestamp);
-typedef uint32_t (RENDERDOC_CC *pRENDERDOC_GetCapture)(uint32_t idx, char *logfile, uint32_t *pathlength, uint64_t *timestamp);
+ // Show the current frame number
+ eRENDERDOC_Overlay_FrameNumber = 0x4,
-extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_SetCaptureOptions(const CaptureOptions *opts);
-typedef void (RENDERDOC_CC *pRENDERDOC_SetCaptureOptions)(const CaptureOptions *opts);
-
-extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_TriggerCapture();
-typedef void (RENDERDOC_CC *pRENDERDOC_TriggerCapture)();
+ // Show a list of recent captures, and how many captures have been made
+ eRENDERDOC_Overlay_CaptureList = 0x8,
-// In the below functions 'device pointer' corresponds to the API specific handle, e.g.
-// ID3D11Device, or the GL context pointer.
-// The 'window handle' is the OS's native window handle (HWND or GLXDrawable).
-
-// This must match precisely to a pair, and it sets the RenderDoc in-app overlay to select that
-// window as 'active' and respond to keypresses.
-extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_SetActiveWindow(void *device, void *wndHandle);
-typedef void (RENDERDOC_CC *pRENDERDOC_SetActiveWindow)(void *device, void *wndHandle);
-
-// Either parameter can be NULL to wild-card match, such that you can capture from any
-// device to a particular window, or a particular device to any window.
-// In either case, if there are two or more possible matching (device,window) pairs it
-// is undefined which one will be captured.
-// You can pass (NULL, NULL) if you know you only have one device and one window, and
-// it will match. Likewise if you have not created a window at all (only off-screen
-// rendering), then NULL window pointer will capture, whether you pass a NULL device
-// or specify a device among multiple.
+ // Default values for the overlay mask
+ eRENDERDOC_Overlay_Default =
+ (eRENDERDOC_Overlay_Enabled|
+ eRENDERDOC_Overlay_FrameRate|
+ eRENDERDOC_Overlay_FrameNumber|
+ eRENDERDOC_Overlay_CaptureList),
-extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_StartFrameCapture(void *device, void *wndHandle);
-typedef void (RENDERDOC_CC *pRENDERDOC_StartFrameCapture)(void *device, void *wndHandle);
+ // Enable all bits
+ eRENDERDOC_Overlay_All = ~0U,
-extern "C" RENDERDOC_API uint32_t RENDERDOC_CC RENDERDOC_EndFrameCapture(void *device, void *wndHandle);
-typedef uint32_t (RENDERDOC_CC *pRENDERDOC_EndFrameCapture)(void *device, void *wndHandle);
+ // Disable all bits
+ eRENDERDOC_Overlay_None = 0,
+} RENDERDOC_OverlayBits;
-extern "C" RENDERDOC_API uint32_t RENDERDOC_CC RENDERDOC_GetOverlayBits();
+// returns the overlay bits that have been set
typedef uint32_t (RENDERDOC_CC *pRENDERDOC_GetOverlayBits)();
-
-extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_MaskOverlayBits(uint32_t And, uint32_t Or);
+// sets the overlay bits with an and & or mask
typedef void (RENDERDOC_CC *pRENDERDOC_MaskOverlayBits)(uint32_t And, uint32_t Or);
-extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_SetFocusToggleKeys(KeyButton *keys, int num);
-typedef void (RENDERDOC_CC *pRENDERDOC_SetFocusToggleKeys)(KeyButton *keys, int num);
+// this function will attempt to shut down RenderDoc.
+//
+// Note: that this will only work correctly if done immediately after
+// the dll is loaded, before any API work happens. RenderDoc will remove its
+// injected hooks and shut down. Behaviour is undefined if this is called
+// after any API functions have been called.
+typedef void (RENDERDOC_CC *pRENDERDOC_Shutdown)();
-extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_SetCaptureKeys(KeyButton *keys, int num);
-typedef void (RENDERDOC_CC *pRENDERDOC_SetCaptureKeys)(KeyButton *keys, int num);
+// This function will unload RenderDoc's crash handler.
+//
+// If you use your own crash handler and don't want RenderDoc's handler to
+// intercede, you can call this function to unload it and any unhandled
+// exceptions will pass to the next handler.
+typedef void (RENDERDOC_CC *pRENDERDOC_UnloadCrashHandler)();
-extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_InitRemoteAccess(uint32_t *ident);
-typedef void (RENDERDOC_CC *pRENDERDOC_InitRemoteAccess)(uint32_t *ident);
+// Sets the logfile path template
+//
+// logfile is a UTF-8 string that gives a template for how captures will be named
+// and where they will be saved.
+//
+// Any extension is stripped off the path, and captures are saved in the directory
+// specified, and named with the filename and the frame number appended. If the
+// directory does not exist it will be created, including any parent directories.
+//
+// If pathtemplate is NULL, the template will remain unchanged
+//
+// Example:
+//
+// SetLogFilePathTemplate("my_captures/example");
+//
+// Capture #1 -> my_captures/example_frame123.rdc
+// Capture #2 -> my_captures/example_frame456.rdc
+typedef void (RENDERDOC_CC *pRENDERDOC_SetLogFilePathTemplate)(const char *pathtemplate);
+
+// returns the current logfile template, see SetLogFileTemplate above, as a UTF-8 string
+typedef const char* (RENDERDOC_CC *pRENDERDOC_GetLogFilePathTemplate)();
+
+// returns the number of captures that have been made
+typedef uint32_t (RENDERDOC_CC *pRENDERDOC_GetNumCaptures)();
-extern "C" RENDERDOC_API uint32_t RENDERDOC_CC RENDERDOC_IsRemoteAccessConnected();
+// This function returns the details of a capture, by index. New captures are added
+// to the end of the list.
+//
+// logfile will be filled with the absolute path to the capture file, as a UTF-8 string
+// pathlength will be written with the length in bytes of the logfile string
+// timestamp will be written with the time of the capture, in seconds since the Unix epoch
+//
+// Any of the parameters can be NULL and they'll be skipped.
+//
+// The function will return 1 if the capture index is valid, or 0 if the index is invalid
+// If the index is invalid, the values will be unchanged
+//
+// Note: when captures are deleted in the UI they will remain in this list, so the
+// logfile path may not exist anymore.
+typedef uint32_t (RENDERDOC_CC *pRENDERDOC_GetCapture)(uint32_t idx, char *logfile, uint32_t *pathlength, uint64_t *timestamp);
+
+// capture the next frame on whichever window and API is currently considered active
+typedef void (RENDERDOC_CC *pRENDERDOC_TriggerCapture)();
+
+// returns 1 if the RenderDoc UI is connected to this application, 0 otherwise
typedef uint32_t (RENDERDOC_CC *pRENDERDOC_IsRemoteAccessConnected)();
-extern "C" RENDERDOC_API uint32_t RENDERDOC_CC RENDERDOC_LaunchReplayUI(uint32_t connectRemoteAccess, const char *cmdline);
+// This function will launch the Replay UI associated with the RenderDoc library injected
+// into the running application.
+//
+// if connectRemoteAccess is 1, the Replay UI will be launched with a command line parameter
+// to connect to this application
+// cmdline is the rest of the command line, as a UTF-8 string. E.g. a captures to open
+// if cmdline is NULL, the command line will be empty.
+//
+// returns the PID of the replay UI if successful, 0 if not successful.
typedef uint32_t (RENDERDOC_CC *pRENDERDOC_LaunchReplayUI)(uint32_t connectRemoteAccess, const char *cmdline);
-extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_UnloadCrashHandler();
-typedef void (RENDERDOC_CC *pRENDERDOC_UnloadCrashHandler)();
+// RenderDoc can return a higher version than requested if it's backwards compatible,
+// this function returns the actual version returned. If a parameter is NULL, it will be
+// ignored and the others will be filled out.
+typedef void (RENDERDOC_CC *pRENDERDOC_GetAPIVersion)(int *major, int *minor, int *patch);
+
+//////////////////////////////////////////////////////////////////////////
+// Capturing functions
+//
+
+// A device pointer is a pointer to the API's root handle.
+//
+// This would be an ID3D11Device, HGLRC/GLXContext, ID3D12Device, etc
+typedef void* RENDERDOC_DevicePointer;
+
+// A window handle is the OS's native window handle
+//
+// This would be an HWND, GLXDrawable, etc
+typedef void* RENDERDOC_WindowHandle;
+
+// This sets the RenderDoc in-app overlay in the API/window pair as 'active' and it will
+// respond to keypresses. Neither parameter can be NULL
+typedef void (RENDERDOC_CC *pRENDERDOC_SetActiveWindow)(RENDERDOC_DevicePointer device, RENDERDOC_WindowHandle wndHandle);
+
+// When choosing either a device pointer or a window handle to capture, you can pass NULL.
+// Passing NULL specifies a 'wildcard' match against anything. This allows you to specify
+// any API rendering to a specific window, or a specific API instance rendering to any window,
+// or in the simplest case of one window and one API, you can just pass NULL for both.
+//
+// In either case, if there are two or more possible matching (device,window) pairs it
+// is undefined which one will be captured.
+//
+// Note: for headless rendering you can pass NULL for the window handle and either specify
+// a device pointer or leave it NULL as above.
+
+// Immediately starts capturing API calls on the specified device pointer and window handle.
+//
+// If there is no matching thing to capture (e.g. no supported API has been initialised),
+// this will do nothing.
+//
+// The results are undefined (including crashes) if two captures are started overlapping,
+// even on separate devices and/oror windows.
+typedef void (RENDERDOC_CC *pRENDERDOC_StartFrameCapture)(RENDERDOC_DevicePointer device, RENDERDOC_WindowHandle wndHandle);
+
+// Returns whether or not a frame capture is currently ongoing anywhere.
+//
+// This will return 1 if a capture is ongoing, and 0 if there is no capture running
+typedef uint32_t (RENDERDOC_CC *pRENDERDOC_IsFrameCapturing)();
+
+// Ends capturing immediately.
+//
+// This will return 1 if the capture succeeded, and 0 if there was an error capturing.
+typedef uint32_t (RENDERDOC_CC *pRENDERDOC_EndFrameCapture)(RENDERDOC_DevicePointer device, RENDERDOC_WindowHandle wndHandle);
+
+//////////////////////////////////////////////////////////////////////////////////////////////////
+// RenderDoc API versions
+//
+
+// RenderDoc uses semantic versioning (http://semver.org/).
+//
+// MAJOR version is incremented when incompatible API changes happen.
+// MINOR version is incremented when functionality is added in a backwards-compatible manner.
+// PATCH version is incremented when backwards-compatible bug fixes happen.
+//
+// Note that this means the API returned can be higher than the one you might have requested.
+// e.g. if you are running against a newer RenderDoc that supports 1.0.1, it will be returned
+// instead of 1.0.0. You can check this with the GetAPIVersion entry point
+typedef enum
+{
+ eRENDERDOC_API_Version_1_0_0 = 10000, // RENDERDOC_API_1_0_0 = 1 000 000
+} RENDERDOC_Version;
+
+// eRENDERDOC_API_Version_1_0_0
+typedef struct
+{
+ pRENDERDOC_GetAPIVersion GetAPIVersion;
+
+ pRENDERDOC_SetCaptureOptionU32 SetCaptureOptionU32;
+ pRENDERDOC_SetCaptureOptionF32 SetCaptureOptionF32;
+
+ pRENDERDOC_GetCaptureOptionU32 GetCaptureOptionU32;
+ pRENDERDOC_GetCaptureOptionF32 GetCaptureOptionF32;
+
+ pRENDERDOC_SetFocusToggleKeys SetFocusToggleKeys;
+ pRENDERDOC_SetCaptureKeys SetCaptureKeys;
+
+ pRENDERDOC_GetOverlayBits GetOverlayBits;
+ pRENDERDOC_MaskOverlayBits MaskOverlayBits;
+
+ pRENDERDOC_Shutdown Shutdown;
+ pRENDERDOC_UnloadCrashHandler UnloadCrashHandler;
+
+ pRENDERDOC_SetLogFilePathTemplate SetLogFilePathTemplate;
+ pRENDERDOC_GetLogFilePathTemplate GetLogFilePathTemplate;
+
+ pRENDERDOC_GetNumCaptures GetNumCaptures;
+ pRENDERDOC_GetCapture GetCapture;
+
+ pRENDERDOC_TriggerCapture TriggerCapture;
+
+ pRENDERDOC_IsRemoteAccessConnected IsRemoteAccessConnected;
+ pRENDERDOC_LaunchReplayUI LaunchReplayUI;
+
+ pRENDERDOC_SetActiveWindow SetActiveWindow;
+
+ pRENDERDOC_StartFrameCapture StartFrameCapture;
+ pRENDERDOC_IsFrameCapturing IsFrameCapturing;
+ pRENDERDOC_EndFrameCapture EndFrameCapture;
+} RENDERDOC_API_1_0_0;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////
+// RenderDoc API entry point
+//
+// This entry point can be obtained via GetProcAddress/dlsym if RenderDoc is available.
+//
+// The name is the same as the typedef - "RENDERDOC_GetAPI"
+//
+// This function is not thread safe, and should not be called on multiple threads at once.
+// Ideally, call this once as early as possible in your application's startup, before doing
+// any API work, since some configuration functionality etc has to be done also before
+// initialising any APIs.
+//
+// Parameters:
+// version is a single value from the RENDERDOC_Version above.
+//
+// outAPIPointers will be filled out with a pointer to the corresponding struct of function
+// pointers.
+//
+// Returns:
+// 1 - if the outAPIPointers has been filled with a pointer to the API struct requested
+// 0 - if the requested version is not supported or the arguments are invalid.
+//
+typedef int (RENDERDOC_CC *pRENDERDOC_GetAPI)(RENDERDOC_Version version, void **outAPIPointers);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/3rdparty/bgfx/3rdparty/scintilla/gtk/makefile.orig b/3rdparty/bgfx/3rdparty/scintilla/gtk/makefile.orig
new file mode 100644
index 00000000000..ad11a29f4bb
--- /dev/null
+++ b/3rdparty/bgfx/3rdparty/scintilla/gtk/makefile.orig
@@ -0,0 +1,105 @@
+# Make file for Scintilla on Linux or compatible OS
+# Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
+# The License.txt file describes the conditions under which this software may be distributed.
+# This makefile assumes GCC 4.3 is used and changes will be needed to use other compilers.
+# GNU make does not like \r\n line endings so should be saved to CVS in binary form.
+# Builds for GTK+ 2 and no longer supports GTK+ 1.
+# Also works with ming32-make on Windows.
+
+.SUFFIXES: .cxx .c .o .h .a
+ifdef CLANG
+CC = clang++
+CCOMP = clang
+# Can choose aspect to sanitize: address and undefined can simply change SANITIZE but for
+# thread also need to create Position Independent Executable -> search online documentation
+SANITIZE = address
+#SANITIZE = undefined
+else
+CC = g++ -mrecip
+CCOMP = gcc -mrecip
+endif
+AR = ar
+RANLIB = touch
+
+ifdef GTK3
+GTKVERSION=gtk+-3.0
+else
+GTKVERSION=gtk+-2.0
+endif
+
+# Environment variable windir always defined on Win32
+
+ifndef windir
+ifeq ($(shell uname),Darwin)
+RANLIB = ranlib
+endif
+endif
+
+ifdef windir
+DEL = del /q
+COMPLIB=..\bin\scintilla.a
+else
+DEL = rm -f
+COMPLIB=../bin/scintilla.a
+endif
+
+vpath %.h ../src ../include ../lexlib
+vpath %.cxx ../src ../lexlib ../lexers
+
+INCLUDEDIRS=-I ../include -I ../src -I ../lexlib
+ifdef CHECK_DEPRECATED
+DEPRECATED=-DGDK_PIXBUF_DISABLE_DEPRECATED -DGDK_DISABLE_DEPRECATED -DGTK_DISABLE_DEPRECATED -DDISABLE_GDK_FONT
+endif
+CXXBASEFLAGS=-Wall -pedantic -DGTK -DSCI_LEXER $(INCLUDEDIRS) $(DEPRECATED)
+
+ifdef NOTHREADS
+THREADFLAGS=-DG_THREADS_IMPL_NONE
+else
+THREADFLAGS=
+endif
+
+ifdef DEBUG
+ifdef CLANG
+CTFLAGS=-DDEBUG -g -fsanitize=$(SANITIZE) $(CXXBASEFLAGS) $(THREADFLAGS)
+else
+CTFLAGS=-DDEBUG -g $(CXXBASEFLAGS) $(THREADFLAGS)
+endif
+else
+CTFLAGS=-DNDEBUG -Os $(CXXBASEFLAGS) $(THREADFLAGS)
+endif
+
+CFLAGS:=$(CTFLAGS)
+CXXTFLAGS:=--std=c++0x $(CTFLAGS)
+
+CONFIGFLAGS:=$(shell pkg-config --cflags $(GTKVERSION))
+MARSHALLER=scintilla-marshal.o
+
+.cxx.o:
+ $(CC) $(CONFIGFLAGS) $(CXXTFLAGS) $(CXXFLAGS) -c $<
+.c.o:
+ $(CCOMP) $(CONFIGFLAGS) $(CFLAGS) -w -c $<
+
+LEXOBJS:=$(addsuffix .o,$(basename $(notdir $(wildcard ../lexers/Lex*.cxx))))
+
+all: $(COMPLIB)
+
+clean:
+ $(DEL) *.o $(COMPLIB) *.plist
+
+analyze:
+ clang --analyze $(CONFIGFLAGS) $(CXXTFLAGS) $(CXXFLAGS) *.cxx ../src/*.cxx ../lexlib/*.cxx ../lexers/*.cxx
+
+deps:
+ $(CC) -MM $(CONFIGFLAGS) $(CXXTFLAGS) *.cxx ../src/*.cxx ../lexlib/*.cxx ../lexers/*.cxx | sed -e 's/\/usr.* //' | grep [a-zA-Z] >deps.mak
+
+$(COMPLIB): Accessor.o CharacterSet.o LexerBase.o LexerModule.o LexerSimple.o StyleContext.o WordList.o \
+ CharClassify.o Decoration.o Document.o PerLine.o Catalogue.o CallTip.o CaseConvert.o CaseFolder.o \
+ ScintillaBase.o ContractionState.o Editor.o ExternalLexer.o PropSetSimple.o PlatGTK.o \
+ KeyMap.o LineMarker.o PositionCache.o ScintillaGTK.o CellBuffer.o CharacterCategory.o ViewStyle.o \
+ RESearch.o RunStyles.o Selection.o Style.o Indicator.o AutoComplete.o UniConversion.o XPM.o \
+ $(MARSHALLER) $(LEXOBJS)
+ $(AR) rc $@ $^
+ $(RANLIB) $@
+
+# Automatically generate header dependencies with "make deps"
+include deps.mak
diff --git a/3rdparty/bgfx/3rdparty/scintilla/src/Editor.cxx.orig b/3rdparty/bgfx/3rdparty/scintilla/src/Editor.cxx.orig
new file mode 100644
index 00000000000..c17eb21bcee
--- /dev/null
+++ b/3rdparty/bgfx/3rdparty/scintilla/src/Editor.cxx.orig
@@ -0,0 +1,9647 @@
+// Scintilla source code edit control
+/** @file Editor.cxx
+ ** Main code for the edit control.
+ **/
+// Copyright 1998-2011 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <math.h>
+#include <assert.h>
+
+#include <string>
+#include <vector>
+#include <map>
+#include <unordered_map>
+#include <algorithm>
+#include <memory>
+
+#include "Platform.h"
+
+#include "ILexer.h"
+#include "Scintilla.h"
+
+#include "SplitVector.h"
+#include "Partitioning.h"
+#include "RunStyles.h"
+#include "ContractionState.h"
+#include "CellBuffer.h"
+#include "KeyMap.h"
+#include "Indicator.h"
+#include "XPM.h"
+#include "LineMarker.h"
+#include "Style.h"
+#include "ViewStyle.h"
+#include "CharClassify.h"
+#include "Decoration.h"
+#include "CaseFolder.h"
+#include "Document.h"
+#include "UniConversion.h"
+#include "Selection.h"
+#include "PositionCache.h"
+#include "Editor.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+/*
+ return whether this modification represents an operation that
+ may reasonably be deferred (not done now OR [possibly] at all)
+*/
+static bool CanDeferToLastStep(const DocModification &mh) {
+ if (mh.modificationType & (SC_MOD_BEFOREINSERT | SC_MOD_BEFOREDELETE))
+ return true; // CAN skip
+ if (!(mh.modificationType & (SC_PERFORMED_UNDO | SC_PERFORMED_REDO)))
+ return false; // MUST do
+ if (mh.modificationType & SC_MULTISTEPUNDOREDO)
+ return true; // CAN skip
+ return false; // PRESUMABLY must do
+}
+
+static bool CanEliminate(const DocModification &mh) {
+ return
+ (mh.modificationType & (SC_MOD_BEFOREINSERT | SC_MOD_BEFOREDELETE)) != 0;
+}
+
+/*
+ return whether this modification represents the FINAL step
+ in a [possibly lengthy] multi-step Undo/Redo sequence
+*/
+static bool IsLastStep(const DocModification &mh) {
+ return
+ (mh.modificationType & (SC_PERFORMED_UNDO | SC_PERFORMED_REDO)) != 0
+ && (mh.modificationType & SC_MULTISTEPUNDOREDO) != 0
+ && (mh.modificationType & SC_LASTSTEPINUNDOREDO) != 0
+ && (mh.modificationType & SC_MULTILINEUNDOREDO) != 0;
+}
+
+Caret::Caret() :
+ active(false), on(false), period(500) {}
+
+Timer::Timer() :
+ ticking(false), ticksToWait(0), tickerID(0) {}
+
+Idler::Idler() :
+ state(false), idlerID(0) {}
+
+static inline bool IsControlCharacter(int ch) {
+ // iscntrl returns true for lots of chars > 127 which are displayable
+ return ch >= 0 && ch < ' ';
+}
+
+static inline bool IsAllSpacesOrTabs(char *s, unsigned int len) {
+ for (unsigned int i = 0; i < len; i++) {
+ // This is safe because IsSpaceOrTab() will return false for null terminators
+ if (!IsSpaceOrTab(s[i]))
+ return false;
+ }
+ return true;
+}
+
+PrintParameters::PrintParameters() {
+ magnification = 0;
+ colourMode = SC_PRINT_NORMAL;
+ wrapState = eWrapWord;
+}
+
+Editor::Editor() {
+ ctrlID = 0;
+
+ stylesValid = false;
+ technology = SC_TECHNOLOGY_DEFAULT;
+ scaleRGBAImage = 100;
+
+ cursorMode = SC_CURSORNORMAL;
+
+ hasFocus = false;
+ hideSelection = false;
+ inOverstrike = false;
+ drawOverstrikeCaret = true;
+ errorStatus = 0;
+ mouseDownCaptures = true;
+
+ bufferedDraw = true;
+ twoPhaseDraw = true;
+
+ lastClickTime = 0;
+ dwellDelay = SC_TIME_FOREVER;
+ ticksToDwell = SC_TIME_FOREVER;
+ dwelling = false;
+ ptMouseLast.x = 0;
+ ptMouseLast.y = 0;
+ inDragDrop = ddNone;
+ dropWentOutside = false;
+ posDrag = SelectionPosition(invalidPosition);
+ posDrop = SelectionPosition(invalidPosition);
+ hotSpotClickPos = INVALID_POSITION;
+ selectionType = selChar;
+
+ lastXChosen = 0;
+ lineAnchorPos = 0;
+ originalAnchorPos = 0;
+ wordSelectAnchorStartPos = 0;
+ wordSelectAnchorEndPos = 0;
+ wordSelectInitialCaretPos = -1;
+
+ primarySelection = true;
+
+ caretXPolicy = CARET_SLOP | CARET_EVEN;
+ caretXSlop = 50;
+
+ caretYPolicy = CARET_EVEN;
+ caretYSlop = 0;
+
+ visiblePolicy = 0;
+ visibleSlop = 0;
+
+ searchAnchor = 0;
+
+ xOffset = 0;
+ xCaretMargin = 50;
+ horizontalScrollBarVisible = true;
+ scrollWidth = 2000;
+ trackLineWidth = false;
+ lineWidthMaxSeen = 0;
+ verticalScrollBarVisible = true;
+ endAtLastLine = true;
+ caretSticky = SC_CARETSTICKY_OFF;
+ marginOptions = SC_MARGINOPTION_NONE;
+ mouseSelectionRectangularSwitch = false;
+ multipleSelection = false;
+ additionalSelectionTyping = false;
+ multiPasteMode = SC_MULTIPASTE_ONCE;
+ additionalCaretsBlink = true;
+ additionalCaretsVisible = true;
+ virtualSpaceOptions = SCVS_NONE;
+
+ pixmapLine = 0;
+ pixmapSelMargin = 0;
+ pixmapSelPattern = 0;
+ pixmapSelPatternOffset1 = 0;
+ pixmapIndentGuide = 0;
+ pixmapIndentGuideHighlight = 0;
+
+ targetStart = 0;
+ targetEnd = 0;
+ searchFlags = 0;
+
+ topLine = 0;
+ posTopLine = 0;
+
+ lengthForEncode = -1;
+
+ needUpdateUI = 0;
+ ContainerNeedsUpdate(SC_UPDATE_CONTENT);
+ braces[0] = invalidPosition;
+ braces[1] = invalidPosition;
+ bracesMatchStyle = STYLE_BRACEBAD;
+ highlightGuideColumn = 0;
+
+ paintState = notPainting;
+ paintAbandonedByStyling = false;
+ paintingAllText = false;
+ willRedrawAll = false;
+
+ modEventMask = SC_MODEVENTMASKALL;
+
+ pdoc = new Document();
+ pdoc->AddRef();
+ pdoc->AddWatcher(this, 0);
+
+ recordingMacro = false;
+ foldFlags = 0;
+ foldAutomatic = 0;
+
+ wrapWidth = LineLayout::wrapWidthInfinite;
+
+ convertPastes = true;
+
+ hsStart = -1;
+ hsEnd = -1;
+
+ llc.SetLevel(LineLayoutCache::llcCaret);
+ posCache.SetSize(0x400);
+
+ SetRepresentations();
+}
+
+Editor::~Editor() {
+ pdoc->RemoveWatcher(this, 0);
+ pdoc->Release();
+ pdoc = 0;
+ DropGraphics(true);
+}
+
+void Editor::Finalise() {
+ SetIdle(false);
+ CancelModes();
+}
+
+void Editor::SetRepresentations() {
+ reprs.Clear();
+
+ // C0 control set
+ const char *reps[] = {
+ "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
+ "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI",
+ "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB",
+ "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US"
+ };
+ for (size_t j=0; j < (sizeof(reps) / sizeof(reps[0])); j++) {
+ char c[2] = { static_cast<char>(j), 0 };
+ reprs.SetRepresentation(c, reps[j]);
+ }
+
+ // C1 control set
+ // As well as Unicode mode, ISO-8859-1 should use these
+ if (IsUnicodeMode()) {
+ const char *repsC1[] = {
+ "PAD", "HOP", "BPH", "NBH", "IND", "NEL", "SSA", "ESA",
+ "HTS", "HTJ", "VTS", "PLD", "PLU", "RI", "SS2", "SS3",
+ "DCS", "PU1", "PU2", "STS", "CCH", "MW", "SPA", "EPA",
+ "SOS", "SGCI", "SCI", "CSI", "ST", "OSC", "PM", "APC"
+ };
+ for (size_t j=0; j < (sizeof(repsC1) / sizeof(repsC1[0])); j++) {
+ char c1[3] = { '\xc2', static_cast<char>(0x80+j), 0 };
+ reprs.SetRepresentation(c1, repsC1[j]);
+ }
+ }
+
+ // UTF-8 invalid bytes
+ if (IsUnicodeMode()) {
+ for (int k=0x80; k < 0x100; k++) {
+ char hiByte[2] = { static_cast<char>(k), 0 };
+ char hexits[4];
+ sprintf(hexits, "x%2X", k);
+ reprs.SetRepresentation(hiByte, hexits);
+ }
+ }
+}
+
+void Editor::DropGraphics(bool freeObjects) {
+ if (freeObjects) {
+ delete pixmapLine;
+ pixmapLine = 0;
+ delete pixmapSelMargin;
+ pixmapSelMargin = 0;
+ delete pixmapSelPattern;
+ pixmapSelPattern = 0;
+ delete pixmapSelPatternOffset1;
+ pixmapSelPatternOffset1 = 0;
+ delete pixmapIndentGuide;
+ pixmapIndentGuide = 0;
+ delete pixmapIndentGuideHighlight;
+ pixmapIndentGuideHighlight = 0;
+ } else {
+ if (pixmapLine)
+ pixmapLine->Release();
+ if (pixmapSelMargin)
+ pixmapSelMargin->Release();
+ if (pixmapSelPattern)
+ pixmapSelPattern->Release();
+ if (pixmapSelPatternOffset1)
+ pixmapSelPatternOffset1->Release();
+ if (pixmapIndentGuide)
+ pixmapIndentGuide->Release();
+ if (pixmapIndentGuideHighlight)
+ pixmapIndentGuideHighlight->Release();
+ }
+}
+
+void Editor::AllocateGraphics() {
+ if (!pixmapLine)
+ pixmapLine = Surface::Allocate(technology);
+ if (!pixmapSelMargin)
+ pixmapSelMargin = Surface::Allocate(technology);
+ if (!pixmapSelPattern)
+ pixmapSelPattern = Surface::Allocate(technology);
+ if (!pixmapSelPatternOffset1)
+ pixmapSelPatternOffset1 = Surface::Allocate(technology);
+ if (!pixmapIndentGuide)
+ pixmapIndentGuide = Surface::Allocate(technology);
+ if (!pixmapIndentGuideHighlight)
+ pixmapIndentGuideHighlight = Surface::Allocate(technology);
+}
+
+void Editor::InvalidateStyleData() {
+ stylesValid = false;
+ vs.technology = technology;
+ DropGraphics(false);
+ AllocateGraphics();
+ llc.Invalidate(LineLayout::llInvalid);
+ posCache.Clear();
+}
+
+void Editor::InvalidateStyleRedraw() {
+ NeedWrapping();
+ InvalidateStyleData();
+ Redraw();
+}
+
+void Editor::RefreshStyleData() {
+ if (!stylesValid) {
+ stylesValid = true;
+ AutoSurface surface(this);
+ if (surface) {
+ vs.Refresh(*surface, pdoc->tabInChars);
+ }
+ SetScrollBars();
+ SetRectangularRange();
+ }
+}
+
+Point Editor::GetVisibleOriginInMain() {
+ return Point(0,0);
+}
+
+Point Editor::DocumentPointFromView(Point ptView) {
+ Point ptDocument = ptView;
+ if (wMargin.GetID()) {
+ Point ptOrigin = GetVisibleOriginInMain();
+ ptDocument.x += ptOrigin.x;
+ ptDocument.y += ptOrigin.y;
+ } else {
+ ptDocument.x += xOffset;
+ ptDocument.y += topLine * vs.lineHeight;
+ }
+ return ptDocument;
+}
+
+int Editor::TopLineOfMain() const {
+ if (wMargin.GetID())
+ return 0;
+ else
+ return topLine;
+}
+
+PRectangle Editor::GetClientRectangle() {
+ return wMain.GetClientPosition();
+}
+
+PRectangle Editor::GetTextRectangle() {
+ PRectangle rc = GetClientRectangle();
+ rc.left += vs.textStart;
+ rc.right -= vs.rightMarginWidth;
+ return rc;
+}
+
+int Editor::LinesOnScreen() {
+ PRectangle rcClient = GetClientRectangle();
+ int htClient = rcClient.bottom - rcClient.top;
+ //Platform::DebugPrintf("lines on screen = %d\n", htClient / lineHeight + 1);
+ return htClient / vs.lineHeight;
+}
+
+int Editor::LinesToScroll() {
+ int retVal = LinesOnScreen() - 1;
+ if (retVal < 1)
+ return 1;
+ else
+ return retVal;
+}
+
+int Editor::MaxScrollPos() {
+ //Platform::DebugPrintf("Lines %d screen = %d maxScroll = %d\n",
+ //LinesTotal(), LinesOnScreen(), LinesTotal() - LinesOnScreen() + 1);
+ int retVal = cs.LinesDisplayed();
+ if (endAtLastLine) {
+ retVal -= LinesOnScreen();
+ } else {
+ retVal--;
+ }
+ if (retVal < 0) {
+ return 0;
+ } else {
+ return retVal;
+ }
+}
+
+const char *ControlCharacterString(unsigned char ch) {
+ const char *reps[] = {
+ "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
+ "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI",
+ "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB",
+ "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US"
+ };
+ if (ch < (sizeof(reps) / sizeof(reps[0]))) {
+ return reps[ch];
+ } else {
+ return "BAD";
+ }
+}
+
+/**
+ * Convenience class to ensure LineLayout objects are always disposed.
+ */
+class AutoLineLayout {
+ LineLayoutCache &llc;
+ LineLayout *ll;
+ AutoLineLayout &operator=(const AutoLineLayout &);
+public:
+ AutoLineLayout(LineLayoutCache &llc_, LineLayout *ll_) : llc(llc_), ll(ll_) {}
+ ~AutoLineLayout() {
+ llc.Dispose(ll);
+ ll = 0;
+ }
+ LineLayout *operator->() const {
+ return ll;
+ }
+ operator LineLayout *() const {
+ return ll;
+ }
+ void Set(LineLayout *ll_) {
+ llc.Dispose(ll);
+ ll = ll_;
+ }
+};
+
+SelectionPosition Editor::ClampPositionIntoDocument(SelectionPosition sp) const {
+ if (sp.Position() < 0) {
+ return SelectionPosition(0);
+ } else if (sp.Position() > pdoc->Length()) {
+ return SelectionPosition(pdoc->Length());
+ } else {
+ // If not at end of line then set offset to 0
+ if (!pdoc->IsLineEndPosition(sp.Position()))
+ sp.SetVirtualSpace(0);
+ return sp;
+ }
+}
+
+Point Editor::LocationFromPosition(SelectionPosition pos) {
+ Point pt;
+ RefreshStyleData();
+ if (pos.Position() == INVALID_POSITION)
+ return pt;
+ int line = pdoc->LineFromPosition(pos.Position());
+ int lineVisible = cs.DisplayFromDoc(line);
+ //Platform::DebugPrintf("line=%d\n", line);
+ AutoSurface surface(this);
+ AutoLineLayout ll(llc, RetrieveLineLayout(line));
+ if (surface && ll) {
+ // -1 because of adding in for visible lines in following loop.
+ pt.y = (lineVisible - topLine - 1) * vs.lineHeight;
+ pt.x = 0;
+ unsigned int posLineStart = pdoc->LineStart(line);
+ LayoutLine(line, surface, vs, ll, wrapWidth);
+ int posInLine = pos.Position() - posLineStart;
+ // In case of very long line put x at arbitrary large position
+ if (posInLine > ll->maxLineLength) {
+ pt.x = ll->positions[ll->maxLineLength] - ll->positions[ll->LineStart(ll->lines)];
+ }
+
+ for (int subLine = 0; subLine < ll->lines; subLine++) {
+ if ((posInLine >= ll->LineStart(subLine)) && (posInLine <= ll->LineStart(subLine + 1))) {
+ pt.x = ll->positions[posInLine] - ll->positions[ll->LineStart(subLine)];
+ if (ll->wrapIndent != 0) {
+ int lineStart = ll->LineStart(subLine);
+ if (lineStart != 0) // Wrapped
+ pt.x += ll->wrapIndent;
+ }
+ }
+ if (posInLine >= ll->LineStart(subLine)) {
+ pt.y += vs.lineHeight;
+ }
+ }
+ pt.x += vs.textStart - xOffset;
+ }
+ pt.x += pos.VirtualSpace() * vs.styles[ll->EndLineStyle()].spaceWidth;
+ return pt;
+}
+
+Point Editor::LocationFromPosition(int pos) {
+ return LocationFromPosition(SelectionPosition(pos));
+}
+
+int Editor::XFromPosition(int pos) {
+ Point pt = LocationFromPosition(pos);
+ return pt.x - vs.textStart + xOffset;
+}
+
+int Editor::XFromPosition(SelectionPosition sp) {
+ Point pt = LocationFromPosition(sp);
+ return pt.x - vs.textStart + xOffset;
+}
+
+int Editor::LineFromLocation(Point pt) const {
+ return cs.DocFromDisplay(pt.y / vs.lineHeight + topLine);
+}
+
+void Editor::SetTopLine(int topLineNew) {
+ if ((topLine != topLineNew) && (topLineNew >= 0)) {
+ topLine = topLineNew;
+ ContainerNeedsUpdate(SC_UPDATE_V_SCROLL);
+ }
+ posTopLine = pdoc->LineStart(cs.DocFromDisplay(topLine));
+}
+
+SelectionPosition Editor::SPositionFromLocation(Point pt, bool canReturnInvalid, bool charPosition, bool virtualSpace) {
+ RefreshStyleData();
+ if (canReturnInvalid) {
+ PRectangle rcClient = GetTextRectangle();
+ if (!rcClient.Contains(pt))
+ return SelectionPosition(INVALID_POSITION);
+ if (pt.x < vs.textStart)
+ return SelectionPosition(INVALID_POSITION);
+ if (pt.y < 0)
+ return SelectionPosition(INVALID_POSITION);
+ }
+ pt = DocumentPointFromView(pt);
+ pt.x = pt.x - vs.textStart;
+ int visibleLine = floor(pt.y / vs.lineHeight);
+ if (!canReturnInvalid && (visibleLine < 0))
+ visibleLine = 0;
+ int lineDoc = cs.DocFromDisplay(visibleLine);
+ if (canReturnInvalid && (lineDoc < 0))
+ return SelectionPosition(INVALID_POSITION);
+ if (lineDoc >= pdoc->LinesTotal())
+ return SelectionPosition(canReturnInvalid ? INVALID_POSITION : pdoc->Length());
+ unsigned int posLineStart = pdoc->LineStart(lineDoc);
+ SelectionPosition retVal(canReturnInvalid ? INVALID_POSITION : static_cast<int>(posLineStart));
+ AutoSurface surface(this);
+ AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc));
+ if (surface && ll) {
+ LayoutLine(lineDoc, surface, vs, ll, wrapWidth);
+ int lineStartSet = cs.DisplayFromDoc(lineDoc);
+ int subLine = visibleLine - lineStartSet;
+ if (subLine < ll->lines) {
+ int lineStart = ll->LineStart(subLine);
+ int lineEnd = ll->LineLastVisible(subLine);
+ XYPOSITION subLineStart = ll->positions[lineStart];
+
+ if (ll->wrapIndent != 0) {
+ if (lineStart != 0) // Wrapped
+ pt.x -= ll->wrapIndent;
+ }
+ int i = ll->FindBefore(pt.x + subLineStart, lineStart, lineEnd);
+ while (i < lineEnd) {
+ if (charPosition) {
+ if ((pt.x + subLineStart) < (ll->positions[i + 1])) {
+ return SelectionPosition(pdoc->MovePositionOutsideChar(i + posLineStart, 1));
+ }
+ } else {
+ if ((pt.x + subLineStart) < ((ll->positions[i] + ll->positions[i + 1]) / 2)) {
+ return SelectionPosition(pdoc->MovePositionOutsideChar(i + posLineStart, 1));
+ }
+ }
+ i++;
+ }
+ if (virtualSpace) {
+ const XYPOSITION spaceWidth = vs.styles[ll->EndLineStyle()].spaceWidth;
+ int spaceOffset = (pt.x + subLineStart - ll->positions[lineEnd] + spaceWidth / 2) /
+ spaceWidth;
+ return SelectionPosition(lineEnd + posLineStart, spaceOffset);
+ } else if (canReturnInvalid) {
+ if (pt.x < (ll->positions[lineEnd] - subLineStart)) {
+ return SelectionPosition(pdoc->MovePositionOutsideChar(lineEnd + posLineStart, 1));
+ }
+ } else {
+ return SelectionPosition(lineEnd + posLineStart);
+ }
+ }
+ if (!canReturnInvalid)
+ return SelectionPosition(ll->numCharsInLine + posLineStart);
+ }
+ return retVal;
+}
+
+int Editor::PositionFromLocation(Point pt, bool canReturnInvalid, bool charPosition) {
+ return SPositionFromLocation(pt, canReturnInvalid, charPosition, false).Position();
+}
+
+/**
+ * Find the document position corresponding to an x coordinate on a particular document line.
+ * Ensure is between whole characters when document is in multi-byte or UTF-8 mode.
+ */
+SelectionPosition Editor::SPositionFromLineX(int lineDoc, int x) {
+ RefreshStyleData();
+ if (lineDoc >= pdoc->LinesTotal())
+ return SelectionPosition(pdoc->Length());
+ //Platform::DebugPrintf("Position of (%d,%d) line = %d top=%d\n", pt.x, pt.y, line, topLine);
+ AutoSurface surface(this);
+ AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc));
+ int retVal = 0;
+ if (surface && ll) {
+ unsigned int posLineStart = pdoc->LineStart(lineDoc);
+ LayoutLine(lineDoc, surface, vs, ll, wrapWidth);
+ int subLine = 0;
+ int lineStart = ll->LineStart(subLine);
+ int lineEnd = ll->LineLastVisible(subLine);
+ XYPOSITION subLineStart = ll->positions[lineStart];
+ XYPOSITION newX = x;
+
+ if (ll->wrapIndent != 0) {
+ if (lineStart != 0) // Wrapped
+ newX -= ll->wrapIndent;
+ }
+ int i = ll->FindBefore(newX + subLineStart, lineStart, lineEnd);
+ while (i < lineEnd) {
+ if ((newX + subLineStart) < ((ll->positions[i] + ll->positions[i + 1]) / 2)) {
+ retVal = pdoc->MovePositionOutsideChar(i + posLineStart, 1);
+ return SelectionPosition(retVal);
+ }
+ i++;
+ }
+ const XYPOSITION spaceWidth = vs.styles[ll->EndLineStyle()].spaceWidth;
+ int spaceOffset = (newX + subLineStart - ll->positions[lineEnd] + spaceWidth / 2) / spaceWidth;
+ return SelectionPosition(lineEnd + posLineStart, spaceOffset);
+ }
+ return SelectionPosition(retVal);
+}
+
+int Editor::PositionFromLineX(int lineDoc, int x) {
+ return SPositionFromLineX(lineDoc, x).Position();
+}
+
+/**
+ * If painting then abandon the painting because a wider redraw is needed.
+ * @return true if calling code should stop drawing.
+ */
+bool Editor::AbandonPaint() {
+ if ((paintState == painting) && !paintingAllText) {
+ paintState = paintAbandoned;
+ }
+ return paintState == paintAbandoned;
+}
+
+void Editor::RedrawRect(PRectangle rc) {
+ //Platform::DebugPrintf("Redraw %0d,%0d - %0d,%0d\n", rc.left, rc.top, rc.right, rc.bottom);
+
+ // Clip the redraw rectangle into the client area
+ PRectangle rcClient = GetClientRectangle();
+ if (rc.top < rcClient.top)
+ rc.top = rcClient.top;
+ if (rc.bottom > rcClient.bottom)
+ rc.bottom = rcClient.bottom;
+ if (rc.left < rcClient.left)
+ rc.left = rcClient.left;
+ if (rc.right > rcClient.right)
+ rc.right = rcClient.right;
+
+ if ((rc.bottom > rc.top) && (rc.right > rc.left)) {
+ wMain.InvalidateRectangle(rc);
+ }
+}
+
+void Editor::Redraw() {
+ //Platform::DebugPrintf("Redraw all\n");
+ PRectangle rcClient = GetClientRectangle();
+ wMain.InvalidateRectangle(rcClient);
+ if (wMargin.GetID())
+ wMargin.InvalidateAll();
+ //wMain.InvalidateAll();
+}
+
+void Editor::RedrawSelMargin(int line, bool allAfter) {
+ if (!AbandonPaint()) {
+ if (vs.maskInLine) {
+ Redraw();
+ } else {
+ PRectangle rcSelMargin = GetClientRectangle();
+ rcSelMargin.right = rcSelMargin.left + vs.fixedColumnWidth;
+ if (line != -1) {
+ int position = pdoc->LineStart(line);
+ PRectangle rcLine = RectangleFromRange(position, position);
+
+ // Inflate line rectangle if there are image markers with height larger than line height
+ if (vs.largestMarkerHeight > vs.lineHeight) {
+ int delta = (vs.largestMarkerHeight - vs.lineHeight + 1) / 2;
+ rcLine.top -= delta;
+ rcLine.bottom += delta;
+ if (rcLine.top < rcSelMargin.top)
+ rcLine.top = rcSelMargin.top;
+ if (rcLine.bottom > rcSelMargin.bottom)
+ rcLine.bottom = rcSelMargin.bottom;
+ }
+
+ rcSelMargin.top = rcLine.top;
+ if (!allAfter)
+ rcSelMargin.bottom = rcLine.bottom;
+ }
+ if (wMargin.GetID()) {
+ Point ptOrigin = GetVisibleOriginInMain();
+ rcSelMargin.Move(-ptOrigin.x, -ptOrigin.y);
+ wMargin.InvalidateRectangle(rcSelMargin);
+ } else {
+ wMain.InvalidateRectangle(rcSelMargin);
+ }
+ }
+ }
+}
+
+PRectangle Editor::RectangleFromRange(int start, int end) {
+ int minPos = start;
+ if (minPos > end)
+ minPos = end;
+ int maxPos = start;
+ if (maxPos < end)
+ maxPos = end;
+ int minLine = cs.DisplayFromDoc(pdoc->LineFromPosition(minPos));
+ int lineDocMax = pdoc->LineFromPosition(maxPos);
+ int maxLine = cs.DisplayFromDoc(lineDocMax) + cs.GetHeight(lineDocMax) - 1;
+ PRectangle rcClient = GetTextRectangle();
+ PRectangle rc;
+ const int leftTextOverlap = ((xOffset == 0) && (vs.leftMarginWidth > 0)) ? 1 : 0;
+ rc.left = vs.textStart - leftTextOverlap;
+ rc.top = (minLine - TopLineOfMain()) * vs.lineHeight;
+ if (rc.top < rcClient.top)
+ rc.top = rcClient.top;
+ rc.right = rcClient.right;
+ rc.bottom = (maxLine - TopLineOfMain() + 1) * vs.lineHeight;
+
+ return rc;
+}
+
+void Editor::InvalidateRange(int start, int end) {
+ RedrawRect(RectangleFromRange(start, end));
+}
+
+int Editor::CurrentPosition() const {
+ return sel.MainCaret();
+}
+
+bool Editor::SelectionEmpty() const {
+ return sel.Empty();
+}
+
+SelectionPosition Editor::SelectionStart() {
+ return sel.RangeMain().Start();
+}
+
+SelectionPosition Editor::SelectionEnd() {
+ return sel.RangeMain().End();
+}
+
+void Editor::SetRectangularRange() {
+ if (sel.IsRectangular()) {
+ int xAnchor = XFromPosition(sel.Rectangular().anchor);
+ int xCaret = XFromPosition(sel.Rectangular().caret);
+ if (sel.selType == Selection::selThin) {
+ xCaret = xAnchor;
+ }
+ int lineAnchorRect = pdoc->LineFromPosition(sel.Rectangular().anchor.Position());
+ int lineCaret = pdoc->LineFromPosition(sel.Rectangular().caret.Position());
+ int increment = (lineCaret > lineAnchorRect) ? 1 : -1;
+ for (int line=lineAnchorRect; line != lineCaret+increment; line += increment) {
+ SelectionRange range(SPositionFromLineX(line, xCaret), SPositionFromLineX(line, xAnchor));
+ if ((virtualSpaceOptions & SCVS_RECTANGULARSELECTION) == 0)
+ range.ClearVirtualSpace();
+ if (line == lineAnchorRect)
+ sel.SetSelection(range);
+ else
+ sel.AddSelectionWithoutTrim(range);
+ }
+ }
+}
+
+void Editor::ThinRectangularRange() {
+ if (sel.IsRectangular()) {
+ sel.selType = Selection::selThin;
+ if (sel.Rectangular().caret < sel.Rectangular().anchor) {
+ sel.Rectangular() = SelectionRange(sel.Range(sel.Count()-1).caret, sel.Range(0).anchor);
+ } else {
+ sel.Rectangular() = SelectionRange(sel.Range(sel.Count()-1).anchor, sel.Range(0).caret);
+ }
+ SetRectangularRange();
+ }
+}
+
+void Editor::InvalidateSelection(SelectionRange newMain, bool invalidateWholeSelection) {
+ if (sel.Count() > 1 || !(sel.RangeMain().anchor == newMain.anchor) || sel.IsRectangular()) {
+ invalidateWholeSelection = true;
+ }
+ int firstAffected = Platform::Minimum(sel.RangeMain().Start().Position(), newMain.Start().Position());
+ // +1 for lastAffected ensures caret repainted
+ int lastAffected = Platform::Maximum(newMain.caret.Position()+1, newMain.anchor.Position());
+ lastAffected = Platform::Maximum(lastAffected, sel.RangeMain().End().Position());
+ if (invalidateWholeSelection) {
+ for (size_t r=0; r<sel.Count(); r++) {
+ firstAffected = Platform::Minimum(firstAffected, sel.Range(r).caret.Position());
+ firstAffected = Platform::Minimum(firstAffected, sel.Range(r).anchor.Position());
+ lastAffected = Platform::Maximum(lastAffected, sel.Range(r).caret.Position()+1);
+ lastAffected = Platform::Maximum(lastAffected, sel.Range(r).anchor.Position());
+ }
+ }
+ ContainerNeedsUpdate(SC_UPDATE_SELECTION);
+ InvalidateRange(firstAffected, lastAffected);
+}
+
+void Editor::SetSelection(SelectionPosition currentPos_, SelectionPosition anchor_) {
+ currentPos_ = ClampPositionIntoDocument(currentPos_);
+ anchor_ = ClampPositionIntoDocument(anchor_);
+ int currentLine = pdoc->LineFromPosition(currentPos_.Position());
+ /* For Line selection - ensure the anchor and caret are always
+ at the beginning and end of the region lines. */
+ if (sel.selType == Selection::selLines) {
+ if (currentPos_ > anchor_) {
+ anchor_ = SelectionPosition(pdoc->LineStart(pdoc->LineFromPosition(anchor_.Position())));
+ currentPos_ = SelectionPosition(pdoc->LineEnd(pdoc->LineFromPosition(currentPos_.Position())));
+ } else {
+ currentPos_ = SelectionPosition(pdoc->LineStart(pdoc->LineFromPosition(currentPos_.Position())));
+ anchor_ = SelectionPosition(pdoc->LineEnd(pdoc->LineFromPosition(anchor_.Position())));
+ }
+ }
+ SelectionRange rangeNew(currentPos_, anchor_);
+ if (sel.Count() > 1 || !(sel.RangeMain() == rangeNew)) {
+ InvalidateSelection(rangeNew);
+ }
+ sel.RangeMain() = rangeNew;
+ SetRectangularRange();
+ ClaimSelection();
+
+ if (highlightDelimiter.NeedsDrawing(currentLine)) {
+ RedrawSelMargin();
+ }
+ QueueIdleWork(WorkNeeded::workUpdateUI);
+}
+
+void Editor::SetSelection(int currentPos_, int anchor_) {
+ SetSelection(SelectionPosition(currentPos_), SelectionPosition(anchor_));
+}
+
+// Just move the caret on the main selection
+void Editor::SetSelection(SelectionPosition currentPos_) {
+ currentPos_ = ClampPositionIntoDocument(currentPos_);
+ int currentLine = pdoc->LineFromPosition(currentPos_.Position());
+ if (sel.Count() > 1 || !(sel.RangeMain().caret == currentPos_)) {
+ InvalidateSelection(SelectionRange(currentPos_));
+ }
+ if (sel.IsRectangular()) {
+ sel.Rectangular() =
+ SelectionRange(SelectionPosition(currentPos_), sel.Rectangular().anchor);
+ SetRectangularRange();
+ } else {
+ sel.RangeMain() =
+ SelectionRange(SelectionPosition(currentPos_), sel.RangeMain().anchor);
+ }
+ ClaimSelection();
+
+ if (highlightDelimiter.NeedsDrawing(currentLine)) {
+ RedrawSelMargin();
+ }
+ QueueIdleWork(WorkNeeded::workUpdateUI);
+}
+
+void Editor::SetSelection(int currentPos_) {
+ SetSelection(SelectionPosition(currentPos_));
+}
+
+void Editor::SetEmptySelection(SelectionPosition currentPos_) {
+ int currentLine = pdoc->LineFromPosition(currentPos_.Position());
+ SelectionRange rangeNew(ClampPositionIntoDocument(currentPos_));
+ if (sel.Count() > 1 || !(sel.RangeMain() == rangeNew)) {
+ InvalidateSelection(rangeNew);
+ }
+ sel.Clear();
+ sel.RangeMain() = rangeNew;
+ SetRectangularRange();
+ ClaimSelection();
+
+ if (highlightDelimiter.NeedsDrawing(currentLine)) {
+ RedrawSelMargin();
+ }
+ QueueIdleWork(WorkNeeded::workUpdateUI);
+}
+
+void Editor::SetEmptySelection(int currentPos_) {
+ SetEmptySelection(SelectionPosition(currentPos_));
+}
+
+bool Editor::RangeContainsProtected(int start, int end) const {
+ if (vs.ProtectionActive()) {
+ if (start > end) {
+ int t = start;
+ start = end;
+ end = t;
+ }
+ int mask = pdoc->stylingBitsMask;
+ for (int pos = start; pos < end; pos++) {
+ if (vs.styles[pdoc->StyleAt(pos) & mask].IsProtected())
+ return true;
+ }
+ }
+ return false;
+}
+
+bool Editor::SelectionContainsProtected() {
+ for (size_t r=0; r<sel.Count(); r++) {
+ if (RangeContainsProtected(sel.Range(r).Start().Position(),
+ sel.Range(r).End().Position())) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * Asks document to find a good position and then moves out of any invisible positions.
+ */
+int Editor::MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd) const {
+ return MovePositionOutsideChar(SelectionPosition(pos), moveDir, checkLineEnd).Position();
+}
+
+SelectionPosition Editor::MovePositionOutsideChar(SelectionPosition pos, int moveDir, bool checkLineEnd) const {
+ int posMoved = pdoc->MovePositionOutsideChar(pos.Position(), moveDir, checkLineEnd);
+ if (posMoved != pos.Position())
+ pos.SetPosition(posMoved);
+ if (vs.ProtectionActive()) {
+ int mask = pdoc->stylingBitsMask;
+ if (moveDir > 0) {
+ if ((pos.Position() > 0) && vs.styles[pdoc->StyleAt(pos.Position() - 1) & mask].IsProtected()) {
+ while ((pos.Position() < pdoc->Length()) &&
+ (vs.styles[pdoc->StyleAt(pos.Position()) & mask].IsProtected()))
+ pos.Add(1);
+ }
+ } else if (moveDir < 0) {
+ if (vs.styles[pdoc->StyleAt(pos.Position()) & mask].IsProtected()) {
+ while ((pos.Position() > 0) &&
+ (vs.styles[pdoc->StyleAt(pos.Position() - 1) & mask].IsProtected()))
+ pos.Add(-1);
+ }
+ }
+ }
+ return pos;
+}
+
+int Editor::MovePositionTo(SelectionPosition newPos, Selection::selTypes selt, bool ensureVisible) {
+ bool simpleCaret = (sel.Count() == 1) && sel.Empty();
+ SelectionPosition spCaret = sel.Last();
+
+ int delta = newPos.Position() - sel.MainCaret();
+ newPos = ClampPositionIntoDocument(newPos);
+ newPos = MovePositionOutsideChar(newPos, delta);
+ if (!multipleSelection && sel.IsRectangular() && (selt == Selection::selStream)) {
+ // Can't turn into multiple selection so clear additional selections
+ InvalidateSelection(SelectionRange(newPos), true);
+ SelectionRange rangeMain = sel.RangeMain();
+ sel.SetSelection(rangeMain);
+ }
+ if (!sel.IsRectangular() && (selt == Selection::selRectangle)) {
+ // Switching to rectangular
+ InvalidateSelection(sel.RangeMain(), false);
+ SelectionRange rangeMain = sel.RangeMain();
+ sel.Clear();
+ sel.Rectangular() = rangeMain;
+ }
+ if (selt != Selection::noSel) {
+ sel.selType = selt;
+ }
+ if (selt != Selection::noSel || sel.MoveExtends()) {
+ SetSelection(newPos);
+ } else {
+ SetEmptySelection(newPos);
+ }
+ ShowCaretAtCurrentPosition();
+
+ int currentLine = pdoc->LineFromPosition(newPos.Position());
+ if (ensureVisible) {
+ // In case in need of wrapping to ensure DisplayFromDoc works.
+ if (currentLine >= wrapPending.start)
+ WrapLines(wsAll);
+ XYScrollPosition newXY = XYScrollToMakeVisible(
+ SelectionRange(posDrag.IsValid() ? posDrag : sel.RangeMain().caret), xysDefault);
+ if (simpleCaret && (newXY.xOffset == xOffset)) {
+ // simple vertical scroll then invalidate
+ ScrollTo(newXY.topLine);
+ InvalidateSelection(SelectionRange(spCaret), true);
+ } else {
+ SetXYScroll(newXY);
+ }
+ }
+
+ if (highlightDelimiter.NeedsDrawing(currentLine)) {
+ RedrawSelMargin();
+ }
+ return 0;
+}
+
+int Editor::MovePositionTo(int newPos, Selection::selTypes selt, bool ensureVisible) {
+ return MovePositionTo(SelectionPosition(newPos), selt, ensureVisible);
+}
+
+SelectionPosition Editor::MovePositionSoVisible(SelectionPosition pos, int moveDir) {
+ pos = ClampPositionIntoDocument(pos);
+ pos = MovePositionOutsideChar(pos, moveDir);
+ int lineDoc = pdoc->LineFromPosition(pos.Position());
+ if (cs.GetVisible(lineDoc)) {
+ return pos;
+ } else {
+ int lineDisplay = cs.DisplayFromDoc(lineDoc);
+ if (moveDir > 0) {
+ // lineDisplay is already line before fold as lines in fold use display line of line after fold
+ lineDisplay = Platform::Clamp(lineDisplay, 0, cs.LinesDisplayed());
+ return SelectionPosition(pdoc->LineStart(cs.DocFromDisplay(lineDisplay)));
+ } else {
+ lineDisplay = Platform::Clamp(lineDisplay - 1, 0, cs.LinesDisplayed());
+ return SelectionPosition(pdoc->LineEnd(cs.DocFromDisplay(lineDisplay)));
+ }
+ }
+}
+
+SelectionPosition Editor::MovePositionSoVisible(int pos, int moveDir) {
+ return MovePositionSoVisible(SelectionPosition(pos), moveDir);
+}
+
+Point Editor::PointMainCaret() {
+ return LocationFromPosition(sel.Range(sel.Main()).caret);
+}
+
+/**
+ * Choose the x position that the caret will try to stick to
+ * as it moves up and down.
+ */
+void Editor::SetLastXChosen() {
+ Point pt = PointMainCaret();
+ lastXChosen = pt.x + xOffset;
+}
+
+void Editor::ScrollTo(int line, bool moveThumb) {
+ int topLineNew = Platform::Clamp(line, 0, MaxScrollPos());
+ if (topLineNew != topLine) {
+ // Try to optimise small scrolls
+#ifndef UNDER_CE
+ int linesToMove = topLine - topLineNew;
+ bool performBlit = (abs(linesToMove) <= 10) && (paintState == notPainting);
+ willRedrawAll = !performBlit;
+#endif
+ SetTopLine(topLineNew);
+ // Optimize by styling the view as this will invalidate any needed area
+ // which could abort the initial paint if discovered later.
+ StyleToPositionInView(PositionAfterArea(GetClientRectangle()));
+#ifndef UNDER_CE
+ // Perform redraw rather than scroll if many lines would be redrawn anyway.
+ if (performBlit) {
+ ScrollText(linesToMove);
+ } else {
+ Redraw();
+ }
+ willRedrawAll = false;
+#else
+ Redraw();
+#endif
+ if (moveThumb) {
+ SetVerticalScrollPos();
+ }
+ }
+}
+
+void Editor::ScrollText(int /* linesToMove */) {
+ //Platform::DebugPrintf("Editor::ScrollText %d\n", linesToMove);
+ Redraw();
+}
+
+void Editor::HorizontalScrollTo(int xPos) {
+ //Platform::DebugPrintf("HorizontalScroll %d\n", xPos);
+ if (xPos < 0)
+ xPos = 0;
+ if (!Wrapping() && (xOffset != xPos)) {
+ xOffset = xPos;
+ ContainerNeedsUpdate(SC_UPDATE_H_SCROLL);
+ SetHorizontalScrollPos();
+ RedrawRect(GetClientRectangle());
+ }
+}
+
+void Editor::VerticalCentreCaret() {
+ int lineDoc = pdoc->LineFromPosition(sel.IsRectangular() ? sel.Rectangular().caret.Position() : sel.MainCaret());
+ int lineDisplay = cs.DisplayFromDoc(lineDoc);
+ int newTop = lineDisplay - (LinesOnScreen() / 2);
+ if (topLine != newTop) {
+ SetTopLine(newTop > 0 ? newTop : 0);
+ RedrawRect(GetClientRectangle());
+ }
+}
+
+// Avoid 64 bit compiler warnings.
+// Scintilla does not support text buffers larger than 2**31
+static int istrlen(const char *s) {
+ return static_cast<int>(strlen(s));
+}
+
+void Editor::MoveSelectedLines(int lineDelta) {
+
+ // if selection doesn't start at the beginning of the line, set the new start
+ int selectionStart = SelectionStart().Position();
+ int startLine = pdoc->LineFromPosition(selectionStart);
+ int beginningOfStartLine = pdoc->LineStart(startLine);
+ selectionStart = beginningOfStartLine;
+
+ // if selection doesn't end at the beginning of a line greater than that of the start,
+ // then set it at the beginning of the next one
+ int selectionEnd = SelectionEnd().Position();
+ int endLine = pdoc->LineFromPosition(selectionEnd);
+ int beginningOfEndLine = pdoc->LineStart(endLine);
+ bool appendEol = false;
+ if (selectionEnd > beginningOfEndLine
+ || selectionStart == selectionEnd) {
+ selectionEnd = pdoc->LineStart(endLine + 1);
+ appendEol = (selectionEnd == pdoc->Length() && pdoc->LineFromPosition(selectionEnd) == endLine);
+ }
+
+ // if there's nowhere for the selection to move
+ // (i.e. at the beginning going up or at the end going down),
+ // stop it right there!
+ if ((selectionStart == 0 && lineDelta < 0)
+ || (selectionEnd == pdoc->Length() && lineDelta > 0)
+ || selectionStart == selectionEnd) {
+ return;
+ }
+
+ UndoGroup ug(pdoc);
+
+ if (lineDelta > 0 && selectionEnd == pdoc->LineStart(pdoc->LinesTotal() - 1)) {
+ SetSelection(pdoc->MovePositionOutsideChar(selectionEnd - 1, -1), selectionEnd);
+ ClearSelection();
+ selectionEnd = CurrentPosition();
+ }
+ SetSelection(selectionStart, selectionEnd);
+
+ SelectionText selectedText;
+ CopySelectionRange(&selectedText);
+
+ int selectionLength = SelectionRange(selectionStart, selectionEnd).Length();
+ Point currentLocation = LocationFromPosition(CurrentPosition());
+ int currentLine = LineFromLocation(currentLocation);
+
+ if (appendEol)
+ SetSelection(pdoc->MovePositionOutsideChar(selectionStart - 1, -1), selectionEnd);
+ ClearSelection();
+
+ const char *eol = StringFromEOLMode(pdoc->eolMode);
+ if (currentLine + lineDelta >= pdoc->LinesTotal())
+ pdoc->InsertCString(pdoc->Length(), eol);
+ GoToLine(currentLine + lineDelta);
+
+ pdoc->InsertCString(CurrentPosition(), selectedText.Data());
+ if (appendEol) {
+ pdoc->InsertCString(CurrentPosition() + selectionLength, eol);
+ selectionLength += istrlen(eol);
+ }
+ SetSelection(CurrentPosition(), CurrentPosition() + selectionLength);
+}
+
+void Editor::MoveSelectedLinesUp() {
+ MoveSelectedLines(-1);
+}
+
+void Editor::MoveSelectedLinesDown() {
+ MoveSelectedLines(1);
+}
+
+void Editor::MoveCaretInsideView(bool ensureVisible) {
+ PRectangle rcClient = GetTextRectangle();
+ Point pt = PointMainCaret();
+ if (pt.y < rcClient.top) {
+ MovePositionTo(SPositionFromLocation(
+ Point(lastXChosen - xOffset, rcClient.top),
+ false, false, UserVirtualSpace()),
+ Selection::noSel, ensureVisible);
+ } else if ((pt.y + vs.lineHeight - 1) > rcClient.bottom) {
+ int yOfLastLineFullyDisplayed = rcClient.top + (LinesOnScreen() - 1) * vs.lineHeight;
+ MovePositionTo(SPositionFromLocation(
+ Point(lastXChosen - xOffset, rcClient.top + yOfLastLineFullyDisplayed),
+ false, false, UserVirtualSpace()),
+ Selection::noSel, ensureVisible);
+ }
+}
+
+int Editor::DisplayFromPosition(int pos) {
+ int lineDoc = pdoc->LineFromPosition(pos);
+ int lineDisplay = cs.DisplayFromDoc(lineDoc);
+ AutoSurface surface(this);
+ AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc));
+ if (surface && ll) {
+ LayoutLine(lineDoc, surface, vs, ll, wrapWidth);
+ unsigned int posLineStart = pdoc->LineStart(lineDoc);
+ int posInLine = pos - posLineStart;
+ lineDisplay--; // To make up for first increment ahead.
+ for (int subLine = 0; subLine < ll->lines; subLine++) {
+ if (posInLine >= ll->LineStart(subLine)) {
+ lineDisplay++;
+ }
+ }
+ }
+ return lineDisplay;
+}
+
+/**
+ * Ensure the caret is reasonably visible in context.
+ *
+Caret policy in SciTE
+
+If slop is set, we can define a slop value.
+This value defines an unwanted zone (UZ) where the caret is... unwanted.
+This zone is defined as a number of pixels near the vertical margins,
+and as a number of lines near the horizontal margins.
+By keeping the caret away from the edges, it is seen within its context,
+so it is likely that the identifier that the caret is on can be completely seen,
+and that the current line is seen with some of the lines following it which are
+often dependent on that line.
+
+If strict is set, the policy is enforced... strictly.
+The caret is centred on the display if slop is not set,
+and cannot go in the UZ if slop is set.
+
+If jumps is set, the display is moved more energetically
+so the caret can move in the same direction longer before the policy is applied again.
+'3UZ' notation is used to indicate three time the size of the UZ as a distance to the margin.
+
+If even is not set, instead of having symmetrical UZs,
+the left and bottom UZs are extended up to right and top UZs respectively.
+This way, we favour the displaying of useful information: the begining of lines,
+where most code reside, and the lines after the caret, eg. the body of a function.
+
+ | | | | |
+slop | strict | jumps | even | Caret can go to the margin | When reaching limit (caret going out of
+ | | | | | visibility or going into the UZ) display is...
+-----+--------+-------+------+--------------------------------------------+--------------------------------------------------------------
+ 0 | 0 | 0 | 0 | Yes | moved to put caret on top/on right
+ 0 | 0 | 0 | 1 | Yes | moved by one position
+ 0 | 0 | 1 | 0 | Yes | moved to put caret on top/on right
+ 0 | 0 | 1 | 1 | Yes | centred on the caret
+ 0 | 1 | - | 0 | Caret is always on top/on right of display | -
+ 0 | 1 | - | 1 | No, caret is always centred | -
+ 1 | 0 | 0 | 0 | Yes | moved to put caret out of the asymmetrical UZ
+ 1 | 0 | 0 | 1 | Yes | moved to put caret out of the UZ
+ 1 | 0 | 1 | 0 | Yes | moved to put caret at 3UZ of the top or right margin
+ 1 | 0 | 1 | 1 | Yes | moved to put caret at 3UZ of the margin
+ 1 | 1 | - | 0 | Caret is always at UZ of top/right margin | -
+ 1 | 1 | 0 | 1 | No, kept out of UZ | moved by one position
+ 1 | 1 | 1 | 1 | No, kept out of UZ | moved to put caret at 3UZ of the margin
+*/
+
+Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const SelectionRange range, const XYScrollOptions options) {
+ PRectangle rcClient = GetTextRectangle();
+ Point pt = LocationFromPosition(range.caret);
+ Point ptAnchor = LocationFromPosition(range.anchor);
+ const Point ptOrigin = GetVisibleOriginInMain();
+ pt.x += ptOrigin.x;
+ pt.y += ptOrigin.y;
+ ptAnchor.x += ptOrigin.x;
+ ptAnchor.y += ptOrigin.y;
+ const Point ptBottomCaret(pt.x, pt.y + vs.lineHeight - 1);
+
+ XYScrollPosition newXY(xOffset, topLine);
+ if (rcClient.Empty()) {
+ return newXY;
+ }
+
+ // Vertical positioning
+ if ((options & xysVertical) && (pt.y < rcClient.top || ptBottomCaret.y >= rcClient.bottom || (caretYPolicy & CARET_STRICT) != 0)) {
+ const int lineCaret = DisplayFromPosition(range.caret.Position());
+ const int linesOnScreen = LinesOnScreen();
+ const int halfScreen = Platform::Maximum(linesOnScreen - 1, 2) / 2;
+ const bool bSlop = (caretYPolicy & CARET_SLOP) != 0;
+ const bool bStrict = (caretYPolicy & CARET_STRICT) != 0;
+ const bool bJump = (caretYPolicy & CARET_JUMPS) != 0;
+ const bool bEven = (caretYPolicy & CARET_EVEN) != 0;
+
+ // It should be possible to scroll the window to show the caret,
+ // but this fails to remove the caret on GTK+
+ if (bSlop) { // A margin is defined
+ int yMoveT, yMoveB;
+ if (bStrict) {
+ int yMarginT, yMarginB;
+ if (!(options & xysUseMargin)) {
+ // In drag mode, avoid moves
+ // otherwise, a double click will select several lines.
+ yMarginT = yMarginB = 0;
+ } else {
+ // yMarginT must equal to caretYSlop, with a minimum of 1 and
+ // a maximum of slightly less than half the heigth of the text area.
+ yMarginT = Platform::Clamp(caretYSlop, 1, halfScreen);
+ if (bEven) {
+ yMarginB = yMarginT;
+ } else {
+ yMarginB = linesOnScreen - yMarginT - 1;
+ }
+ }
+ yMoveT = yMarginT;
+ if (bEven) {
+ if (bJump) {
+ yMoveT = Platform::Clamp(caretYSlop * 3, 1, halfScreen);
+ }
+ yMoveB = yMoveT;
+ } else {
+ yMoveB = linesOnScreen - yMoveT - 1;
+ }
+ if (lineCaret < topLine + yMarginT) {
+ // Caret goes too high
+ newXY.topLine = lineCaret - yMoveT;
+ } else if (lineCaret > topLine + linesOnScreen - 1 - yMarginB) {
+ // Caret goes too low
+ newXY.topLine = lineCaret - linesOnScreen + 1 + yMoveB;
+ }
+ } else { // Not strict
+ yMoveT = bJump ? caretYSlop * 3 : caretYSlop;
+ yMoveT = Platform::Clamp(yMoveT, 1, halfScreen);
+ if (bEven) {
+ yMoveB = yMoveT;
+ } else {
+ yMoveB = linesOnScreen - yMoveT - 1;
+ }
+ if (lineCaret < topLine) {
+ // Caret goes too high
+ newXY.topLine = lineCaret - yMoveT;
+ } else if (lineCaret > topLine + linesOnScreen - 1) {
+ // Caret goes too low
+ newXY.topLine = lineCaret - linesOnScreen + 1 + yMoveB;
+ }
+ }
+ } else { // No slop
+ if (!bStrict && !bJump) {
+ // Minimal move
+ if (lineCaret < topLine) {
+ // Caret goes too high
+ newXY.topLine = lineCaret;
+ } else if (lineCaret > topLine + linesOnScreen - 1) {
+ // Caret goes too low
+ if (bEven) {
+ newXY.topLine = lineCaret - linesOnScreen + 1;
+ } else {
+ newXY.topLine = lineCaret;
+ }
+ }
+ } else { // Strict or going out of display
+ if (bEven) {
+ // Always center caret
+ newXY.topLine = lineCaret - halfScreen;
+ } else {
+ // Always put caret on top of display
+ newXY.topLine = lineCaret;
+ }
+ }
+ }
+ if (!(range.caret == range.anchor)) {
+ const int lineAnchor = DisplayFromPosition(range.anchor.Position());
+ if (lineAnchor < lineCaret) {
+ // Shift up to show anchor or as much of range as possible
+ newXY.topLine = std::min(newXY.topLine, lineAnchor);
+ newXY.topLine = std::max(newXY.topLine, lineCaret - LinesOnScreen());
+ } else {
+ // Shift down to show anchor or as much of range as possible
+ newXY.topLine = std::max(newXY.topLine, lineAnchor - LinesOnScreen());
+ newXY.topLine = std::min(newXY.topLine, lineCaret);
+ }
+ }
+ newXY.topLine = Platform::Clamp(newXY.topLine, 0, MaxScrollPos());
+ }
+
+ // Horizontal positioning
+ if ((options & xysHorizontal) && !Wrapping()) {
+ const int halfScreen = Platform::Maximum(rcClient.Width() - 4, 4) / 2;
+ const bool bSlop = (caretXPolicy & CARET_SLOP) != 0;
+ const bool bStrict = (caretXPolicy & CARET_STRICT) != 0;
+ const bool bJump = (caretXPolicy & CARET_JUMPS) != 0;
+ const bool bEven = (caretXPolicy & CARET_EVEN) != 0;
+
+ if (bSlop) { // A margin is defined
+ int xMoveL, xMoveR;
+ if (bStrict) {
+ int xMarginL, xMarginR;
+ if (!(options & xysUseMargin)) {
+ // In drag mode, avoid moves unless very near of the margin
+ // otherwise, a simple click will select text.
+ xMarginL = xMarginR = 2;
+ } else {
+ // xMargin must equal to caretXSlop, with a minimum of 2 and
+ // a maximum of slightly less than half the width of the text area.
+ xMarginR = Platform::Clamp(caretXSlop, 2, halfScreen);
+ if (bEven) {
+ xMarginL = xMarginR;
+ } else {
+ xMarginL = rcClient.Width() - xMarginR - 4;
+ }
+ }
+ if (bJump && bEven) {
+ // Jump is used only in even mode
+ xMoveL = xMoveR = Platform::Clamp(caretXSlop * 3, 1, halfScreen);
+ } else {
+ xMoveL = xMoveR = 0; // Not used, avoid a warning
+ }
+ if (pt.x < rcClient.left + xMarginL) {
+ // Caret is on the left of the display
+ if (bJump && bEven) {
+ newXY.xOffset -= xMoveL;
+ } else {
+ // Move just enough to allow to display the caret
+ newXY.xOffset -= (rcClient.left + xMarginL) - pt.x;
+ }
+ } else if (pt.x >= rcClient.right - xMarginR) {
+ // Caret is on the right of the display
+ if (bJump && bEven) {
+ newXY.xOffset += xMoveR;
+ } else {
+ // Move just enough to allow to display the caret
+ newXY.xOffset += pt.x - (rcClient.right - xMarginR) + 1;
+ }
+ }
+ } else { // Not strict
+ xMoveR = bJump ? caretXSlop * 3 : caretXSlop;
+ xMoveR = Platform::Clamp(xMoveR, 1, halfScreen);
+ if (bEven) {
+ xMoveL = xMoveR;
+ } else {
+ xMoveL = rcClient.Width() - xMoveR - 4;
+ }
+ if (pt.x < rcClient.left) {
+ // Caret is on the left of the display
+ newXY.xOffset -= xMoveL;
+ } else if (pt.x >= rcClient.right) {
+ // Caret is on the right of the display
+ newXY.xOffset += xMoveR;
+ }
+ }
+ } else { // No slop
+ if (bStrict ||
+ (bJump && (pt.x < rcClient.left || pt.x >= rcClient.right))) {
+ // Strict or going out of display
+ if (bEven) {
+ // Center caret
+ newXY.xOffset += pt.x - rcClient.left - halfScreen;
+ } else {
+ // Put caret on right
+ newXY.xOffset += pt.x - rcClient.right + 1;
+ }
+ } else {
+ // Move just enough to allow to display the caret
+ if (pt.x < rcClient.left) {
+ // Caret is on the left of the display
+ if (bEven) {
+ newXY.xOffset -= rcClient.left - pt.x;
+ } else {
+ newXY.xOffset += pt.x - rcClient.right + 1;
+ }
+ } else if (pt.x >= rcClient.right) {
+ // Caret is on the right of the display
+ newXY.xOffset += pt.x - rcClient.right + 1;
+ }
+ }
+ }
+ // In case of a jump (find result) largely out of display, adjust the offset to display the caret
+ if (pt.x + xOffset < rcClient.left + newXY.xOffset) {
+ newXY.xOffset = pt.x + xOffset - rcClient.left;
+ } else if (pt.x + xOffset >= rcClient.right + newXY.xOffset) {
+ newXY.xOffset = pt.x + xOffset - rcClient.right + 1;
+ if (vs.caretStyle == CARETSTYLE_BLOCK) {
+ // Ensure we can see a good portion of the block caret
+ newXY.xOffset += static_cast<int>(vs.aveCharWidth);
+ }
+ }
+ if (!(range.caret == range.anchor)) {
+ if (ptAnchor.x < pt.x) {
+ // Shift to left to show anchor or as much of range as possible
+ int maxOffset = ptAnchor.x + xOffset - rcClient.left - 1;
+ int minOffset = pt.x + xOffset - rcClient.right + 1;
+ newXY.xOffset = std::min(newXY.xOffset, maxOffset);
+ newXY.xOffset = std::max(newXY.xOffset, minOffset);
+ } else {
+ // Shift to right to show anchor or as much of range as possible
+ int minOffset = ptAnchor.x + xOffset - rcClient.right + 1;
+ int maxOffset = pt.x + xOffset - rcClient.left - 1;
+ newXY.xOffset = std::max(newXY.xOffset, minOffset);
+ newXY.xOffset = std::min(newXY.xOffset, maxOffset);
+ }
+ }
+ if (newXY.xOffset < 0) {
+ newXY.xOffset = 0;
+ }
+ }
+
+ return newXY;
+}
+
+void Editor::SetXYScroll(XYScrollPosition newXY) {
+ if ((newXY.topLine != topLine) || (newXY.xOffset != xOffset)) {
+ if (newXY.topLine != topLine) {
+ SetTopLine(newXY.topLine);
+ SetVerticalScrollPos();
+ }
+ if (newXY.xOffset != xOffset) {
+ xOffset = newXY.xOffset;
+ ContainerNeedsUpdate(SC_UPDATE_H_SCROLL);
+ if (newXY.xOffset > 0) {
+ PRectangle rcText = GetTextRectangle();
+ if (horizontalScrollBarVisible &&
+ rcText.Width() + xOffset > scrollWidth) {
+ scrollWidth = xOffset + rcText.Width();
+ SetScrollBars();
+ }
+ }
+ SetHorizontalScrollPos();
+ }
+ Redraw();
+ UpdateSystemCaret();
+ }
+}
+
+void Editor::ScrollRange(SelectionRange range) {
+ SetXYScroll(XYScrollToMakeVisible(range, xysDefault));
+}
+
+void Editor::EnsureCaretVisible(bool useMargin, bool vert, bool horiz) {
+ SetXYScroll(XYScrollToMakeVisible(SelectionRange(posDrag.IsValid() ? posDrag : sel.RangeMain().caret),
+ static_cast<XYScrollOptions>((useMargin?xysUseMargin:0)|(vert?xysVertical:0)|(horiz?xysHorizontal:0))));
+}
+
+void Editor::ShowCaretAtCurrentPosition() {
+ if (hasFocus) {
+ caret.active = true;
+ caret.on = true;
+ SetTicking(true);
+ } else {
+ caret.active = false;
+ caret.on = false;
+ }
+ InvalidateCaret();
+}
+
+void Editor::DropCaret() {
+ caret.active = false;
+ InvalidateCaret();
+}
+
+void Editor::InvalidateCaret() {
+ if (posDrag.IsValid()) {
+ InvalidateRange(posDrag.Position(), posDrag.Position() + 1);
+ } else {
+ for (size_t r=0; r<sel.Count(); r++) {
+ InvalidateRange(sel.Range(r).caret.Position(), sel.Range(r).caret.Position() + 1);
+ }
+ }
+ UpdateSystemCaret();
+}
+
+void Editor::UpdateSystemCaret() {
+}
+
+bool Editor::Wrapping() const {
+ return vs.wrapState != eWrapNone;
+}
+
+void Editor::NeedWrapping(int docLineStart, int docLineEnd) {
+//Platform::DebugPrintf("\nNeedWrapping: %0d..%0d\n", docLineStart, docLineEnd);
+ if (wrapPending.AddRange(docLineStart, docLineEnd)) {
+ llc.Invalidate(LineLayout::llPositions);
+ }
+ // Wrap lines during idle.
+ if (Wrapping() && wrapPending.NeedsWrap()) {
+ SetIdle(true);
+ }
+}
+
+bool Editor::WrapOneLine(Surface *surface, int lineToWrap) {
+ AutoLineLayout ll(llc, RetrieveLineLayout(lineToWrap));
+ int linesWrapped = 1;
+ if (ll) {
+ LayoutLine(lineToWrap, surface, vs, ll, wrapWidth);
+ linesWrapped = ll->lines;
+ }
+ return cs.SetHeight(lineToWrap, linesWrapped +
+ (vs.annotationVisible ? pdoc->AnnotationLines(lineToWrap) : 0));
+}
+
+// Perform wrapping for a subset of the lines needing wrapping.
+// wsAll: wrap all lines which need wrapping in this single call
+// wsVisible: wrap currently visible lines
+// wsIdle: wrap one page + 100 lines
+// Return true if wrapping occurred.
+bool Editor::WrapLines(enum wrapScope ws) {
+ int goodTopLine = topLine;
+ bool wrapOccurred = false;
+ if (!Wrapping()) {
+ if (wrapWidth != LineLayout::wrapWidthInfinite) {
+ wrapWidth = LineLayout::wrapWidthInfinite;
+ for (int lineDoc = 0; lineDoc < pdoc->LinesTotal(); lineDoc++) {
+ cs.SetHeight(lineDoc, 1 +
+ (vs.annotationVisible ? pdoc->AnnotationLines(lineDoc) : 0));
+ }
+ wrapOccurred = true;
+ }
+ wrapPending.Reset();
+
+ } else if (wrapPending.NeedsWrap()) {
+ wrapPending.start = std::min(wrapPending.start, pdoc->LinesTotal());
+ if (!SetIdle(true)) {
+ // Idle processing not supported so full wrap required.
+ ws = wsAll;
+ }
+ // Decide where to start wrapping
+ int lineToWrap = wrapPending.start;
+ int lineToWrapEnd = std::min(wrapPending.end, pdoc->LinesTotal());
+ const int lineDocTop = cs.DocFromDisplay(topLine);
+ const int subLineTop = topLine - cs.DisplayFromDoc(lineDocTop);
+ if (ws == wsVisible) {
+ lineToWrap = Platform::Clamp(lineDocTop-5, wrapPending.start, pdoc->LinesTotal());
+ // Priority wrap to just after visible area.
+ // Since wrapping could reduce display lines, treat each
+ // as taking only one display line.
+ lineToWrapEnd = lineDocTop;
+ int lines = LinesOnScreen() + 1;
+ while ((lineToWrapEnd < cs.LinesInDoc()) && (lines>0)) {
+ if (cs.GetVisible(lineToWrapEnd))
+ lines--;
+ lineToWrapEnd++;
+ }
+ // .. and if the paint window is outside pending wraps
+ if ((lineToWrap > wrapPending.end) || (lineToWrapEnd < wrapPending.start)) {
+ // Currently visible text does not need wrapping
+ return false;
+ }
+ } else if (ws == wsIdle) {
+ lineToWrapEnd = lineToWrap + LinesOnScreen() + 100;
+ }
+ const int lineEndNeedWrap = std::min(wrapPending.end, pdoc->LinesTotal());
+ lineToWrapEnd = std::min(lineToWrapEnd, lineEndNeedWrap);
+
+ // Ensure all lines being wrapped are styled.
+ pdoc->EnsureStyledTo(pdoc->LineStart(lineToWrapEnd));
+
+ if (lineToWrap < lineToWrapEnd) {
+
+ PRectangle rcTextArea = GetClientRectangle();
+ rcTextArea.left = vs.textStart;
+ rcTextArea.right -= vs.rightMarginWidth;
+ wrapWidth = rcTextArea.Width();
+ RefreshStyleData();
+ AutoSurface surface(this);
+ if (surface) {
+//Platform::DebugPrintf("Wraplines: scope=%0d need=%0d..%0d perform=%0d..%0d\n", ws, wrapPending.start, wrapPending.end, lineToWrap, lineToWrapEnd);
+
+ while (lineToWrap < lineToWrapEnd) {
+ if (WrapOneLine(surface, lineToWrap)) {
+ wrapOccurred = true;
+ }
+ wrapPending.Wrapped(lineToWrap);
+ lineToWrap++;
+ }
+
+ goodTopLine = cs.DisplayFromDoc(lineDocTop) + std::min(subLineTop, cs.GetHeight(lineDocTop)-1);
+ }
+ }
+
+ // If wrapping is done, bring it to resting position
+ if (wrapPending.start >= lineEndNeedWrap) {
+ wrapPending.Reset();
+ }
+ }
+
+ if (wrapOccurred) {
+ SetScrollBars();
+ SetTopLine(Platform::Clamp(goodTopLine, 0, MaxScrollPos()));
+ SetVerticalScrollPos();
+ }
+
+ return wrapOccurred;
+}
+
+void Editor::LinesJoin() {
+ if (!RangeContainsProtected(targetStart, targetEnd)) {
+ UndoGroup ug(pdoc);
+ bool prevNonWS = true;
+ for (int pos = targetStart; pos < targetEnd; pos++) {
+ if (pdoc->IsPositionInLineEnd(pos)) {
+ targetEnd -= pdoc->LenChar(pos);
+ pdoc->DelChar(pos);
+ if (prevNonWS) {
+ // Ensure at least one space separating previous lines
+ pdoc->InsertChar(pos, ' ');
+ targetEnd++;
+ }
+ } else {
+ prevNonWS = pdoc->CharAt(pos) != ' ';
+ }
+ }
+ }
+}
+
+const char *Editor::StringFromEOLMode(int eolMode) {
+ if (eolMode == SC_EOL_CRLF) {
+ return "\r\n";
+ } else if (eolMode == SC_EOL_CR) {
+ return "\r";
+ } else {
+ return "\n";
+ }
+}
+
+void Editor::LinesSplit(int pixelWidth) {
+ if (!RangeContainsProtected(targetStart, targetEnd)) {
+ if (pixelWidth == 0) {
+ PRectangle rcText = GetTextRectangle();
+ pixelWidth = rcText.Width();
+ }
+ int lineStart = pdoc->LineFromPosition(targetStart);
+ int lineEnd = pdoc->LineFromPosition(targetEnd);
+ const char *eol = StringFromEOLMode(pdoc->eolMode);
+ UndoGroup ug(pdoc);
+ for (int line = lineStart; line <= lineEnd; line++) {
+ AutoSurface surface(this);
+ AutoLineLayout ll(llc, RetrieveLineLayout(line));
+ if (surface && ll) {
+ unsigned int posLineStart = pdoc->LineStart(line);
+ LayoutLine(line, surface, vs, ll, pixelWidth);
+ for (int subLine = 1; subLine < ll->lines; subLine++) {
+ pdoc->InsertCString(
+ static_cast<int>(posLineStart + (subLine - 1) * strlen(eol) +
+ ll->LineStart(subLine)),
+ eol);
+ targetEnd += static_cast<int>(strlen(eol));
+ }
+ }
+ lineEnd = pdoc->LineFromPosition(targetEnd);
+ }
+ }
+}
+
+int Editor::SubstituteMarkerIfEmpty(int markerCheck, int markerDefault) const {
+ if (vs.markers[markerCheck].markType == SC_MARK_EMPTY)
+ return markerDefault;
+ return markerCheck;
+}
+
+bool ValidStyledText(ViewStyle &vs, size_t styleOffset, const StyledText &st) {
+ if (st.multipleStyles) {
+ for (size_t iStyle=0; iStyle<st.length; iStyle++) {
+ if (!vs.ValidStyle(styleOffset + st.styles[iStyle]))
+ return false;
+ }
+ } else {
+ if (!vs.ValidStyle(styleOffset + st.style))
+ return false;
+ }
+ return true;
+}
+
+static int WidthStyledText(Surface *surface, ViewStyle &vs, int styleOffset,
+ const char *text, const unsigned char *styles, size_t len) {
+ int width = 0;
+ size_t start = 0;
+ while (start < len) {
+ size_t style = styles[start];
+ size_t endSegment = start;
+ while ((endSegment+1 < len) && (static_cast<size_t>(styles[endSegment+1]) == style))
+ endSegment++;
+ width += surface->WidthText(vs.styles[style+styleOffset].font, text + start,
+ static_cast<int>(endSegment - start + 1));
+ start = endSegment + 1;
+ }
+ return width;
+}
+
+static int WidestLineWidth(Surface *surface, ViewStyle &vs, int styleOffset, const StyledText &st) {
+ int widthMax = 0;
+ size_t start = 0;
+ while (start < st.length) {
+ size_t lenLine = st.LineLength(start);
+ int widthSubLine;
+ if (st.multipleStyles) {
+ widthSubLine = WidthStyledText(surface, vs, styleOffset, st.text + start, st.styles + start, lenLine);
+ } else {
+ widthSubLine = surface->WidthText(vs.styles[styleOffset + st.style].font,
+ st.text + start, static_cast<int>(lenLine));
+ }
+ if (widthSubLine > widthMax)
+ widthMax = widthSubLine;
+ start += lenLine + 1;
+ }
+ return widthMax;
+}
+
+void DrawStyledText(Surface *surface, ViewStyle &vs, int styleOffset, PRectangle rcText, int ascent,
+ const StyledText &st, size_t start, size_t length) {
+
+ if (st.multipleStyles) {
+ int x = rcText.left;
+ size_t i = 0;
+ while (i < length) {
+ size_t end = i;
+ int style = st.styles[i + start];
+ while (end < length-1 && st.styles[start+end+1] == style)
+ end++;
+ style += styleOffset;
+ int width = surface->WidthText(vs.styles[style].font,
+ st.text + start + i, static_cast<int>(end - i + 1));
+ PRectangle rcSegment = rcText;
+ rcSegment.left = x;
+ rcSegment.right = x + width + 1;
+ surface->DrawTextNoClip(rcSegment, vs.styles[style].font,
+ ascent, st.text + start + i,
+ static_cast<int>(end - i + 1),
+ vs.styles[style].fore,
+ vs.styles[style].back);
+ x += width;
+ i = end + 1;
+ }
+ } else {
+ size_t style = st.style + styleOffset;
+ surface->DrawTextNoClip(rcText, vs.styles[style].font,
+ rcText.top + vs.maxAscent, st.text + start,
+ static_cast<int>(length),
+ vs.styles[style].fore,
+ vs.styles[style].back);
+ }
+}
+
+void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) {
+ if (vs.fixedColumnWidth == 0)
+ return;
+
+ AllocateGraphics();
+ RefreshStyleData();
+ RefreshPixMaps(surfWindow);
+
+ PRectangle rcMargin = GetClientRectangle();
+ Point ptOrigin = GetVisibleOriginInMain();
+ rcMargin.Move(0, -ptOrigin.y);
+ rcMargin.left = 0;
+ rcMargin.right = vs.fixedColumnWidth;
+
+ if (!rc.Intersects(rcMargin))
+ return;
+
+ Surface *surface;
+ if (bufferedDraw) {
+ surface = pixmapSelMargin;
+ } else {
+ surface = surfWindow;
+ }
+
+ // Clip vertically to paint area to avoid drawing line numbers
+ if (rcMargin.bottom > rc.bottom)
+ rcMargin.bottom = rc.bottom;
+ if (rcMargin.top < rc.top)
+ rcMargin.top = rc.top;
+
+ PRectangle rcSelMargin = rcMargin;
+ rcSelMargin.right = rcMargin.left;
+ if (rcSelMargin.bottom < rc.bottom)
+ rcSelMargin.bottom = rc.bottom;
+
+ for (int margin = 0; margin <= SC_MAX_MARGIN; margin++) {
+ if (vs.ms[margin].width > 0) {
+
+ rcSelMargin.left = rcSelMargin.right;
+ rcSelMargin.right = rcSelMargin.left + vs.ms[margin].width;
+
+ if (vs.ms[margin].style != SC_MARGIN_NUMBER) {
+ if (vs.ms[margin].mask & SC_MASK_FOLDERS) {
+ // Required because of special way brush is created for selection margin
+ // Ensure patterns line up when scrolling with separate margin view
+ // by choosing correctly aligned variant.
+ bool invertPhase = static_cast<int>(ptOrigin.y) & 1;
+ surface->FillRectangle(rcSelMargin,
+ invertPhase ? *pixmapSelPattern : *pixmapSelPatternOffset1);
+ } else {
+ ColourDesired colour;
+ switch (vs.ms[margin].style) {
+ case SC_MARGIN_BACK:
+ colour = vs.styles[STYLE_DEFAULT].back;
+ break;
+ case SC_MARGIN_FORE:
+ colour = vs.styles[STYLE_DEFAULT].fore;
+ break;
+ default:
+ colour = vs.styles[STYLE_LINENUMBER].back;
+ break;
+ }
+ surface->FillRectangle(rcSelMargin, colour);
+ }
+ } else {
+ surface->FillRectangle(rcSelMargin, vs.styles[STYLE_LINENUMBER].back);
+ }
+
+ const int lineStartPaint = (rcMargin.top + ptOrigin.y) / vs.lineHeight;
+ int visibleLine = TopLineOfMain() + lineStartPaint;
+ int yposScreen = lineStartPaint * vs.lineHeight - ptOrigin.y;
+ // Work out whether the top line is whitespace located after a
+ // lessening of fold level which implies a 'fold tail' but which should not
+ // be displayed until the last of a sequence of whitespace.
+ bool needWhiteClosure = false;
+ if (vs.ms[margin].mask & SC_MASK_FOLDERS) {
+ int level = pdoc->GetLevel(cs.DocFromDisplay(visibleLine));
+ if (level & SC_FOLDLEVELWHITEFLAG) {
+ int lineBack = cs.DocFromDisplay(visibleLine);
+ int levelPrev = level;
+ while ((lineBack > 0) && (levelPrev & SC_FOLDLEVELWHITEFLAG)) {
+ lineBack--;
+ levelPrev = pdoc->GetLevel(lineBack);
+ }
+ if (!(levelPrev & SC_FOLDLEVELHEADERFLAG)) {
+ if ((level & SC_FOLDLEVELNUMBERMASK) < (levelPrev & SC_FOLDLEVELNUMBERMASK))
+ needWhiteClosure = true;
+ }
+ }
+ if (highlightDelimiter.isEnabled) {
+ int lastLine = cs.DocFromDisplay(topLine + LinesOnScreen()) + 1;
+ pdoc->GetHighlightDelimiters(highlightDelimiter, pdoc->LineFromPosition(CurrentPosition()), lastLine);
+ }
+ }
+
+ // Old code does not know about new markers needed to distinguish all cases
+ int folderOpenMid = SubstituteMarkerIfEmpty(SC_MARKNUM_FOLDEROPENMID,
+ SC_MARKNUM_FOLDEROPEN);
+ int folderEnd = SubstituteMarkerIfEmpty(SC_MARKNUM_FOLDEREND,
+ SC_MARKNUM_FOLDER);
+
+ while ((visibleLine < cs.LinesDisplayed()) && yposScreen < rc.bottom) {
+
+ PLATFORM_ASSERT(visibleLine < cs.LinesDisplayed());
+ int lineDoc = cs.DocFromDisplay(visibleLine);
+ PLATFORM_ASSERT(cs.GetVisible(lineDoc));
+ bool firstSubLine = visibleLine == cs.DisplayFromDoc(lineDoc);
+ bool lastSubLine = visibleLine == (cs.DisplayFromDoc(lineDoc + 1) - 1);
+
+ int marks = pdoc->GetMark(lineDoc);
+ if (!firstSubLine)
+ marks = 0;
+
+ bool headWithTail = false;
+
+ if (vs.ms[margin].mask & SC_MASK_FOLDERS) {
+ // Decide which fold indicator should be displayed
+ int level = pdoc->GetLevel(lineDoc);
+ int levelNext = pdoc->GetLevel(lineDoc + 1);
+ int levelNum = level & SC_FOLDLEVELNUMBERMASK;
+ int levelNextNum = levelNext & SC_FOLDLEVELNUMBERMASK;
+ if (level & SC_FOLDLEVELHEADERFLAG) {
+ if (firstSubLine) {
+ if (levelNum < levelNextNum) {
+ if (cs.GetExpanded(lineDoc)) {
+ if (levelNum == SC_FOLDLEVELBASE)
+ marks |= 1 << SC_MARKNUM_FOLDEROPEN;
+ else
+ marks |= 1 << folderOpenMid;
+ } else {
+ if (levelNum == SC_FOLDLEVELBASE)
+ marks |= 1 << SC_MARKNUM_FOLDER;
+ else
+ marks |= 1 << folderEnd;
+ }
+ } else if (levelNum > SC_FOLDLEVELBASE) {
+ marks |= 1 << SC_MARKNUM_FOLDERSUB;
+ }
+ } else {
+ if (levelNum < levelNextNum) {
+ if (cs.GetExpanded(lineDoc)) {
+ marks |= 1 << SC_MARKNUM_FOLDERSUB;
+ } else if (levelNum > SC_FOLDLEVELBASE) {
+ marks |= 1 << SC_MARKNUM_FOLDERSUB;
+ }
+ } else if (levelNum > SC_FOLDLEVELBASE) {
+ marks |= 1 << SC_MARKNUM_FOLDERSUB;
+ }
+ }
+ needWhiteClosure = false;
+ int firstFollowupLine = cs.DocFromDisplay(cs.DisplayFromDoc(lineDoc + 1));
+ int firstFollowupLineLevel = pdoc->GetLevel(firstFollowupLine);
+ int secondFollowupLineLevelNum = pdoc->GetLevel(firstFollowupLine + 1) & SC_FOLDLEVELNUMBERMASK;
+ if (!cs.GetExpanded(lineDoc)) {
+ if ((firstFollowupLineLevel & SC_FOLDLEVELWHITEFLAG) &&
+ (levelNum > secondFollowupLineLevelNum))
+ needWhiteClosure = true;
+
+ if (highlightDelimiter.IsFoldBlockHighlighted(firstFollowupLine))
+ headWithTail = true;
+ }
+ } else if (level & SC_FOLDLEVELWHITEFLAG) {
+ if (needWhiteClosure) {
+ if (levelNext & SC_FOLDLEVELWHITEFLAG) {
+ marks |= 1 << SC_MARKNUM_FOLDERSUB;
+ } else if (levelNextNum > SC_FOLDLEVELBASE) {
+ marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL;
+ needWhiteClosure = false;
+ } else {
+ marks |= 1 << SC_MARKNUM_FOLDERTAIL;
+ needWhiteClosure = false;
+ }
+ } else if (levelNum > SC_FOLDLEVELBASE) {
+ if (levelNextNum < levelNum) {
+ if (levelNextNum > SC_FOLDLEVELBASE) {
+ marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL;
+ } else {
+ marks |= 1 << SC_MARKNUM_FOLDERTAIL;
+ }
+ } else {
+ marks |= 1 << SC_MARKNUM_FOLDERSUB;
+ }
+ }
+ } else if (levelNum > SC_FOLDLEVELBASE) {
+ if (levelNextNum < levelNum) {
+ needWhiteClosure = false;
+ if (levelNext & SC_FOLDLEVELWHITEFLAG) {
+ marks |= 1 << SC_MARKNUM_FOLDERSUB;
+ needWhiteClosure = true;
+ } else if (lastSubLine) {
+ if (levelNextNum > SC_FOLDLEVELBASE) {
+ marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL;
+ } else {
+ marks |= 1 << SC_MARKNUM_FOLDERTAIL;
+ }
+ } else {
+ marks |= 1 << SC_MARKNUM_FOLDERSUB;
+ }
+ } else {
+ marks |= 1 << SC_MARKNUM_FOLDERSUB;
+ }
+ }
+ }
+
+ marks &= vs.ms[margin].mask;
+
+ PRectangle rcMarker = rcSelMargin;
+ rcMarker.top = yposScreen;
+ rcMarker.bottom = yposScreen + vs.lineHeight;
+ if (vs.ms[margin].style == SC_MARGIN_NUMBER) {
+ if (firstSubLine) {
+ char number[100] = "";
+ if (lineDoc >= 0)
+ sprintf(number, "%d", lineDoc + 1);
+ if (foldFlags & SC_FOLDFLAG_LEVELNUMBERS) {
+ int lev = pdoc->GetLevel(lineDoc);
+ sprintf(number, "%c%c %03X %03X",
+ (lev & SC_FOLDLEVELHEADERFLAG) ? 'H' : '_',
+ (lev & SC_FOLDLEVELWHITEFLAG) ? 'W' : '_',
+ lev & SC_FOLDLEVELNUMBERMASK,
+ lev >> 16
+ );
+ }
+ PRectangle rcNumber = rcMarker;
+ // Right justify
+ XYPOSITION width = surface->WidthText(vs.styles[STYLE_LINENUMBER].font, number, istrlen(number));
+ XYPOSITION xpos = rcNumber.right - width - vs.marginNumberPadding;
+ rcNumber.left = xpos;
+ surface->DrawTextNoClip(rcNumber, vs.styles[STYLE_LINENUMBER].font,
+ rcNumber.top + vs.maxAscent, number, istrlen(number),
+ vs.styles[STYLE_LINENUMBER].fore,
+ vs.styles[STYLE_LINENUMBER].back);
+ } else if (vs.wrapVisualFlags & SC_WRAPVISUALFLAG_MARGIN) {
+ PRectangle rcWrapMarker = rcMarker;
+ rcWrapMarker.right -= 3;
+ rcWrapMarker.left = rcWrapMarker.right - vs.styles[STYLE_LINENUMBER].aveCharWidth;
+ DrawWrapMarker(surface, rcWrapMarker, false, vs.styles[STYLE_LINENUMBER].fore);
+ }
+ } else if (vs.ms[margin].style == SC_MARGIN_TEXT || vs.ms[margin].style == SC_MARGIN_RTEXT) {
+ if (firstSubLine) {
+ const StyledText stMargin = pdoc->MarginStyledText(lineDoc);
+ if (stMargin.text && ValidStyledText(vs, vs.marginStyleOffset, stMargin)) {
+ surface->FillRectangle(rcMarker,
+ vs.styles[stMargin.StyleAt(0)+vs.marginStyleOffset].back);
+ if (vs.ms[margin].style == SC_MARGIN_RTEXT) {
+ int width = WidestLineWidth(surface, vs, vs.marginStyleOffset, stMargin);
+ rcMarker.left = rcMarker.right - width - 3;
+ }
+ DrawStyledText(surface, vs, vs.marginStyleOffset, rcMarker, rcMarker.top + vs.maxAscent,
+ stMargin, 0, stMargin.length);
+ }
+ }
+ }
+
+ if (marks) {
+ for (int markBit = 0; (markBit < 32) && marks; markBit++) {
+ if (marks & 1) {
+ LineMarker::typeOfFold tFold = LineMarker::undefined;
+ if ((vs.ms[margin].mask & SC_MASK_FOLDERS) && highlightDelimiter.IsFoldBlockHighlighted(lineDoc)) {
+ if (highlightDelimiter.IsBodyOfFoldBlock(lineDoc)) {
+ tFold = LineMarker::body;
+ } else if (highlightDelimiter.IsHeadOfFoldBlock(lineDoc)) {
+ if (firstSubLine) {
+ tFold = headWithTail ? LineMarker::headWithTail : LineMarker::head;
+ } else {
+ if (cs.GetExpanded(lineDoc) || headWithTail) {
+ tFold = LineMarker::body;
+ } else {
+ tFold = LineMarker::undefined;
+ }
+ }
+ } else if (highlightDelimiter.IsTailOfFoldBlock(lineDoc)) {
+ tFold = LineMarker::tail;
+ }
+ }
+ vs.markers[markBit].Draw(surface, rcMarker, vs.styles[STYLE_LINENUMBER].font, tFold, vs.ms[margin].style);
+ }
+ marks >>= 1;
+ }
+ }
+
+ visibleLine++;
+ yposScreen += vs.lineHeight;
+ }
+ }
+ }
+
+ PRectangle rcBlankMargin = rcMargin;
+ rcBlankMargin.left = rcSelMargin.right;
+ surface->FillRectangle(rcBlankMargin, vs.styles[STYLE_DEFAULT].back);
+
+ if (bufferedDraw) {
+ surfWindow->Copy(rcMargin, Point(rcMargin.left, rcMargin.top), *pixmapSelMargin);
+ }
+}
+
+void DrawTabArrow(Surface *surface, PRectangle rcTab, int ymid) {
+ int ydiff = (rcTab.bottom - rcTab.top) / 2;
+ int xhead = rcTab.right - 1 - ydiff;
+ if (xhead <= rcTab.left) {
+ ydiff -= rcTab.left - xhead - 1;
+ xhead = rcTab.left - 1;
+ }
+ if ((rcTab.left + 2) < (rcTab.right - 1))
+ surface->MoveTo(rcTab.left + 2, ymid);
+ else
+ surface->MoveTo(rcTab.right - 1, ymid);
+ surface->LineTo(rcTab.right - 1, ymid);
+ surface->LineTo(xhead, ymid - ydiff);
+ surface->MoveTo(rcTab.right - 1, ymid);
+ surface->LineTo(xhead, ymid + ydiff);
+}
+
+LineLayout *Editor::RetrieveLineLayout(int lineNumber) {
+ int posLineStart = pdoc->LineStart(lineNumber);
+ int posLineEnd = pdoc->LineStart(lineNumber + 1);
+ PLATFORM_ASSERT(posLineEnd >= posLineStart);
+ int lineCaret = pdoc->LineFromPosition(sel.MainCaret());
+ return llc.Retrieve(lineNumber, lineCaret,
+ posLineEnd - posLineStart, pdoc->GetStyleClock(),
+ LinesOnScreen() + 1, pdoc->LinesTotal());
+}
+
+/**
+ * Fill in the LineLayout data for the given line.
+ * Copy the given @a line and its styles from the document into local arrays.
+ * Also determine the x position at which each character starts.
+ */
+void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayout *ll, int width) {
+//void LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayout *ll, int width, Document *pdoc, PositionCache &posCache, SpecialRepresentations &reprs) {
+ if (!ll)
+ return;
+
+ PLATFORM_ASSERT(line < pdoc->LinesTotal());
+ PLATFORM_ASSERT(ll->chars != NULL);
+ int posLineStart = pdoc->LineStart(line);
+ int posLineEnd = pdoc->LineStart(line + 1);
+ // If the line is very long, limit the treatment to a length that should fit in the viewport
+ if (posLineEnd > (posLineStart + ll->maxLineLength)) {
+ posLineEnd = posLineStart + ll->maxLineLength;
+ }
+ if (ll->validity == LineLayout::llCheckTextAndStyle) {
+ int lineLength = posLineEnd - posLineStart;
+ if (!vstyle.viewEOL) {
+ lineLength = pdoc->LineEnd(line) - posLineStart;
+ }
+ if (lineLength == ll->numCharsInLine) {
+ // See if chars, styles, indicators, are all the same
+ bool allSame = true;
+ const int styleMask = pdoc->stylingBitsMask;
+ // Check base line layout
+ char styleByte = 0;
+ int numCharsInLine = 0;
+ while (numCharsInLine < lineLength) {
+ int charInDoc = numCharsInLine + posLineStart;
+ char chDoc = pdoc->CharAt(charInDoc);
+ styleByte = pdoc->StyleAt(charInDoc);
+ allSame = allSame &&
+ (ll->styles[numCharsInLine] == static_cast<unsigned char>(styleByte & styleMask));
+ allSame = allSame &&
+ (ll->indicators[numCharsInLine] == static_cast<char>(styleByte & ~styleMask));
+ if (vstyle.styles[ll->styles[numCharsInLine]].caseForce == Style::caseMixed)
+ allSame = allSame &&
+ (ll->chars[numCharsInLine] == chDoc);
+ else if (vstyle.styles[ll->styles[numCharsInLine]].caseForce == Style::caseLower)
+ allSame = allSame &&
+ (ll->chars[numCharsInLine] == static_cast<char>(tolower(chDoc)));
+ else // Style::caseUpper
+ allSame = allSame &&
+ (ll->chars[numCharsInLine] == static_cast<char>(toupper(chDoc)));
+ numCharsInLine++;
+ }
+ allSame = allSame && (ll->styles[numCharsInLine] == styleByte); // For eolFilled
+ if (allSame) {
+ ll->validity = LineLayout::llPositions;
+ } else {
+ ll->validity = LineLayout::llInvalid;
+ }
+ } else {
+ ll->validity = LineLayout::llInvalid;
+ }
+ }
+ if (ll->validity == LineLayout::llInvalid) {
+ ll->widthLine = LineLayout::wrapWidthInfinite;
+ ll->lines = 1;
+ if (vstyle.edgeState == EDGE_BACKGROUND) {
+ ll->edgeColumn = pdoc->FindColumn(line, vstyle.theEdge);
+ if (ll->edgeColumn >= posLineStart) {
+ ll->edgeColumn -= posLineStart;
+ }
+ } else {
+ ll->edgeColumn = -1;
+ }
+
+ char styleByte;
+ const int styleMask = pdoc->stylingBitsMask;
+ ll->styleBitsSet = 0;
+ // Fill base line layout
+ const int lineLength = posLineEnd - posLineStart;
+ pdoc->GetCharRange(ll->chars, posLineStart, lineLength);
+ pdoc->GetStyleRange(ll->styles, posLineStart, lineLength);
+ int numCharsBeforeEOL = pdoc->LineEnd(line) - posLineStart;
+ const int numCharsInLine = (vstyle.viewEOL) ? lineLength : numCharsBeforeEOL;
+ for (int styleInLine = 0; styleInLine < numCharsInLine; styleInLine++) {
+ styleByte = ll->styles[styleInLine];
+ ll->styleBitsSet |= styleByte;
+ ll->styles[styleInLine] = static_cast<char>(styleByte & styleMask);
+ ll->indicators[styleInLine] = static_cast<char>(styleByte & ~styleMask);
+ }
+ styleByte = static_cast<char>(((lineLength > 0) ? ll->styles[lineLength-1] : 0) & styleMask);
+ if (vstyle.someStylesForceCase) {
+ for (int charInLine = 0; charInLine<lineLength; charInLine++) {
+ char chDoc = ll->chars[charInLine];
+ if (vstyle.styles[ll->styles[charInLine]].caseForce == Style::caseUpper)
+ ll->chars[charInLine] = static_cast<char>(toupper(chDoc));
+ else if (vstyle.styles[ll->styles[charInLine]].caseForce == Style::caseLower)
+ ll->chars[charInLine] = static_cast<char>(tolower(chDoc));
+ }
+ }
+ ll->xHighlightGuide = 0;
+ // Extra element at the end of the line to hold end x position and act as
+ ll->chars[numCharsInLine] = 0; // Also triggers processing in the loops as this is a control character
+ ll->styles[numCharsInLine] = styleByte; // For eolFilled
+ ll->indicators[numCharsInLine] = 0;
+
+ // Layout the line, determining the position of each character,
+ // with an extra element at the end for the end of the line.
+ ll->positions[0] = 0;
+ bool lastSegItalics = false;
+
+ BreakFinder bfLayout(ll, 0, numCharsInLine, posLineStart, 0, false, pdoc, &reprs);
+ while (bfLayout.More()) {
+
+ const TextSegment ts = bfLayout.Next();
+
+ std::fill(&ll->positions[ts.start+1], &ll->positions[ts.end()+1], 0.0f);
+ if (vstyle.styles[ll->styles[ts.start]].visible) {
+ if (ts.representation) {
+ XYPOSITION representationWidth = vstyle.controlCharWidth;
+ if (ll->chars[ts.start] == '\t') {
+ // Tab is a special case of representation, taking a variable amount of space
+ representationWidth =
+ ((static_cast<int>((ll->positions[ts.start] + 2) / vstyle.tabWidth) + 1) * vstyle.tabWidth) - ll->positions[ts.start];
+ } else {
+ if (representationWidth <= 0.0) {
+ XYPOSITION positionsRepr[256]; // Should expand when needed
+ posCache.MeasureWidths(surface, vstyle, STYLE_CONTROLCHAR, ts.representation->stringRep.c_str(),
+ static_cast<unsigned int>(ts.representation->stringRep.length()), positionsRepr, pdoc);
+ representationWidth = positionsRepr[ts.representation->stringRep.length()-1] + vstyle.ctrlCharPadding;
+ }
+ }
+ for (int ii=0; ii < ts.length; ii++)
+ ll->positions[ts.start + 1 + ii] = representationWidth;
+ } else {
+ if ((ts.length == 1) && (' ' == ll->chars[ts.start])) {
+ // Over half the segments are single characters and of these about half are space characters.
+ ll->positions[ts.start + 1] = vstyle.styles[ll->styles[ts.start]].spaceWidth;
+ } else {
+ posCache.MeasureWidths(surface, vstyle, ll->styles[ts.start], ll->chars + ts.start,
+ ts.length, ll->positions + ts.start + 1, pdoc);
+ }
+ }
+ lastSegItalics = (!ts.representation) && ((ll->chars[ts.end()-1] != ' ') && vstyle.styles[ll->styles[ts.start]].italic);
+ }
+
+ for (int posToIncrease = ts.start+1; posToIncrease <= ts.end(); posToIncrease++) {
+ ll->positions[posToIncrease] += ll->positions[ts.start];
+ }
+ }
+
+ // Small hack to make lines that end with italics not cut off the edge of the last character
+ if (lastSegItalics) {
+ ll->positions[numCharsInLine] += vstyle.lastSegItalicsOffset;
+ }
+ ll->numCharsInLine = numCharsInLine;
+ ll->numCharsBeforeEOL = numCharsBeforeEOL;
+ ll->validity = LineLayout::llPositions;
+ }
+ // Hard to cope when too narrow, so just assume there is space
+ if (width < 20) {
+ width = 20;
+ }
+ if ((ll->validity == LineLayout::llPositions) || (ll->widthLine != width)) {
+ ll->widthLine = width;
+ if (width == LineLayout::wrapWidthInfinite) {
+ ll->lines = 1;
+ } else if (width > ll->positions[ll->numCharsInLine]) {
+ // Simple common case where line does not need wrapping.
+ ll->lines = 1;
+ } else {
+ if (vstyle.wrapVisualFlags & SC_WRAPVISUALFLAG_END) {
+ width -= static_cast<int>(vstyle.aveCharWidth); // take into account the space for end wrap mark
+ }
+ XYPOSITION wrapAddIndent = 0; // This will be added to initial indent of line
+ if (vstyle.wrapIndentMode == SC_WRAPINDENT_INDENT) {
+ wrapAddIndent = pdoc->IndentSize() * vstyle.spaceWidth;
+ } else if (vstyle.wrapIndentMode == SC_WRAPINDENT_FIXED) {
+ wrapAddIndent = vstyle.wrapVisualStartIndent * vstyle.aveCharWidth;
+ }
+ ll->wrapIndent = wrapAddIndent;
+ if (vstyle.wrapIndentMode != SC_WRAPINDENT_FIXED)
+ for (int i = 0; i < ll->numCharsInLine; i++) {
+ if (!IsSpaceOrTab(ll->chars[i])) {
+ ll->wrapIndent += ll->positions[i]; // Add line indent
+ break;
+ }
+ }
+ // Check for text width minimum
+ if (ll->wrapIndent > width - static_cast<int>(vstyle.aveCharWidth) * 15)
+ ll->wrapIndent = wrapAddIndent;
+ // Check for wrapIndent minimum
+ if ((vstyle.wrapVisualFlags & SC_WRAPVISUALFLAG_START) && (ll->wrapIndent < vstyle.aveCharWidth))
+ ll->wrapIndent = vstyle.aveCharWidth; // Indent to show start visual
+ ll->lines = 0;
+ // Calculate line start positions based upon width.
+ int lastGoodBreak = 0;
+ int lastLineStart = 0;
+ XYACCUMULATOR startOffset = 0;
+ int p = 0;
+ while (p < ll->numCharsInLine) {
+ if ((ll->positions[p + 1] - startOffset) >= width) {
+ if (lastGoodBreak == lastLineStart) {
+ // Try moving to start of last character
+ if (p > 0) {
+ lastGoodBreak = pdoc->MovePositionOutsideChar(p + posLineStart, -1)
+ - posLineStart;
+ }
+ if (lastGoodBreak == lastLineStart) {
+ // Ensure at least one character on line.
+ lastGoodBreak = pdoc->MovePositionOutsideChar(lastGoodBreak + posLineStart + 1, 1)
+ - posLineStart;
+ }
+ }
+ lastLineStart = lastGoodBreak;
+ ll->lines++;
+ ll->SetLineStart(ll->lines, lastGoodBreak);
+ startOffset = ll->positions[lastGoodBreak];
+ // take into account the space for start wrap mark and indent
+ startOffset -= ll->wrapIndent;
+ p = lastGoodBreak + 1;
+ continue;
+ }
+ if (p > 0) {
+ if (vstyle.wrapState == eWrapChar) {
+ lastGoodBreak = pdoc->MovePositionOutsideChar(p + posLineStart, -1)
+ - posLineStart;
+ p = pdoc->MovePositionOutsideChar(p + 1 + posLineStart, 1) - posLineStart;
+ continue;
+ } else if (ll->styles[p] != ll->styles[p - 1]) {
+ lastGoodBreak = p;
+ } else if (IsSpaceOrTab(ll->chars[p - 1]) && !IsSpaceOrTab(ll->chars[p])) {
+ lastGoodBreak = p;
+ }
+ }
+ p++;
+ }
+ ll->lines++;
+ }
+ ll->validity = LineLayout::llLines;
+ }
+}
+
+ColourDesired Editor::SelectionBackground(ViewStyle &vsDraw, bool main) const {
+ return main ?
+ (primarySelection ? vsDraw.selColours.back : vsDraw.selBackground2) :
+ vsDraw.selAdditionalBackground;
+}
+
+ColourDesired Editor::TextBackground(ViewStyle &vsDraw, bool overrideBackground,
+ ColourDesired background, int inSelection, bool inHotspot, int styleMain, int i, LineLayout *ll) const {
+ if (inSelection == 1) {
+ if (vsDraw.selColours.back.isSet && (vsDraw.selAlpha == SC_ALPHA_NOALPHA)) {
+ return SelectionBackground(vsDraw, true);
+ }
+ } else if (inSelection == 2) {
+ if (vsDraw.selColours.back.isSet && (vsDraw.selAdditionalAlpha == SC_ALPHA_NOALPHA)) {
+ return SelectionBackground(vsDraw, false);
+ }
+ } else {
+ if ((vsDraw.edgeState == EDGE_BACKGROUND) &&
+ (i >= ll->edgeColumn) &&
+ (i < ll->numCharsBeforeEOL))
+ return vsDraw.edgecolour;
+ if (inHotspot && vsDraw.hotspotColours.back.isSet)
+ return vsDraw.hotspotColours.back;
+ }
+ if (overrideBackground && (styleMain != STYLE_BRACELIGHT) && (styleMain != STYLE_BRACEBAD)) {
+ return background;
+ } else {
+ return vsDraw.styles[styleMain].back;
+ }
+}
+
+void Editor::DrawIndentGuide(Surface *surface, int lineVisible, int lineHeight, int start, PRectangle rcSegment, bool highlight) {
+ Point from(0, ((lineVisible & 1) && (lineHeight & 1)) ? 1 : 0);
+ PRectangle rcCopyArea(start + 1, rcSegment.top, start + 2, rcSegment.bottom);
+ surface->Copy(rcCopyArea, from,
+ highlight ? *pixmapIndentGuideHighlight : *pixmapIndentGuide);
+}
+
+void Editor::DrawWrapMarker(Surface *surface, PRectangle rcPlace,
+ bool isEndMarker, ColourDesired wrapColour) {
+ surface->PenColour(wrapColour);
+
+ enum { xa = 1 }; // gap before start
+ int w = rcPlace.right - rcPlace.left - xa - 1;
+
+ bool xStraight = isEndMarker; // x-mirrored symbol for start marker
+
+ int x0 = xStraight ? rcPlace.left : rcPlace.right - 1;
+ int y0 = rcPlace.top;
+
+ int dy = (rcPlace.bottom - rcPlace.top) / 5;
+ int y = (rcPlace.bottom - rcPlace.top) / 2 + dy;
+
+ struct Relative {
+ Surface *surface;
+ int xBase;
+ int xDir;
+ int yBase;
+ int yDir;
+ void MoveTo(int xRelative, int yRelative) {
+ surface->MoveTo(xBase + xDir * xRelative, yBase + yDir * yRelative);
+ }
+ void LineTo(int xRelative, int yRelative) {
+ surface->LineTo(xBase + xDir * xRelative, yBase + yDir * yRelative);
+ }
+ };
+ Relative rel = {surface, x0, xStraight ? 1 : -1, y0, 1};
+
+ // arrow head
+ rel.MoveTo(xa, y);
+ rel.LineTo(xa + 2*w / 3, y - dy);
+ rel.MoveTo(xa, y);
+ rel.LineTo(xa + 2*w / 3, y + dy);
+
+ // arrow body
+ rel.MoveTo(xa, y);
+ rel.LineTo(xa + w, y);
+ rel.LineTo(xa + w, y - 2 * dy);
+ rel.LineTo(xa - 1, // on windows lineto is exclusive endpoint, perhaps GTK not...
+ y - 2 * dy);
+}
+
+static void SimpleAlphaRectangle(Surface *surface, PRectangle rc, ColourDesired fill, int alpha) {
+ if (alpha != SC_ALPHA_NOALPHA) {
+ surface->AlphaRectangle(rc, 0, fill, alpha, fill, alpha, 0);
+ }
+}
+
+void DrawTextBlob(Surface *surface, ViewStyle &vsDraw, PRectangle rcSegment,
+ const char *s, ColourDesired textBack, ColourDesired textFore, bool twoPhaseDraw) {
+ if (!twoPhaseDraw) {
+ surface->FillRectangle(rcSegment, textBack);
+ }
+ Font &ctrlCharsFont = vsDraw.styles[STYLE_CONTROLCHAR].font;
+ int normalCharHeight = surface->Ascent(ctrlCharsFont) -
+ surface->InternalLeading(ctrlCharsFont);
+ PRectangle rcCChar = rcSegment;
+ rcCChar.left = rcCChar.left + 1;
+ rcCChar.top = rcSegment.top + vsDraw.maxAscent - normalCharHeight;
+ rcCChar.bottom = rcSegment.top + vsDraw.maxAscent + 1;
+ PRectangle rcCentral = rcCChar;
+ rcCentral.top++;
+ rcCentral.bottom--;
+ surface->FillRectangle(rcCentral, textFore);
+ PRectangle rcChar = rcCChar;
+ rcChar.left++;
+ rcChar.right--;
+ surface->DrawTextClipped(rcChar, ctrlCharsFont,
+ rcSegment.top + vsDraw.maxAscent, s, istrlen(s),
+ textBack, textFore);
+}
+
+void Editor::DrawEOL(Surface *surface, ViewStyle &vsDraw, PRectangle rcLine, LineLayout *ll,
+ int line, int lineEnd, int xStart, int subLine, XYACCUMULATOR subLineStart,
+ bool overrideBackground, ColourDesired background,
+ bool drawWrapMarkEnd, ColourDesired wrapColour) {
+
+ const int posLineStart = pdoc->LineStart(line);
+ const int styleMask = pdoc->stylingBitsMask;
+ PRectangle rcSegment = rcLine;
+
+ const bool lastSubLine = subLine == (ll->lines - 1);
+ XYPOSITION virtualSpace = 0;
+ if (lastSubLine) {
+ const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth;
+ virtualSpace = sel.VirtualSpaceFor(pdoc->LineEnd(line)) * spaceWidth;
+ }
+ XYPOSITION xEol = ll->positions[lineEnd] - subLineStart;
+
+ // Fill the virtual space and show selections within it
+ if (virtualSpace) {
+ rcSegment.left = xEol + xStart;
+ rcSegment.right = xEol + xStart + virtualSpace;
+ surface->FillRectangle(rcSegment, overrideBackground ? background : vsDraw.styles[ll->styles[ll->numCharsInLine] & styleMask].back);
+ if (!hideSelection && ((vsDraw.selAlpha == SC_ALPHA_NOALPHA) || (vsDraw.selAdditionalAlpha == SC_ALPHA_NOALPHA))) {
+ SelectionSegment virtualSpaceRange(SelectionPosition(pdoc->LineEnd(line)), SelectionPosition(pdoc->LineEnd(line), sel.VirtualSpaceFor(pdoc->LineEnd(line))));
+ for (size_t r=0; r<sel.Count(); r++) {
+ int alpha = (r == sel.Main()) ? vsDraw.selAlpha : vsDraw.selAdditionalAlpha;
+ if (alpha == SC_ALPHA_NOALPHA) {
+ SelectionSegment portion = sel.Range(r).Intersect(virtualSpaceRange);
+ if (!portion.Empty()) {
+ const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth;
+ rcSegment.left = xStart + ll->positions[portion.start.Position() - posLineStart] - subLineStart + portion.start.VirtualSpace() * spaceWidth;
+ rcSegment.right = xStart + ll->positions[portion.end.Position() - posLineStart] - subLineStart + portion.end.VirtualSpace() * spaceWidth;
+ rcSegment.left = (rcSegment.left > rcLine.left) ? rcSegment.left : rcLine.left;
+ rcSegment.right = (rcSegment.right < rcLine.right) ? rcSegment.right : rcLine.right;
+ surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, r == sel.Main()));
+ }
+ }
+ }
+ }
+ }
+
+ int eolInSelection = 0;
+ int alpha = SC_ALPHA_NOALPHA;
+ if (!hideSelection) {
+ int posAfterLineEnd = pdoc->LineStart(line + 1);
+ eolInSelection = (subLine == (ll->lines - 1)) ? sel.InSelectionForEOL(posAfterLineEnd) : 0;
+ alpha = (eolInSelection == 1) ? vsDraw.selAlpha : vsDraw.selAdditionalAlpha;
+ }
+
+ // Draw the [CR], [LF], or [CR][LF] blobs if visible line ends are on
+ XYPOSITION blobsWidth = 0;
+ if (lastSubLine) {
+ for (int eolPos=ll->numCharsBeforeEOL; eolPos<ll->numCharsInLine; eolPos++) {
+ rcSegment.left = xStart + ll->positions[eolPos] - subLineStart + virtualSpace;
+ rcSegment.right = xStart + ll->positions[eolPos+1] - subLineStart + virtualSpace;
+ blobsWidth += rcSegment.Width();
+ char hexits[4];
+ const char *ctrlChar;
+ unsigned char chEOL = ll->chars[eolPos];
+ if (UTF8IsAscii(chEOL)) {
+ ctrlChar = ControlCharacterString(chEOL);
+ } else {
+ sprintf(hexits, "x%2X", chEOL);
+ ctrlChar = hexits;
+ }
+ int styleMain = ll->styles[eolPos];
+ ColourDesired textBack = TextBackground(vsDraw, overrideBackground, background, eolInSelection, false, styleMain, eolPos, ll);
+ ColourDesired textFore = vsDraw.styles[styleMain].fore;
+ if (eolInSelection && vsDraw.selColours.fore.isSet) {
+ textFore = (eolInSelection == 1) ? vsDraw.selColours.fore : vsDraw.selAdditionalForeground;
+ }
+ if (eolInSelection && vsDraw.selColours.back.isSet && (line < pdoc->LinesTotal() - 1)) {
+ if (alpha == SC_ALPHA_NOALPHA) {
+ surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, eolInSelection == 1));
+ } else {
+ surface->FillRectangle(rcSegment, textBack);
+ }
+ } else {
+ surface->FillRectangle(rcSegment, textBack);
+ }
+ DrawTextBlob(surface, vsDraw, rcSegment, ctrlChar, textBack, textFore, twoPhaseDraw);
+ if (eolInSelection && vsDraw.selColours.back.isSet && (line < pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) {
+ SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1), alpha);
+ }
+ }
+ }
+
+ // Draw the eol-is-selected rectangle
+ rcSegment.left = xEol + xStart + virtualSpace + blobsWidth;
+ rcSegment.right = rcSegment.left + vsDraw.aveCharWidth;
+
+ if (eolInSelection && vsDraw.selColours.back.isSet && (line < pdoc->LinesTotal() - 1) && (alpha == SC_ALPHA_NOALPHA)) {
+ surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, eolInSelection == 1));
+ } else {
+ if (overrideBackground) {
+ surface->FillRectangle(rcSegment, background);
+ } else if (line < pdoc->LinesTotal() - 1) {
+ surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine] & styleMask].back);
+ } else if (vsDraw.styles[ll->styles[ll->numCharsInLine] & styleMask].eolFilled) {
+ surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine] & styleMask].back);
+ } else {
+ surface->FillRectangle(rcSegment, vsDraw.styles[STYLE_DEFAULT].back);
+ }
+ if (eolInSelection && vsDraw.selColours.back.isSet && (line < pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) {
+ SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1), alpha);
+ }
+ }
+
+ // Fill the remainder of the line
+ rcSegment.left = rcSegment.right;
+ if (rcSegment.left < rcLine.left)
+ rcSegment.left = rcLine.left;
+ rcSegment.right = rcLine.right;
+
+ if (eolInSelection && vsDraw.selEOLFilled && vsDraw.selColours.back.isSet && (line < pdoc->LinesTotal() - 1) && (alpha == SC_ALPHA_NOALPHA)) {
+ surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, eolInSelection == 1));
+ } else {
+ if (overrideBackground) {
+ surface->FillRectangle(rcSegment, background);
+ } else if (vsDraw.styles[ll->styles[ll->numCharsInLine] & styleMask].eolFilled) {
+ surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine] & styleMask].back);
+ } else {
+ surface->FillRectangle(rcSegment, vsDraw.styles[STYLE_DEFAULT].back);
+ }
+ if (eolInSelection && vsDraw.selEOLFilled && vsDraw.selColours.back.isSet && (line < pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) {
+ SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1), alpha);
+ }
+ }
+
+ if (drawWrapMarkEnd) {
+ PRectangle rcPlace = rcSegment;
+
+ if (vsDraw.wrapVisualFlagsLocation & SC_WRAPVISUALFLAGLOC_END_BY_TEXT) {
+ rcPlace.left = xEol + xStart + virtualSpace;
+ rcPlace.right = rcPlace.left + vsDraw.aveCharWidth;
+ } else {
+ // rcLine is clipped to text area
+ rcPlace.right = rcLine.right;
+ rcPlace.left = rcPlace.right - vsDraw.aveCharWidth;
+ }
+ DrawWrapMarker(surface, rcPlace, true, wrapColour);
+ }
+}
+
+void Editor::DrawIndicator(int indicNum, int startPos, int endPos, Surface *surface, ViewStyle &vsDraw,
+ int xStart, PRectangle rcLine, LineLayout *ll, int subLine) {
+ const XYPOSITION subLineStart = ll->positions[ll->LineStart(subLine)];
+ PRectangle rcIndic(
+ ll->positions[startPos] + xStart - subLineStart,
+ rcLine.top + vsDraw.maxAscent,
+ ll->positions[endPos] + xStart - subLineStart,
+ rcLine.top + vsDraw.maxAscent + 3);
+ vsDraw.indicators[indicNum].Draw(surface, rcIndic, rcLine);
+}
+
+void Editor::DrawIndicators(Surface *surface, ViewStyle &vsDraw, int line, int xStart,
+ PRectangle rcLine, LineLayout *ll, int subLine, int lineEnd, bool under) {
+ // Draw decorators
+ const int posLineStart = pdoc->LineStart(line);
+ const int lineStart = ll->LineStart(subLine);
+ const int posLineEnd = posLineStart + lineEnd;
+
+ if (!under) {
+ // Draw indicators
+ // foreach indicator...
+ for (int indicnum = 0, mask = 1 << pdoc->stylingBits; mask < 0x100; indicnum++) {
+ if (!(mask & ll->styleBitsSet)) {
+ mask <<= 1;
+ continue;
+ }
+ int startPos = -1;
+ // foreach style pos in line...
+ for (int indicPos = lineStart; indicPos <= lineEnd; indicPos++) {
+ // look for starts...
+ if (startPos < 0) {
+ // NOT in indicator run, looking for START
+ if (indicPos < lineEnd && (ll->indicators[indicPos] & mask))
+ startPos = indicPos;
+ }
+ // ... or ends
+ if (startPos >= 0) {
+ // IN indicator run, looking for END
+ if (indicPos >= lineEnd || !(ll->indicators[indicPos] & mask)) {
+ // AT end of indicator run, DRAW it!
+ DrawIndicator(indicnum, startPos, indicPos, surface, vsDraw, xStart, rcLine, ll, subLine);
+ // RESET control var
+ startPos = -1;
+ }
+ }
+ }
+ mask <<= 1;
+ }
+ }
+
+ for (Decoration *deco = pdoc->decorations.root; deco; deco = deco->next) {
+ if (under == vsDraw.indicators[deco->indicator].under) {
+ int startPos = posLineStart + lineStart;
+ if (!deco->rs.ValueAt(startPos)) {
+ startPos = deco->rs.EndRun(startPos);
+ }
+ while ((startPos < posLineEnd) && (deco->rs.ValueAt(startPos))) {
+ int endPos = deco->rs.EndRun(startPos);
+ if (endPos > posLineEnd)
+ endPos = posLineEnd;
+ DrawIndicator(deco->indicator, startPos - posLineStart, endPos - posLineStart,
+ surface, vsDraw, xStart, rcLine, ll, subLine);
+ startPos = deco->rs.EndRun(endPos);
+ }
+ }
+ }
+
+ // Use indicators to highlight matching braces
+ if ((vs.braceHighlightIndicatorSet && (bracesMatchStyle == STYLE_BRACELIGHT)) ||
+ (vs.braceBadLightIndicatorSet && (bracesMatchStyle == STYLE_BRACEBAD))) {
+ int braceIndicator = (bracesMatchStyle == STYLE_BRACELIGHT) ? vs.braceHighlightIndicator : vs.braceBadLightIndicator;
+ if (under == vsDraw.indicators[braceIndicator].under) {
+ Range rangeLine(posLineStart + lineStart, posLineEnd);
+ if (rangeLine.ContainsCharacter(braces[0])) {
+ int braceOffset = braces[0] - posLineStart;
+ if (braceOffset < ll->numCharsInLine) {
+ DrawIndicator(braceIndicator, braceOffset, braceOffset + 1, surface, vsDraw, xStart, rcLine, ll, subLine);
+ }
+ }
+ if (rangeLine.ContainsCharacter(braces[1])) {
+ int braceOffset = braces[1] - posLineStart;
+ if (braceOffset < ll->numCharsInLine) {
+ DrawIndicator(braceIndicator, braceOffset, braceOffset + 1, surface, vsDraw, xStart, rcLine, ll, subLine);
+ }
+ }
+ }
+ }
+}
+
+void Editor::DrawAnnotation(Surface *surface, ViewStyle &vsDraw, int line, int xStart,
+ PRectangle rcLine, LineLayout *ll, int subLine) {
+ int indent = pdoc->GetLineIndentation(line) * vsDraw.spaceWidth;
+ PRectangle rcSegment = rcLine;
+ int annotationLine = subLine - ll->lines;
+ const StyledText stAnnotation = pdoc->AnnotationStyledText(line);
+ if (stAnnotation.text && ValidStyledText(vsDraw, vsDraw.annotationStyleOffset, stAnnotation)) {
+ surface->FillRectangle(rcSegment, vsDraw.styles[0].back);
+ if (vs.annotationVisible == ANNOTATION_BOXED) {
+ // Only care about calculating width if need to draw box
+ int widthAnnotation = WidestLineWidth(surface, vsDraw, vsDraw.annotationStyleOffset, stAnnotation);
+ widthAnnotation += vsDraw.spaceWidth * 2; // Margins
+ rcSegment.left = xStart + indent;
+ rcSegment.right = rcSegment.left + widthAnnotation;
+ } else {
+ rcSegment.left = xStart;
+ }
+ const int annotationLines = pdoc->AnnotationLines(line);
+ size_t start = 0;
+ size_t lengthAnnotation = stAnnotation.LineLength(start);
+ int lineInAnnotation = 0;
+ while ((lineInAnnotation < annotationLine) && (start < stAnnotation.length)) {
+ start += lengthAnnotation + 1;
+ lengthAnnotation = stAnnotation.LineLength(start);
+ lineInAnnotation++;
+ }
+ PRectangle rcText = rcSegment;
+ if (vs.annotationVisible == ANNOTATION_BOXED) {
+ surface->FillRectangle(rcText,
+ vsDraw.styles[stAnnotation.StyleAt(start) + vsDraw.annotationStyleOffset].back);
+ rcText.left += vsDraw.spaceWidth;
+ }
+ DrawStyledText(surface, vsDraw, vsDraw.annotationStyleOffset, rcText, rcText.top + vsDraw.maxAscent,
+ stAnnotation, start, lengthAnnotation);
+ if (vs.annotationVisible == ANNOTATION_BOXED) {
+ surface->PenColour(vsDraw.styles[vsDraw.annotationStyleOffset].fore);
+ surface->MoveTo(rcSegment.left, rcSegment.top);
+ surface->LineTo(rcSegment.left, rcSegment.bottom);
+ surface->MoveTo(rcSegment.right, rcSegment.top);
+ surface->LineTo(rcSegment.right, rcSegment.bottom);
+ if (subLine == ll->lines) {
+ surface->MoveTo(rcSegment.left, rcSegment.top);
+ surface->LineTo(rcSegment.right, rcSegment.top);
+ }
+ if (subLine == ll->lines+annotationLines-1) {
+ surface->MoveTo(rcSegment.left, rcSegment.bottom - 1);
+ surface->LineTo(rcSegment.right, rcSegment.bottom - 1);
+ }
+ }
+ }
+}
+
+void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVisible, int xStart,
+ PRectangle rcLine, LineLayout *ll, int subLine) {
+
+ if (subLine >= ll->lines) {
+ DrawAnnotation(surface, vsDraw, line, xStart, rcLine, ll, subLine);
+ return; // No further drawing
+ }
+
+ PRectangle rcSegment = rcLine;
+
+ // Using one font for all control characters so it can be controlled independently to ensure
+ // the box goes around the characters tightly. Seems to be no way to work out what height
+ // is taken by an individual character - internal leading gives varying results.
+ Font &ctrlCharsFont = vsDraw.styles[STYLE_CONTROLCHAR].font;
+
+ // See if something overrides the line background color: Either if caret is on the line
+ // and background color is set for that, or if a marker is defined that forces its background
+ // color onto the line, or if a marker is defined but has no selection margin in which to
+ // display itself (as long as it's not an SC_MARK_EMPTY marker). These are checked in order
+ // with the earlier taking precedence. When multiple markers cause background override,
+ // the color for the highest numbered one is used.
+ bool overrideBackground = false;
+ ColourDesired background;
+ if ((caret.active || vsDraw.alwaysShowCaretLineBackground) && vsDraw.showCaretLineBackground && (vsDraw.caretLineAlpha == SC_ALPHA_NOALPHA) && ll->containsCaret) {
+ overrideBackground = true;
+ background = vsDraw.caretLineBackground;
+ }
+ if (!overrideBackground) {
+ int marks = pdoc->GetMark(line);
+ for (int markBit = 0; (markBit < 32) && marks; markBit++) {
+ if ((marks & 1) && (vsDraw.markers[markBit].markType == SC_MARK_BACKGROUND) &&
+ (vsDraw.markers[markBit].alpha == SC_ALPHA_NOALPHA)) {
+ background = vsDraw.markers[markBit].back;
+ overrideBackground = true;
+ }
+ marks >>= 1;
+ }
+ }
+ if (!overrideBackground) {
+ if (vsDraw.maskInLine) {
+ int marksMasked = pdoc->GetMark(line) & vsDraw.maskInLine;
+ if (marksMasked) {
+ for (int markBit = 0; (markBit < 32) && marksMasked; markBit++) {
+ if ((marksMasked & 1) && (vsDraw.markers[markBit].markType != SC_MARK_EMPTY) &&
+ (vsDraw.markers[markBit].alpha == SC_ALPHA_NOALPHA)) {
+ overrideBackground = true;
+ background = vsDraw.markers[markBit].back;
+ }
+ marksMasked >>= 1;
+ }
+ }
+ }
+ }
+
+ const bool drawWhitespaceBackground = (vsDraw.viewWhitespace != wsInvisible) &&
+ (!overrideBackground) && (vsDraw.whitespaceColours.back.isSet);
+
+ bool inIndentation = subLine == 0; // Do not handle indentation except on first subline.
+ const XYPOSITION indentWidth = pdoc->IndentSize() * vsDraw.spaceWidth;
+ const XYPOSITION epsilon = 0.0001f; // A small nudge to avoid floating point precision issues
+
+ const int posLineStart = pdoc->LineStart(line);
+
+ const int startseg = ll->LineStart(subLine);
+ const XYACCUMULATOR subLineStart = ll->positions[startseg];
+ int lineStart = 0;
+ int lineEnd = 0;
+ if (subLine < ll->lines) {
+ lineStart = ll->LineStart(subLine);
+ lineEnd = ll->LineStart(subLine + 1);
+ if (subLine == ll->lines - 1) {
+ lineEnd = ll->numCharsBeforeEOL;
+ }
+ }
+
+ const ColourDesired wrapColour = vsDraw.WrapColour();
+
+ bool drawWrapMarkEnd = false;
+
+ if (vsDraw.wrapVisualFlags & SC_WRAPVISUALFLAG_END) {
+ if (subLine + 1 < ll->lines) {
+ drawWrapMarkEnd = ll->LineStart(subLine + 1) != 0;
+ }
+ }
+
+ if (ll->wrapIndent != 0) {
+
+ bool continuedWrapLine = false;
+ if (subLine < ll->lines) {
+ continuedWrapLine = ll->LineStart(subLine) != 0;
+ }
+
+ if (continuedWrapLine) {
+ // draw continuation rect
+ PRectangle rcPlace = rcSegment;
+
+ rcPlace.left = ll->positions[startseg] + xStart - subLineStart;
+ rcPlace.right = rcPlace.left + ll->wrapIndent;
+
+ // default bgnd here..
+ surface->FillRectangle(rcSegment, overrideBackground ? background :
+ vsDraw.styles[STYLE_DEFAULT].back);
+
+ // main line style would be below but this would be inconsistent with end markers
+ // also would possibly not be the style at wrap point
+ //int styleMain = ll->styles[lineStart];
+ //surface->FillRectangle(rcPlace, vsDraw.styles[styleMain].back);
+
+ if (vsDraw.wrapVisualFlags & SC_WRAPVISUALFLAG_START) {
+
+ if (vsDraw.wrapVisualFlagsLocation & SC_WRAPVISUALFLAGLOC_START_BY_TEXT)
+ rcPlace.left = rcPlace.right - vsDraw.aveCharWidth;
+ else
+ rcPlace.right = rcPlace.left + vsDraw.aveCharWidth;
+
+ DrawWrapMarker(surface, rcPlace, false, wrapColour);
+ }
+
+ xStart += static_cast<int>(ll->wrapIndent);
+ }
+ }
+
+ const bool selBackDrawn = vsDraw.selColours.back.isSet &&
+ ((vsDraw.selAlpha == SC_ALPHA_NOALPHA) || (vsDraw.selAdditionalAlpha == SC_ALPHA_NOALPHA));
+
+ // Does not take margin into account but not significant
+ const int xStartVisible = static_cast<int>(subLineStart) - xStart;
+
+ ll->psel = &sel;
+
+ if (twoPhaseDraw) {
+ BreakFinder bfBack(ll, lineStart, lineEnd, posLineStart, xStartVisible, selBackDrawn, pdoc, &reprs);
+
+ // Background drawing loop
+ while (bfBack.More()) {
+
+ const TextSegment ts = bfBack.Next();
+ const int i = ts.end() - 1;
+ const int iDoc = i + posLineStart;
+
+ rcSegment.left = ll->positions[ts.start] + xStart - subLineStart;
+ rcSegment.right = ll->positions[ts.end()] + xStart - subLineStart;
+ // Only try to draw if really visible - enhances performance by not calling environment to
+ // draw strings that are completely past the right side of the window.
+ if (rcSegment.Intersects(rcLine)) {
+ // Clip to line rectangle, since may have a huge position which will not work with some platforms
+ if (rcSegment.left < rcLine.left)
+ rcSegment.left = rcLine.left;
+ if (rcSegment.right > rcLine.right)
+ rcSegment.right = rcLine.right;
+
+ const int inSelection = hideSelection ? 0 : sel.CharacterInSelection(iDoc);
+ const bool inHotspot = (ll->hsStart != -1) && (iDoc >= ll->hsStart) && (iDoc < ll->hsEnd);
+ ColourDesired textBack = TextBackground(vsDraw, overrideBackground, background, inSelection,
+ inHotspot, ll->styles[i], i, ll);
+ if (ts.representation) {
+ if (ll->chars[i] == '\t') {
+ // Tab display
+ if (drawWhitespaceBackground &&
+ (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways))
+ textBack = vsDraw.whitespaceColours.back;
+ } else {
+ // Blob display
+ inIndentation = false;
+ }
+ surface->FillRectangle(rcSegment, textBack);
+ } else {
+ // Normal text display
+ surface->FillRectangle(rcSegment, textBack);
+ if (vsDraw.viewWhitespace != wsInvisible ||
+ (inIndentation && vsDraw.viewIndentationGuides == ivReal)) {
+ for (int cpos = 0; cpos <= i - ts.start; cpos++) {
+ if (ll->chars[cpos + ts.start] == ' ') {
+ if (drawWhitespaceBackground &&
+ (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) {
+ PRectangle rcSpace(ll->positions[cpos + ts.start] + xStart - subLineStart,
+ rcSegment.top,
+ ll->positions[cpos + ts.start + 1] + xStart - subLineStart,
+ rcSegment.bottom);
+ surface->FillRectangle(rcSpace, vsDraw.whitespaceColours.back);
+ }
+ } else {
+ inIndentation = false;
+ }
+ }
+ }
+ }
+ } else if (rcSegment.left > rcLine.right) {
+ break;
+ }
+ }
+
+ DrawEOL(surface, vsDraw, rcLine, ll, line, lineEnd,
+ xStart, subLine, subLineStart, overrideBackground, background,
+ drawWrapMarkEnd, wrapColour);
+ }
+
+ DrawIndicators(surface, vsDraw, line, xStart, rcLine, ll, subLine, lineEnd, true);
+
+ if (vsDraw.edgeState == EDGE_LINE) {
+ int edgeX = vsDraw.theEdge * vsDraw.spaceWidth;
+ rcSegment.left = edgeX + xStart;
+ if ((ll->wrapIndent != 0) && (lineStart != 0))
+ rcSegment.left -= ll->wrapIndent;
+ rcSegment.right = rcSegment.left + 1;
+ surface->FillRectangle(rcSegment, vsDraw.edgecolour);
+ }
+
+ // Draw underline mark as part of background if not transparent
+ int marks = pdoc->GetMark(line);
+ int markBit;
+ for (markBit = 0; (markBit < 32) && marks; markBit++) {
+ if ((marks & 1) && (vsDraw.markers[markBit].markType == SC_MARK_UNDERLINE) &&
+ (vsDraw.markers[markBit].alpha == SC_ALPHA_NOALPHA)) {
+ PRectangle rcUnderline = rcLine;
+ rcUnderline.top = rcUnderline.bottom - 2;
+ surface->FillRectangle(rcUnderline, vsDraw.markers[markBit].back);
+ }
+ marks >>= 1;
+ }
+
+ inIndentation = subLine == 0; // Do not handle indentation except on first subline.
+ // Foreground drawing loop
+ BreakFinder bfFore(ll, lineStart, lineEnd, posLineStart, xStartVisible,
+ ((!twoPhaseDraw && selBackDrawn) || vsDraw.selColours.fore.isSet), pdoc, &reprs);
+
+ while (bfFore.More()) {
+
+ const TextSegment ts = bfFore.Next();
+ const int i = ts.end() - 1;
+ const int iDoc = i + posLineStart;
+
+ rcSegment.left = ll->positions[ts.start] + xStart - subLineStart;
+ rcSegment.right = ll->positions[ts.end()] + xStart - subLineStart;
+ // Only try to draw if really visible - enhances performance by not calling environment to
+ // draw strings that are completely past the right side of the window.
+ if (rcSegment.Intersects(rcLine)) {
+ int styleMain = ll->styles[i];
+ ColourDesired textFore = vsDraw.styles[styleMain].fore;
+ Font &textFont = vsDraw.styles[styleMain].font;
+ //hotspot foreground
+ if (ll->hsStart != -1 && iDoc >= ll->hsStart && iDoc < hsEnd) {
+ if (vsDraw.hotspotColours.fore.isSet)
+ textFore = vsDraw.hotspotColours.fore;
+ }
+ const int inSelection = hideSelection ? 0 : sel.CharacterInSelection(iDoc);
+ if (inSelection && (vsDraw.selColours.fore.isSet)) {
+ textFore = (inSelection == 1) ? vsDraw.selColours.fore : vsDraw.selAdditionalForeground;
+ }
+ const bool inHotspot = (ll->hsStart != -1) && (iDoc >= ll->hsStart) && (iDoc < ll->hsEnd);
+ ColourDesired textBack = TextBackground(vsDraw, overrideBackground, background, inSelection, inHotspot, styleMain, i, ll);
+ if (ts.representation) {
+ if (ll->chars[i] == '\t') {
+ // Tab display
+ if (!twoPhaseDraw) {
+ if (drawWhitespaceBackground &&
+ (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways))
+ textBack = vsDraw.whitespaceColours.back;
+ surface->FillRectangle(rcSegment, textBack);
+ }
+ if (inIndentation && vsDraw.viewIndentationGuides == ivReal) {
+ for (int indentCount = (ll->positions[i] + epsilon) / indentWidth;
+ indentCount <= (ll->positions[i + 1] - epsilon) / indentWidth;
+ indentCount++) {
+ if (indentCount > 0) {
+ int xIndent = indentCount * indentWidth;
+ DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIndent + xStart, rcSegment,
+ (ll->xHighlightGuide == xIndent));
+ }
+ }
+ }
+ if (vsDraw.viewWhitespace != wsInvisible) {
+ if (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways) {
+ if (vsDraw.whitespaceColours.fore.isSet)
+ textFore = vsDraw.whitespaceColours.fore;
+ surface->PenColour(textFore);
+ PRectangle rcTab(rcSegment.left + 1, rcSegment.top + 4,
+ rcSegment.right - 1, rcSegment.bottom - vsDraw.maxDescent);
+ DrawTabArrow(surface, rcTab, rcSegment.top + vsDraw.lineHeight / 2);
+ }
+ }
+ } else {
+ inIndentation = false;
+ if (vsDraw.controlCharSymbol >= 32) {
+ char cc[2] = { static_cast<char>(vsDraw.controlCharSymbol), '\0' };
+ surface->DrawTextNoClip(rcSegment, ctrlCharsFont,
+ rcSegment.top + vsDraw.maxAscent,
+ cc, 1, textBack, textFore);
+ } else {
+ DrawTextBlob(surface, vsDraw, rcSegment, ts.representation->stringRep.c_str(), textBack, textFore, twoPhaseDraw);
+ }
+ }
+ } else {
+ // Normal text display
+ if (vsDraw.styles[styleMain].visible) {
+ if (twoPhaseDraw) {
+ surface->DrawTextTransparent(rcSegment, textFont,
+ rcSegment.top + vsDraw.maxAscent, ll->chars + ts.start,
+ i - ts.start + 1, textFore);
+ } else {
+ surface->DrawTextNoClip(rcSegment, textFont,
+ rcSegment.top + vsDraw.maxAscent, ll->chars + ts.start,
+ i - ts.start + 1, textFore, textBack);
+ }
+ }
+ if (vsDraw.viewWhitespace != wsInvisible ||
+ (inIndentation && vsDraw.viewIndentationGuides != ivNone)) {
+ for (int cpos = 0; cpos <= i - ts.start; cpos++) {
+ if (ll->chars[cpos + ts.start] == ' ') {
+ if (vsDraw.viewWhitespace != wsInvisible) {
+ if (vsDraw.whitespaceColours.fore.isSet)
+ textFore = vsDraw.whitespaceColours.fore;
+ if (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways) {
+ XYPOSITION xmid = (ll->positions[cpos + ts.start] + ll->positions[cpos + ts.start + 1]) / 2;
+ if (!twoPhaseDraw && drawWhitespaceBackground &&
+ (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) {
+ textBack = vsDraw.whitespaceColours.back;
+ PRectangle rcSpace(ll->positions[cpos + ts.start] + xStart - subLineStart,
+ rcSegment.top,
+ ll->positions[cpos + ts.start + 1] + xStart - subLineStart,
+ rcSegment.bottom);
+ surface->FillRectangle(rcSpace, textBack);
+ }
+ PRectangle rcDot(xmid + xStart - subLineStart, rcSegment.top + vsDraw.lineHeight / 2, 0, 0);
+ rcDot.right = rcDot.left + vs.whitespaceSize;
+ rcDot.bottom = rcDot.top + vs.whitespaceSize;
+ surface->FillRectangle(rcDot, textFore);
+ }
+ }
+ if (inIndentation && vsDraw.viewIndentationGuides == ivReal) {
+ for (int indentCount = (ll->positions[cpos + ts.start] + epsilon) / indentWidth;
+ indentCount <= (ll->positions[cpos + ts.start + 1] - epsilon) / indentWidth;
+ indentCount++) {
+ if (indentCount > 0) {
+ int xIndent = indentCount * indentWidth;
+ DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIndent + xStart, rcSegment,
+ (ll->xHighlightGuide == xIndent));
+ }
+ }
+ }
+ } else {
+ inIndentation = false;
+ }
+ }
+ }
+ }
+ if (ll->hsStart != -1 && vsDraw.hotspotUnderline && iDoc >= ll->hsStart && iDoc < ll->hsEnd) {
+ PRectangle rcUL = rcSegment;
+ rcUL.top = rcUL.top + vsDraw.maxAscent + 1;
+ rcUL.bottom = rcUL.top + 1;
+ if (vsDraw.hotspotColours.fore.isSet)
+ surface->FillRectangle(rcUL, vsDraw.hotspotColours.fore);
+ else
+ surface->FillRectangle(rcUL, textFore);
+ } else if (vsDraw.styles[styleMain].underline) {
+ PRectangle rcUL = rcSegment;
+ rcUL.top = rcUL.top + vsDraw.maxAscent + 1;
+ rcUL.bottom = rcUL.top + 1;
+ surface->FillRectangle(rcUL, textFore);
+ }
+ } else if (rcSegment.left > rcLine.right) {
+ break;
+ }
+ }
+ if ((vsDraw.viewIndentationGuides == ivLookForward || vsDraw.viewIndentationGuides == ivLookBoth)
+ && (subLine == 0)) {
+ int indentSpace = pdoc->GetLineIndentation(line);
+ int xStartText = ll->positions[pdoc->GetLineIndentPosition(line) - posLineStart];
+
+ // Find the most recent line with some text
+
+ int lineLastWithText = line;
+ while (lineLastWithText > Platform::Maximum(line-20, 0) && pdoc->IsWhiteLine(lineLastWithText)) {
+ lineLastWithText--;
+ }
+ if (lineLastWithText < line) {
+ xStartText = 100000; // Don't limit to visible indentation on empty line
+ // This line is empty, so use indentation of last line with text
+ int indentLastWithText = pdoc->GetLineIndentation(lineLastWithText);
+ int isFoldHeader = pdoc->GetLevel(lineLastWithText) & SC_FOLDLEVELHEADERFLAG;
+ if (isFoldHeader) {
+ // Level is one more level than parent
+ indentLastWithText += pdoc->IndentSize();
+ }
+ if (vsDraw.viewIndentationGuides == ivLookForward) {
+ // In viLookForward mode, previous line only used if it is a fold header
+ if (isFoldHeader) {
+ indentSpace = Platform::Maximum(indentSpace, indentLastWithText);
+ }
+ } else { // viLookBoth
+ indentSpace = Platform::Maximum(indentSpace, indentLastWithText);
+ }
+ }
+
+ int lineNextWithText = line;
+ while (lineNextWithText < Platform::Minimum(line+20, pdoc->LinesTotal()) && pdoc->IsWhiteLine(lineNextWithText)) {
+ lineNextWithText++;
+ }
+ if (lineNextWithText > line) {
+ xStartText = 100000; // Don't limit to visible indentation on empty line
+ // This line is empty, so use indentation of first next line with text
+ indentSpace = Platform::Maximum(indentSpace,
+ pdoc->GetLineIndentation(lineNextWithText));
+ }
+
+ for (int indentPos = pdoc->IndentSize(); indentPos < indentSpace; indentPos += pdoc->IndentSize()) {
+ int xIndent = indentPos * vsDraw.spaceWidth;
+ if (xIndent < xStartText) {
+ DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIndent + xStart, rcSegment,
+ (ll->xHighlightGuide == xIndent));
+ }
+ }
+ }
+
+ DrawIndicators(surface, vsDraw, line, xStart, rcLine, ll, subLine, lineEnd, false);
+
+ // End of the drawing of the current line
+ if (!twoPhaseDraw) {
+ DrawEOL(surface, vsDraw, rcLine, ll, line, lineEnd,
+ xStart, subLine, subLineStart, overrideBackground, background,
+ drawWrapMarkEnd, wrapColour);
+ }
+ if (!hideSelection && ((vsDraw.selAlpha != SC_ALPHA_NOALPHA) || (vsDraw.selAdditionalAlpha != SC_ALPHA_NOALPHA))) {
+ // For each selection draw
+ int virtualSpaces = 0;
+ if (subLine == (ll->lines - 1)) {
+ virtualSpaces = sel.VirtualSpaceFor(pdoc->LineEnd(line));
+ }
+ SelectionPosition posStart(posLineStart + lineStart);
+ SelectionPosition posEnd(posLineStart + lineEnd, virtualSpaces);
+ SelectionSegment virtualSpaceRange(posStart, posEnd);
+ for (size_t r=0; r<sel.Count(); r++) {
+ int alpha = (r == sel.Main()) ? vsDraw.selAlpha : vsDraw.selAdditionalAlpha;
+ if (alpha != SC_ALPHA_NOALPHA) {
+ SelectionSegment portion = sel.Range(r).Intersect(virtualSpaceRange);
+ if (!portion.Empty()) {
+ const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth;
+ rcSegment.left = xStart + ll->positions[portion.start.Position() - posLineStart] - subLineStart + portion.start.VirtualSpace() * spaceWidth;
+ rcSegment.right = xStart + ll->positions[portion.end.Position() - posLineStart] - subLineStart + portion.end.VirtualSpace() * spaceWidth;
+ if ((ll->wrapIndent != 0) && (lineStart != 0)) {
+ if ((portion.start.Position() - posLineStart) == lineStart && sel.Range(r).ContainsCharacter(portion.start.Position() - 1))
+ rcSegment.left -= static_cast<int>(ll->wrapIndent); // indentation added to xStart was truncated to int, so we do the same here
+ }
+ rcSegment.left = (rcSegment.left > rcLine.left) ? rcSegment.left : rcLine.left;
+ rcSegment.right = (rcSegment.right < rcLine.right) ? rcSegment.right : rcLine.right;
+ if (rcSegment.right > rcLine.left)
+ SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, r == sel.Main()), alpha);
+ }
+ }
+ }
+ }
+
+ // Draw any translucent whole line states
+ rcSegment = rcLine;
+ if ((caret.active || vsDraw.alwaysShowCaretLineBackground) && vsDraw.showCaretLineBackground && ll->containsCaret) {
+ SimpleAlphaRectangle(surface, rcSegment, vsDraw.caretLineBackground, vsDraw.caretLineAlpha);
+ }
+ marks = pdoc->GetMark(line);
+ for (markBit = 0; (markBit < 32) && marks; markBit++) {
+ if ((marks & 1) && (vsDraw.markers[markBit].markType == SC_MARK_BACKGROUND)) {
+ SimpleAlphaRectangle(surface, rcSegment, vsDraw.markers[markBit].back, vsDraw.markers[markBit].alpha);
+ } else if ((marks & 1) && (vsDraw.markers[markBit].markType == SC_MARK_UNDERLINE)) {
+ PRectangle rcUnderline = rcSegment;
+ rcUnderline.top = rcUnderline.bottom - 2;
+ SimpleAlphaRectangle(surface, rcUnderline, vsDraw.markers[markBit].back, vsDraw.markers[markBit].alpha);
+ }
+ marks >>= 1;
+ }
+ if (vsDraw.maskInLine) {
+ int marksMasked = pdoc->GetMark(line) & vsDraw.maskInLine;
+ if (marksMasked) {
+ for (markBit = 0; (markBit < 32) && marksMasked; markBit++) {
+ if ((marksMasked & 1) && (vsDraw.markers[markBit].markType != SC_MARK_EMPTY)) {
+ SimpleAlphaRectangle(surface, rcSegment, vsDraw.markers[markBit].back, vsDraw.markers[markBit].alpha);
+ }
+ marksMasked >>= 1;
+ }
+ }
+ }
+}
+
+void Editor::DrawBlockCaret(Surface *surface, ViewStyle &vsDraw, LineLayout *ll, int subLine,
+ int xStart, int offset, int posCaret, PRectangle rcCaret, ColourDesired caretColour) {
+
+ int lineStart = ll->LineStart(subLine);
+ int posBefore = posCaret;
+ int posAfter = MovePositionOutsideChar(posCaret + 1, 1);
+ int numCharsToDraw = posAfter - posCaret;
+
+ // Work out where the starting and ending offsets are. We need to
+ // see if the previous character shares horizontal space, such as a
+ // glyph / combining character. If so we'll need to draw that too.
+ int offsetFirstChar = offset;
+ int offsetLastChar = offset + (posAfter - posCaret);
+ while ((posBefore > 0) && ((offsetLastChar - numCharsToDraw) >= lineStart)) {
+ if ((ll->positions[offsetLastChar] - ll->positions[offsetLastChar - numCharsToDraw]) > 0) {
+ // The char does not share horizontal space
+ break;
+ }
+ // Char shares horizontal space, update the numChars to draw
+ // Update posBefore to point to the prev char
+ posBefore = MovePositionOutsideChar(posBefore - 1, -1);
+ numCharsToDraw = posAfter - posBefore;
+ offsetFirstChar = offset - (posCaret - posBefore);
+ }
+
+ // See if the next character shares horizontal space, if so we'll
+ // need to draw that too.
+ if (offsetFirstChar < 0)
+ offsetFirstChar = 0;
+ numCharsToDraw = offsetLastChar - offsetFirstChar;
+ while ((offsetLastChar < ll->LineStart(subLine + 1)) && (offsetLastChar <= ll->numCharsInLine)) {
+ // Update posAfter to point to the 2nd next char, this is where
+ // the next character ends, and 2nd next begins. We'll need
+ // to compare these two
+ posBefore = posAfter;
+ posAfter = MovePositionOutsideChar(posAfter + 1, 1);
+ offsetLastChar = offset + (posAfter - posCaret);
+ if ((ll->positions[offsetLastChar] - ll->positions[offsetLastChar - (posAfter - posBefore)]) > 0) {
+ // The char does not share horizontal space
+ break;
+ }
+ // Char shares horizontal space, update the numChars to draw
+ numCharsToDraw = offsetLastChar - offsetFirstChar;
+ }
+
+ // We now know what to draw, update the caret drawing rectangle
+ rcCaret.left = ll->positions[offsetFirstChar] - ll->positions[lineStart] + xStart;
+ rcCaret.right = ll->positions[offsetFirstChar+numCharsToDraw] - ll->positions[lineStart] + xStart;
+
+ // Adjust caret position to take into account any word wrapping symbols.
+ if ((ll->wrapIndent != 0) && (lineStart != 0)) {
+ XYPOSITION wordWrapCharWidth = ll->wrapIndent;
+ rcCaret.left += wordWrapCharWidth;
+ rcCaret.right += wordWrapCharWidth;
+ }
+
+ // This character is where the caret block is, we override the colours
+ // (inversed) for drawing the caret here.
+ int styleMain = ll->styles[offsetFirstChar];
+ surface->DrawTextClipped(rcCaret, vsDraw.styles[styleMain].font,
+ rcCaret.top + vsDraw.maxAscent, ll->chars + offsetFirstChar,
+ numCharsToDraw, vsDraw.styles[styleMain].back,
+ caretColour);
+}
+
+void Editor::RefreshPixMaps(Surface *surfaceWindow) {
+ if (!pixmapSelPattern->Initialised()) {
+ const int patternSize = 8;
+ pixmapSelPattern->InitPixMap(patternSize, patternSize, surfaceWindow, wMain.GetID());
+ pixmapSelPatternOffset1->InitPixMap(patternSize, patternSize, surfaceWindow, wMain.GetID());
+ // This complex procedure is to reproduce the checkerboard dithered pattern used by windows
+ // for scroll bars and Visual Studio for its selection margin. The colour of this pattern is half
+ // way between the chrome colour and the chrome highlight colour making a nice transition
+ // between the window chrome and the content area. And it works in low colour depths.
+ PRectangle rcPattern(0, 0, patternSize, patternSize);
+
+ // Initialize default colours based on the chrome colour scheme. Typically the highlight is white.
+ ColourDesired colourFMFill = vs.selbar;
+ ColourDesired colourFMStripes = vs.selbarlight;
+
+ if (!(vs.selbarlight == ColourDesired(0xff, 0xff, 0xff))) {
+ // User has chosen an unusual chrome colour scheme so just use the highlight edge colour.
+ // (Typically, the highlight colour is white.)
+ colourFMFill = vs.selbarlight;
+ }
+
+ if (vs.foldmarginColour.isSet) {
+ // override default fold margin colour
+ colourFMFill = vs.foldmarginColour;
+ }
+ if (vs.foldmarginHighlightColour.isSet) {
+ // override default fold margin highlight colour
+ colourFMStripes = vs.foldmarginHighlightColour;
+ }
+
+ pixmapSelPattern->FillRectangle(rcPattern, colourFMFill);
+ pixmapSelPatternOffset1->FillRectangle(rcPattern, colourFMStripes);
+ for (int y = 0; y < patternSize; y++) {
+ for (int x = y % 2; x < patternSize; x+=2) {
+ PRectangle rcPixel(x, y, x+1, y+1);
+ pixmapSelPattern->FillRectangle(rcPixel, colourFMStripes);
+ pixmapSelPatternOffset1->FillRectangle(rcPixel, colourFMFill);
+ }
+ }
+ }
+
+ if (!pixmapIndentGuide->Initialised()) {
+ // 1 extra pixel in height so can handle odd/even positions and so produce a continuous line
+ pixmapIndentGuide->InitPixMap(1, vs.lineHeight + 1, surfaceWindow, wMain.GetID());
+ pixmapIndentGuideHighlight->InitPixMap(1, vs.lineHeight + 1, surfaceWindow, wMain.GetID());
+ PRectangle rcIG(0, 0, 1, vs.lineHeight);
+ pixmapIndentGuide->FillRectangle(rcIG, vs.styles[STYLE_INDENTGUIDE].back);
+ pixmapIndentGuide->PenColour(vs.styles[STYLE_INDENTGUIDE].fore);
+ pixmapIndentGuideHighlight->FillRectangle(rcIG, vs.styles[STYLE_BRACELIGHT].back);
+ pixmapIndentGuideHighlight->PenColour(vs.styles[STYLE_BRACELIGHT].fore);
+ for (int stripe = 1; stripe < vs.lineHeight + 1; stripe += 2) {
+ PRectangle rcPixel(0, stripe, 1, stripe+1);
+ pixmapIndentGuide->FillRectangle(rcPixel, vs.styles[STYLE_INDENTGUIDE].fore);
+ pixmapIndentGuideHighlight->FillRectangle(rcPixel, vs.styles[STYLE_BRACELIGHT].fore);
+ }
+ }
+
+ if (bufferedDraw) {
+ if (!pixmapLine->Initialised()) {
+ PRectangle rcClient = GetClientRectangle();
+ pixmapLine->InitPixMap(rcClient.Width(), vs.lineHeight,
+ surfaceWindow, wMain.GetID());
+ pixmapSelMargin->InitPixMap(vs.fixedColumnWidth,
+ rcClient.Height(), surfaceWindow, wMain.GetID());
+ }
+ }
+}
+
+void Editor::DrawCarets(Surface *surface, ViewStyle &vsDraw, int lineDoc, int xStart,
+ PRectangle rcLine, LineLayout *ll, int subLine) {
+ // When drag is active it is the only caret drawn
+ bool drawDrag = posDrag.IsValid();
+ if (hideSelection && !drawDrag)
+ return;
+ const int posLineStart = pdoc->LineStart(lineDoc);
+ // For each selection draw
+ for (size_t r=0; (r<sel.Count()) || drawDrag; r++) {
+ const bool mainCaret = r == sel.Main();
+ const SelectionPosition posCaret = (drawDrag ? posDrag : sel.Range(r).caret);
+ const int offset = posCaret.Position() - posLineStart;
+ const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth;
+ const XYPOSITION virtualOffset = posCaret.VirtualSpace() * spaceWidth;
+ if (ll->InLine(offset, subLine) && offset <= ll->numCharsBeforeEOL) {
+ XYPOSITION xposCaret = ll->positions[offset] + virtualOffset - ll->positions[ll->LineStart(subLine)];
+ if (ll->wrapIndent != 0) {
+ int lineStart = ll->LineStart(subLine);
+ if (lineStart != 0) // Wrapped
+ xposCaret += ll->wrapIndent;
+ }
+ bool caretBlinkState = (caret.active && caret.on) || (!additionalCaretsBlink && !mainCaret);
+ bool caretVisibleState = additionalCaretsVisible || mainCaret;
+ if ((xposCaret >= 0) && (vsDraw.caretWidth > 0) && (vsDraw.caretStyle != CARETSTYLE_INVISIBLE) &&
+ ((posDrag.IsValid()) || (caretBlinkState && caretVisibleState))) {
+ bool caretAtEOF = false;
+ bool caretAtEOL = false;
+ bool drawBlockCaret = false;
+ XYPOSITION widthOverstrikeCaret;
+ int caretWidthOffset = 0;
+ PRectangle rcCaret = rcLine;
+
+ if (posCaret.Position() == pdoc->Length()) { // At end of document
+ caretAtEOF = true;
+ widthOverstrikeCaret = vsDraw.aveCharWidth;
+ } else if ((posCaret.Position() - posLineStart) >= ll->numCharsInLine) { // At end of line
+ caretAtEOL = true;
+ widthOverstrikeCaret = vsDraw.aveCharWidth;
+ } else {
+ widthOverstrikeCaret = ll->positions[offset + 1] - ll->positions[offset];
+ }
+ if (widthOverstrikeCaret < 3) // Make sure its visible
+ widthOverstrikeCaret = 3;
+
+ if (xposCaret > 0)
+ caretWidthOffset = 1; // Move back so overlaps both character cells.
+ xposCaret += xStart;
+ if (posDrag.IsValid()) {
+ /* Dragging text, use a line caret */
+ rcCaret.left = xposCaret - caretWidthOffset;
+ rcCaret.right = rcCaret.left + vsDraw.caretWidth;
+ } else if (inOverstrike && drawOverstrikeCaret) {
+ /* Overstrike (insert mode), use a modified bar caret */
+ rcCaret.top = rcCaret.bottom - 2;
+ rcCaret.left = xposCaret + 1;
+ rcCaret.right = rcCaret.left + widthOverstrikeCaret - 1;
+ } else if (vsDraw.caretStyle == CARETSTYLE_BLOCK) {
+ /* Block caret */
+ rcCaret.left = xposCaret;
+ if (!caretAtEOL && !caretAtEOF && (ll->chars[offset] != '\t') && !(IsControlCharacter(ll->chars[offset]))) {
+ drawBlockCaret = true;
+ rcCaret.right = xposCaret + widthOverstrikeCaret;
+ } else {
+ rcCaret.right = xposCaret + vsDraw.aveCharWidth;
+ }
+ } else {
+ /* Line caret */
+ rcCaret.left = xposCaret - caretWidthOffset;
+ rcCaret.right = rcCaret.left + vsDraw.caretWidth;
+ }
+ ColourDesired caretColour = mainCaret ? vsDraw.caretcolour : vsDraw.additionalCaretColour;
+ if (drawBlockCaret) {
+ DrawBlockCaret(surface, vsDraw, ll, subLine, xStart, offset, posCaret.Position(), rcCaret, caretColour);
+ } else {
+ surface->FillRectangle(rcCaret, caretColour);
+ }
+ }
+ }
+ if (drawDrag)
+ break;
+ }
+}
+
+void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) {
+ //Platform::DebugPrintf("Paint:%1d (%3d,%3d) ... (%3d,%3d)\n",
+ // paintingAllText, rcArea.left, rcArea.top, rcArea.right, rcArea.bottom);
+ AllocateGraphics();
+
+ RefreshStyleData();
+ if (paintState == paintAbandoned)
+ return; // Scroll bars may have changed so need redraw
+ RefreshPixMaps(surfaceWindow);
+
+ paintAbandonedByStyling = false;
+
+ StyleToPositionInView(PositionAfterArea(rcArea));
+
+ PRectangle rcClient = GetClientRectangle();
+ Point ptOrigin = GetVisibleOriginInMain();
+ //Platform::DebugPrintf("Client: (%3d,%3d) ... (%3d,%3d) %d\n",
+ // rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
+
+ int screenLinePaintFirst = rcArea.top / vs.lineHeight;
+
+ int xStart = vs.textStart - xOffset + ptOrigin.x;
+ int ypos = 0;
+ if (!bufferedDraw)
+ ypos += screenLinePaintFirst * vs.lineHeight;
+ int yposScreen = screenLinePaintFirst * vs.lineHeight;
+
+ if (NotifyUpdateUI()) {
+ RefreshStyleData();
+ RefreshPixMaps(surfaceWindow);
+ }
+
+ // Wrap the visible lines if needed.
+ if (WrapLines(wsVisible)) {
+ // The wrapping process has changed the height of some lines so
+ // abandon this paint for a complete repaint.
+ if (AbandonPaint()) {
+ return;
+ }
+ RefreshPixMaps(surfaceWindow); // In case pixmaps invalidated by scrollbar change
+ }
+ PLATFORM_ASSERT(pixmapSelPattern->Initialised());
+
+ if (!bufferedDraw)
+ surfaceWindow->SetClip(rcArea);
+
+ if (paintState != paintAbandoned) {
+ if (vs.marginInside) {
+ PaintSelMargin(surfaceWindow, rcArea);
+ PRectangle rcRightMargin = rcClient;
+ rcRightMargin.left = rcRightMargin.right - vs.rightMarginWidth;
+ if (rcArea.Intersects(rcRightMargin)) {
+ surfaceWindow->FillRectangle(rcRightMargin, vs.styles[STYLE_DEFAULT].back);
+ }
+ } else { // Else separate view so separate paint event but leftMargin included to allow overlap
+ PRectangle rcLeftMargin = rcArea;
+ rcLeftMargin.left = 0;
+ rcLeftMargin.right = rcLeftMargin.left + vs.leftMarginWidth;
+ if (rcArea.Intersects(rcLeftMargin)) {
+ surfaceWindow->FillRectangle(rcLeftMargin, vs.styles[STYLE_DEFAULT].back);
+ }
+ }
+ }
+
+ if (paintState == paintAbandoned) {
+ // Either styling or NotifyUpdateUI noticed that painting is needed
+ // outside the current painting rectangle
+ //Platform::DebugPrintf("Abandoning paint\n");
+ if (Wrapping()) {
+ if (paintAbandonedByStyling) {
+ // Styling has spilled over a line end, such as occurs by starting a multiline
+ // comment. The width of subsequent text may have changed, so rewrap.
+ NeedWrapping(cs.DocFromDisplay(topLine));
+ }
+ }
+ return;
+ }
+ //Platform::DebugPrintf("start display %d, offset = %d\n", pdoc->Length(), xOffset);
+
+ // Allow text at start of line to overlap 1 pixel into the margin as this displays
+ // serifs and italic stems for aliased text.
+ const int leftTextOverlap = ((xOffset == 0) && (vs.leftMarginWidth > 0)) ? 1 : 0;
+
+ // Do the painting
+ if (rcArea.right > vs.textStart - leftTextOverlap) {
+
+ Surface *surface = surfaceWindow;
+ if (bufferedDraw) {
+ surface = pixmapLine;
+ PLATFORM_ASSERT(pixmapLine->Initialised());
+ }
+ surface->SetUnicodeMode(IsUnicodeMode());
+ surface->SetDBCSMode(CodePage());
+
+ int visibleLine = TopLineOfMain() + screenLinePaintFirst;
+
+ SelectionPosition posCaret = sel.RangeMain().caret;
+ if (posDrag.IsValid())
+ posCaret = posDrag;
+ int lineCaret = pdoc->LineFromPosition(posCaret.Position());
+
+ PRectangle rcTextArea = rcClient;
+ if (vs.marginInside) {
+ rcTextArea.left += vs.textStart;
+ rcTextArea.right -= vs.rightMarginWidth;
+ } else {
+ rcTextArea = rcArea;
+ }
+
+ // Remove selection margin from drawing area so text will not be drawn
+ // on it in unbuffered mode.
+ if (!bufferedDraw && vs.marginInside) {
+ PRectangle rcClipText = rcTextArea;
+ rcClipText.left -= leftTextOverlap;
+ surfaceWindow->SetClip(rcClipText);
+ }
+
+ // Loop on visible lines
+ //double durLayout = 0.0;
+ //double durPaint = 0.0;
+ //double durCopy = 0.0;
+ //ElapsedTime etWhole;
+ int lineDocPrevious = -1; // Used to avoid laying out one document line multiple times
+ AutoLineLayout ll(llc, 0);
+ while (visibleLine < cs.LinesDisplayed() && yposScreen < rcArea.bottom) {
+
+ int lineDoc = cs.DocFromDisplay(visibleLine);
+ // Only visible lines should be handled by the code within the loop
+ PLATFORM_ASSERT(cs.GetVisible(lineDoc));
+ int lineStartSet = cs.DisplayFromDoc(lineDoc);
+ int subLine = visibleLine - lineStartSet;
+
+ // Copy this line and its styles from the document into local arrays
+ // and determine the x position at which each character starts.
+ //ElapsedTime et;
+ if (lineDoc != lineDocPrevious) {
+ ll.Set(0);
+ ll.Set(RetrieveLineLayout(lineDoc));
+ LayoutLine(lineDoc, surface, vs, ll, wrapWidth);
+ lineDocPrevious = lineDoc;
+ }
+ //durLayout += et.Duration(true);
+
+ if (ll) {
+ ll->containsCaret = lineDoc == lineCaret;
+ if (hideSelection) {
+ ll->containsCaret = false;
+ }
+
+ GetHotSpotRange(ll->hsStart, ll->hsEnd);
+
+ PRectangle rcLine = rcTextArea;
+ rcLine.top = ypos;
+ rcLine.bottom = ypos + vs.lineHeight;
+
+ bool bracesIgnoreStyle = false;
+ if ((vs.braceHighlightIndicatorSet && (bracesMatchStyle == STYLE_BRACELIGHT)) ||
+ (vs.braceBadLightIndicatorSet && (bracesMatchStyle == STYLE_BRACEBAD))) {
+ bracesIgnoreStyle = true;
+ }
+ Range rangeLine(pdoc->LineStart(lineDoc), pdoc->LineStart(lineDoc + 1));
+ // Highlight the current braces if any
+ ll->SetBracesHighlight(rangeLine, braces, static_cast<char>(bracesMatchStyle),
+ highlightGuideColumn * vs.spaceWidth, bracesIgnoreStyle);
+
+ if (leftTextOverlap && bufferedDraw) {
+ PRectangle rcSpacer = rcLine;
+ rcSpacer.right = rcSpacer.left;
+ rcSpacer.left -= 1;
+ surface->FillRectangle(rcSpacer, vs.styles[STYLE_DEFAULT].back);
+ }
+
+ // Draw the line
+ DrawLine(surface, vs, lineDoc, visibleLine, xStart, rcLine, ll, subLine);
+ //durPaint += et.Duration(true);
+
+ // Restore the previous styles for the brace highlights in case layout is in cache.
+ ll->RestoreBracesHighlight(rangeLine, braces, bracesIgnoreStyle);
+
+ bool expanded = cs.GetExpanded(lineDoc);
+ const int level = pdoc->GetLevel(lineDoc);
+ const int levelNext = pdoc->GetLevel(lineDoc + 1);
+ if ((level & SC_FOLDLEVELHEADERFLAG) &&
+ ((level & SC_FOLDLEVELNUMBERMASK) < (levelNext & SC_FOLDLEVELNUMBERMASK))) {
+ // Paint the line above the fold
+ if ((expanded && (foldFlags & SC_FOLDFLAG_LINEBEFORE_EXPANDED))
+ ||
+ (!expanded && (foldFlags & SC_FOLDFLAG_LINEBEFORE_CONTRACTED))) {
+ PRectangle rcFoldLine = rcLine;
+ rcFoldLine.bottom = rcFoldLine.top + 1;
+ surface->FillRectangle(rcFoldLine, vs.styles[STYLE_DEFAULT].fore);
+ }
+ // Paint the line below the fold
+ if ((expanded && (foldFlags & SC_FOLDFLAG_LINEAFTER_EXPANDED))
+ ||
+ (!expanded && (foldFlags & SC_FOLDFLAG_LINEAFTER_CONTRACTED))) {
+ PRectangle rcFoldLine = rcLine;
+ rcFoldLine.top = rcFoldLine.bottom - 1;
+ surface->FillRectangle(rcFoldLine, vs.styles[STYLE_DEFAULT].fore);
+ }
+ }
+
+ DrawCarets(surface, vs, lineDoc, xStart, rcLine, ll, subLine);
+
+ if (bufferedDraw) {
+ Point from(vs.textStart-leftTextOverlap, 0);
+ PRectangle rcCopyArea(vs.textStart-leftTextOverlap, yposScreen,
+ rcClient.right - vs.rightMarginWidth, yposScreen + vs.lineHeight);
+ surfaceWindow->Copy(rcCopyArea, from, *pixmapLine);
+ }
+
+ lineWidthMaxSeen = Platform::Maximum(
+ lineWidthMaxSeen, ll->positions[ll->numCharsInLine]);
+ //durCopy += et.Duration(true);
+ }
+
+ if (!bufferedDraw) {
+ ypos += vs.lineHeight;
+ }
+
+ yposScreen += vs.lineHeight;
+ visibleLine++;
+
+ //gdk_flush();
+ }
+ ll.Set(0);
+ //if (durPaint < 0.00000001)
+ // durPaint = 0.00000001;
+
+ // Right column limit indicator
+ PRectangle rcBeyondEOF = (vs.marginInside) ? rcClient : rcArea;
+ rcBeyondEOF.left = vs.textStart;
+ rcBeyondEOF.right = rcBeyondEOF.right - ((vs.marginInside) ? vs.rightMarginWidth : 0);
+ rcBeyondEOF.top = (cs.LinesDisplayed() - TopLineOfMain()) * vs.lineHeight;
+ if (rcBeyondEOF.top < rcBeyondEOF.bottom) {
+ surfaceWindow->FillRectangle(rcBeyondEOF, vs.styles[STYLE_DEFAULT].back);
+ if (vs.edgeState == EDGE_LINE) {
+ int edgeX = vs.theEdge * vs.spaceWidth;
+ rcBeyondEOF.left = edgeX + xStart;
+ rcBeyondEOF.right = rcBeyondEOF.left + 1;
+ surfaceWindow->FillRectangle(rcBeyondEOF, vs.edgecolour);
+ }
+ }
+ //Platform::DebugPrintf(
+ //"Layout:%9.6g Paint:%9.6g Ratio:%9.6g Copy:%9.6g Total:%9.6g\n",
+ //durLayout, durPaint, durLayout / durPaint, durCopy, etWhole.Duration());
+ NotifyPainted();
+ }
+}
+
+// Space (3 space characters) between line numbers and text when printing.
+#define lineNumberPrintSpace " "
+
+ColourDesired InvertedLight(ColourDesired orig) {
+ unsigned int r = orig.GetRed();
+ unsigned int g = orig.GetGreen();
+ unsigned int b = orig.GetBlue();
+ unsigned int l = (r + g + b) / 3; // There is a better calculation for this that matches human eye
+ unsigned int il = 0xff - l;
+ if (l == 0)
+ return ColourDesired(0xff, 0xff, 0xff);
+ r = r * il / l;
+ g = g * il / l;
+ b = b * il / l;
+ return ColourDesired(Platform::Minimum(r, 0xff), Platform::Minimum(g, 0xff), Platform::Minimum(b, 0xff));
+}
+
+// This is mostly copied from the Paint method but with some things omitted
+// such as the margin markers, line numbers, selection and caret
+// Should be merged back into a combined Draw method.
+long Editor::FormatRange(bool draw, Sci_RangeToFormat *pfr) {
+ if (!pfr)
+ return 0;
+
+ AutoSurface surface(pfr->hdc, this, SC_TECHNOLOGY_DEFAULT);
+ if (!surface)
+ return 0;
+ AutoSurface surfaceMeasure(pfr->hdcTarget, this, SC_TECHNOLOGY_DEFAULT);
+ if (!surfaceMeasure) {
+ return 0;
+ }
+
+ // Can't use measurements cached for screen
+ posCache.Clear();
+
+ ViewStyle vsPrint(vs);
+ vsPrint.technology = SC_TECHNOLOGY_DEFAULT;
+
+ // Modify the view style for printing as do not normally want any of the transient features to be printed
+ // Printing supports only the line number margin.
+ int lineNumberIndex = -1;
+ for (int margin = 0; margin <= SC_MAX_MARGIN; margin++) {
+ if ((vsPrint.ms[margin].style == SC_MARGIN_NUMBER) && (vsPrint.ms[margin].width > 0)) {
+ lineNumberIndex = margin;
+ } else {
+ vsPrint.ms[margin].width = 0;
+ }
+ }
+ vsPrint.fixedColumnWidth = 0;
+ vsPrint.zoomLevel = printParameters.magnification;
+ // Don't show indentation guides
+ // If this ever gets changed, cached pixmap would need to be recreated if technology != SC_TECHNOLOGY_DEFAULT
+ vsPrint.viewIndentationGuides = ivNone;
+ // Don't show the selection when printing
+ vsPrint.selColours.back.isSet = false;
+ vsPrint.selColours.fore.isSet = false;
+ vsPrint.selAlpha = SC_ALPHA_NOALPHA;
+ vsPrint.selAdditionalAlpha = SC_ALPHA_NOALPHA;
+ vsPrint.whitespaceColours.back.isSet = false;
+ vsPrint.whitespaceColours.fore.isSet = false;
+ vsPrint.showCaretLineBackground = false;
+ vsPrint.alwaysShowCaretLineBackground = false;
+ // Don't highlight matching braces using indicators
+ vsPrint.braceHighlightIndicatorSet = false;
+ vsPrint.braceBadLightIndicatorSet = false;
+
+ // Set colours for printing according to users settings
+ for (size_t sty = 0; sty < vsPrint.styles.size(); sty++) {
+ if (printParameters.colourMode == SC_PRINT_INVERTLIGHT) {
+ vsPrint.styles[sty].fore = InvertedLight(vsPrint.styles[sty].fore);
+ vsPrint.styles[sty].back = InvertedLight(vsPrint.styles[sty].back);
+ } else if (printParameters.colourMode == SC_PRINT_BLACKONWHITE) {
+ vsPrint.styles[sty].fore = ColourDesired(0, 0, 0);
+ vsPrint.styles[sty].back = ColourDesired(0xff, 0xff, 0xff);
+ } else if (printParameters.colourMode == SC_PRINT_COLOURONWHITE) {
+ vsPrint.styles[sty].back = ColourDesired(0xff, 0xff, 0xff);
+ } else if (printParameters.colourMode == SC_PRINT_COLOURONWHITEDEFAULTBG) {
+ if (sty <= STYLE_DEFAULT) {
+ vsPrint.styles[sty].back = ColourDesired(0xff, 0xff, 0xff);
+ }
+ }
+ }
+ // White background for the line numbers
+ vsPrint.styles[STYLE_LINENUMBER].back = ColourDesired(0xff, 0xff, 0xff);
+
+ // Printing uses different margins, so reset screen margins
+ vsPrint.leftMarginWidth = 0;
+ vsPrint.rightMarginWidth = 0;
+
+ vsPrint.Refresh(*surfaceMeasure, pdoc->tabInChars);
+ // Determining width must hapen after fonts have been realised in Refresh
+ int lineNumberWidth = 0;
+ if (lineNumberIndex >= 0) {
+ lineNumberWidth = surfaceMeasure->WidthText(vsPrint.styles[STYLE_LINENUMBER].font,
+ "99999" lineNumberPrintSpace, 5 + istrlen(lineNumberPrintSpace));
+ vsPrint.ms[lineNumberIndex].width = lineNumberWidth;
+ vsPrint.Refresh(*surfaceMeasure, pdoc->tabInChars); // Recalculate fixedColumnWidth
+ }
+
+ int linePrintStart = pdoc->LineFromPosition(pfr->chrg.cpMin);
+ int linePrintLast = linePrintStart + (pfr->rc.bottom - pfr->rc.top) / vsPrint.lineHeight - 1;
+ if (linePrintLast < linePrintStart)
+ linePrintLast = linePrintStart;
+ int linePrintMax = pdoc->LineFromPosition(pfr->chrg.cpMax);
+ if (linePrintLast > linePrintMax)
+ linePrintLast = linePrintMax;
+ //Platform::DebugPrintf("Formatting lines=[%0d,%0d,%0d] top=%0d bottom=%0d line=%0d %0d\n",
+ // linePrintStart, linePrintLast, linePrintMax, pfr->rc.top, pfr->rc.bottom, vsPrint.lineHeight,
+ // surfaceMeasure->Height(vsPrint.styles[STYLE_LINENUMBER].font));
+ int endPosPrint = pdoc->Length();
+ if (linePrintLast < pdoc->LinesTotal())
+ endPosPrint = pdoc->LineStart(linePrintLast + 1);
+
+ // Ensure we are styled to where we are formatting.
+ pdoc->EnsureStyledTo(endPosPrint);
+
+ int xStart = vsPrint.fixedColumnWidth + pfr->rc.left;
+ int ypos = pfr->rc.top;
+
+ int lineDoc = linePrintStart;
+
+ int nPrintPos = pfr->chrg.cpMin;
+ int visibleLine = 0;
+ int widthPrint = pfr->rc.right - pfr->rc.left - vsPrint.fixedColumnWidth;
+ if (printParameters.wrapState == eWrapNone)
+ widthPrint = LineLayout::wrapWidthInfinite;
+
+ while (lineDoc <= linePrintLast && ypos < pfr->rc.bottom) {
+
+ // When printing, the hdc and hdcTarget may be the same, so
+ // changing the state of surfaceMeasure may change the underlying
+ // state of surface. Therefore, any cached state is discarded before
+ // using each surface.
+ surfaceMeasure->FlushCachedState();
+
+ // Copy this line and its styles from the document into local arrays
+ // and determine the x position at which each character starts.
+ LineLayout ll(pdoc->LineStart(lineDoc+1)-pdoc->LineStart(lineDoc)+1);
+ LayoutLine(lineDoc, surfaceMeasure, vsPrint, &ll, widthPrint);
+
+ ll.containsCaret = false;
+
+ PRectangle rcLine;
+ rcLine.left = pfr->rc.left;
+ rcLine.top = ypos;
+ rcLine.right = pfr->rc.right - 1;
+ rcLine.bottom = ypos + vsPrint.lineHeight;
+
+ // When document line is wrapped over multiple display lines, find where
+ // to start printing from to ensure a particular position is on the first
+ // line of the page.
+ if (visibleLine == 0) {
+ int startWithinLine = nPrintPos - pdoc->LineStart(lineDoc);
+ for (int iwl = 0; iwl < ll.lines - 1; iwl++) {
+ if (ll.LineStart(iwl) <= startWithinLine && ll.LineStart(iwl + 1) >= startWithinLine) {
+ visibleLine = -iwl;
+ }
+ }
+
+ if (ll.lines > 1 && startWithinLine >= ll.LineStart(ll.lines - 1)) {
+ visibleLine = -(ll.lines - 1);
+ }
+ }
+
+ if (draw && lineNumberWidth &&
+ (ypos + vsPrint.lineHeight <= pfr->rc.bottom) &&
+ (visibleLine >= 0)) {
+ char number[100];
+ sprintf(number, "%d" lineNumberPrintSpace, lineDoc + 1);
+ PRectangle rcNumber = rcLine;
+ rcNumber.right = rcNumber.left + lineNumberWidth;
+ // Right justify
+ rcNumber.left = rcNumber.right - surfaceMeasure->WidthText(
+ vsPrint.styles[STYLE_LINENUMBER].font, number, istrlen(number));
+ surface->FlushCachedState();
+ surface->DrawTextNoClip(rcNumber, vsPrint.styles[STYLE_LINENUMBER].font,
+ ypos + vsPrint.maxAscent, number, istrlen(number),
+ vsPrint.styles[STYLE_LINENUMBER].fore,
+ vsPrint.styles[STYLE_LINENUMBER].back);
+ }
+
+ // Draw the line
+ surface->FlushCachedState();
+
+ for (int iwl = 0; iwl < ll.lines; iwl++) {
+ if (ypos + vsPrint.lineHeight <= pfr->rc.bottom) {
+ if (visibleLine >= 0) {
+ if (draw) {
+ rcLine.top = ypos;
+ rcLine.bottom = ypos + vsPrint.lineHeight;
+ DrawLine(surface, vsPrint, lineDoc, visibleLine, xStart, rcLine, &ll, iwl);
+ }
+ ypos += vsPrint.lineHeight;
+ }
+ visibleLine++;
+ if (iwl == ll.lines - 1)
+ nPrintPos = pdoc->LineStart(lineDoc + 1);
+ else
+ nPrintPos += ll.LineStart(iwl + 1) - ll.LineStart(iwl);
+ }
+ }
+
+ ++lineDoc;
+ }
+
+ // Clear cache so measurements are not used for screen
+ posCache.Clear();
+
+ return nPrintPos;
+}
+
+int Editor::TextWidth(int style, const char *text) {
+ RefreshStyleData();
+ AutoSurface surface(this);
+ if (surface) {
+ return surface->WidthText(vs.styles[style].font, text, istrlen(text));
+ } else {
+ return 1;
+ }
+}
+
+// Empty method is overridden on GTK+ to show / hide scrollbars
+void Editor::ReconfigureScrollBars() {}
+
+void Editor::SetScrollBars() {
+ RefreshStyleData();
+
+ int nMax = MaxScrollPos();
+ int nPage = LinesOnScreen();
+ bool modified = ModifyScrollBars(nMax + nPage - 1, nPage);
+ if (modified) {
+ DwellEnd(true);
+ }
+
+ // TODO: ensure always showing as many lines as possible
+ // May not be, if, for example, window made larger
+ if (topLine > MaxScrollPos()) {
+ SetTopLine(Platform::Clamp(topLine, 0, MaxScrollPos()));
+ SetVerticalScrollPos();
+ Redraw();
+ }
+ if (modified) {
+ if (!AbandonPaint())
+ Redraw();
+ }
+ //Platform::DebugPrintf("end max = %d page = %d\n", nMax, nPage);
+}
+
+void Editor::ChangeSize() {
+ DropGraphics(false);
+ SetScrollBars();
+ if (Wrapping()) {
+ PRectangle rcTextArea = GetClientRectangle();
+ rcTextArea.left = vs.textStart;
+ rcTextArea.right -= vs.rightMarginWidth;
+ if (wrapWidth != rcTextArea.Width()) {
+ NeedWrapping();
+ Redraw();
+ }
+ }
+}
+
+int Editor::InsertSpace(int position, unsigned int spaces) {
+ if (spaces > 0) {
+ std::string spaceText(spaces, ' ');
+ pdoc->InsertString(position, spaceText.c_str(), spaces);
+ position += spaces;
+ }
+ return position;
+}
+
+void Editor::AddChar(char ch) {
+ char s[2];
+ s[0] = ch;
+ s[1] = '\0';
+ AddCharUTF(s, 1);
+}
+
+void Editor::FilterSelections() {
+ if (!additionalSelectionTyping && (sel.Count() > 1)) {
+ SelectionRange rangeOnly = sel.RangeMain();
+ InvalidateSelection(rangeOnly, true);
+ sel.SetSelection(rangeOnly);
+ }
+}
+
+static bool cmpSelPtrs(const SelectionRange *a, const SelectionRange *b) {
+ return *a < *b;
+}
+
+// AddCharUTF inserts an array of bytes which may or may not be in UTF-8.
+void Editor::AddCharUTF(char *s, unsigned int len, bool treatAsDBCS) {
+ FilterSelections();
+ {
+ UndoGroup ug(pdoc, (sel.Count() > 1) || !sel.Empty() || inOverstrike);
+
+ std::vector<SelectionRange *> selPtrs;
+ for (size_t r = 0; r < sel.Count(); r++) {
+ selPtrs.push_back(&sel.Range(r));
+ }
+ std::sort(selPtrs.begin(), selPtrs.end(), cmpSelPtrs);
+
+ for (std::vector<SelectionRange *>::reverse_iterator rit = selPtrs.rbegin();
+ rit != selPtrs.rend(); ++rit) {
+ SelectionRange *currentSel = *rit;
+ if (!RangeContainsProtected(currentSel->Start().Position(),
+ currentSel->End().Position())) {
+ int positionInsert = currentSel->Start().Position();
+ if (!currentSel->Empty()) {
+ if (currentSel->Length()) {
+ pdoc->DeleteChars(positionInsert, currentSel->Length());
+ currentSel->ClearVirtualSpace();
+ } else {
+ // Range is all virtual so collapse to start of virtual space
+ currentSel->MinimizeVirtualSpace();
+ }
+ } else if (inOverstrike) {
+ if (positionInsert < pdoc->Length()) {
+ if (!pdoc->IsPositionInLineEnd(positionInsert)) {
+ pdoc->DelChar(positionInsert);
+ currentSel->ClearVirtualSpace();
+ }
+ }
+ }
+ positionInsert = InsertSpace(positionInsert, currentSel->caret.VirtualSpace());
+ if (pdoc->InsertString(positionInsert, s, len)) {
+ currentSel->caret.SetPosition(positionInsert + len);
+ currentSel->anchor.SetPosition(positionInsert + len);
+ }
+ currentSel->ClearVirtualSpace();
+ // If in wrap mode rewrap current line so EnsureCaretVisible has accurate information
+ if (Wrapping()) {
+ AutoSurface surface(this);
+ if (surface) {
+ if (WrapOneLine(surface, pdoc->LineFromPosition(positionInsert))) {
+ SetScrollBars();
+ SetVerticalScrollPos();
+ Redraw();
+ }
+ }
+ }
+ }
+ }
+ }
+ if (Wrapping()) {
+ SetScrollBars();
+ }
+ ThinRectangularRange();
+ // If in wrap mode rewrap current line so EnsureCaretVisible has accurate information
+ EnsureCaretVisible();
+ // Avoid blinking during rapid typing:
+ ShowCaretAtCurrentPosition();
+ if ((caretSticky == SC_CARETSTICKY_OFF) ||
+ ((caretSticky == SC_CARETSTICKY_WHITESPACE) && !IsAllSpacesOrTabs(s, len))) {
+ SetLastXChosen();
+ }
+
+ if (treatAsDBCS) {
+ NotifyChar((static_cast<unsigned char>(s[0]) << 8) |
+ static_cast<unsigned char>(s[1]));
+ } else if (len > 0) {
+ int byte = static_cast<unsigned char>(s[0]);
+ if ((byte < 0xC0) || (1 == len)) {
+ // Handles UTF-8 characters between 0x01 and 0x7F and single byte
+ // characters when not in UTF-8 mode.
+ // Also treats \0 and naked trail bytes 0x80 to 0xBF as valid
+ // characters representing themselves.
+ } else {
+ // Unroll 1 to 3 byte UTF-8 sequences. See reference data at:
+ // http://www.cl.cam.ac.uk/~mgk25/unicode.html
+ // http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
+ if (byte < 0xE0) {
+ int byte2 = static_cast<unsigned char>(s[1]);
+ if ((byte2 & 0xC0) == 0x80) {
+ // Two-byte-character lead-byte followed by a trail-byte.
+ byte = (((byte & 0x1F) << 6) | (byte2 & 0x3F));
+ }
+ // A two-byte-character lead-byte not followed by trail-byte
+ // represents itself.
+ } else if (byte < 0xF0) {
+ int byte2 = static_cast<unsigned char>(s[1]);
+ int byte3 = static_cast<unsigned char>(s[2]);
+ if (((byte2 & 0xC0) == 0x80) && ((byte3 & 0xC0) == 0x80)) {
+ // Three-byte-character lead byte followed by two trail bytes.
+ byte = (((byte & 0x0F) << 12) | ((byte2 & 0x3F) << 6) |
+ (byte3 & 0x3F));
+ }
+ // A three-byte-character lead-byte not followed by two trail-bytes
+ // represents itself.
+ }
+ }
+ NotifyChar(byte);
+ }
+
+ if (recordingMacro) {
+ NotifyMacroRecord(SCI_REPLACESEL, 0, reinterpret_cast<sptr_t>(s));
+ }
+}
+
+void Editor::InsertPaste(SelectionPosition selStart, const char *text, int len) {
+ if (multiPasteMode == SC_MULTIPASTE_ONCE) {
+ selStart = SelectionPosition(InsertSpace(selStart.Position(), selStart.VirtualSpace()));
+ if (pdoc->InsertString(selStart.Position(), text, len)) {
+ SetEmptySelection(selStart.Position() + len);
+ }
+ } else {
+ // SC_MULTIPASTE_EACH
+ for (size_t r=0; r<sel.Count(); r++) {
+ if (!RangeContainsProtected(sel.Range(r).Start().Position(),
+ sel.Range(r).End().Position())) {
+ int positionInsert = sel.Range(r).Start().Position();
+ if (!sel.Range(r).Empty()) {
+ if (sel.Range(r).Length()) {
+ pdoc->DeleteChars(positionInsert, sel.Range(r).Length());
+ sel.Range(r).ClearVirtualSpace();
+ } else {
+ // Range is all virtual so collapse to start of virtual space
+ sel.Range(r).MinimizeVirtualSpace();
+ }
+ }
+ positionInsert = InsertSpace(positionInsert, sel.Range(r).caret.VirtualSpace());
+ if (pdoc->InsertString(positionInsert, text, len)) {
+ sel.Range(r).caret.SetPosition(positionInsert + len);
+ sel.Range(r).anchor.SetPosition(positionInsert + len);
+ }
+ sel.Range(r).ClearVirtualSpace();
+ }
+ }
+ }
+}
+
+void Editor::ClearSelection(bool retainMultipleSelections) {
+ if (!sel.IsRectangular() && !retainMultipleSelections)
+ FilterSelections();
+ UndoGroup ug(pdoc);
+ for (size_t r=0; r<sel.Count(); r++) {
+ if (!sel.Range(r).Empty()) {
+ if (!RangeContainsProtected(sel.Range(r).Start().Position(),
+ sel.Range(r).End().Position())) {
+ pdoc->DeleteChars(sel.Range(r).Start().Position(),
+ sel.Range(r).Length());
+ sel.Range(r) = sel.Range(r).Start();
+ }
+ }
+ }
+ ThinRectangularRange();
+ sel.RemoveDuplicates();
+ ClaimSelection();
+}
+
+void Editor::ClearAll() {
+ {
+ UndoGroup ug(pdoc);
+ if (0 != pdoc->Length()) {
+ pdoc->DeleteChars(0, pdoc->Length());
+ }
+ if (!pdoc->IsReadOnly()) {
+ cs.Clear();
+ pdoc->AnnotationClearAll();
+ pdoc->MarginClearAll();
+ }
+ }
+ sel.Clear();
+ SetTopLine(0);
+ SetVerticalScrollPos();
+ InvalidateStyleRedraw();
+}
+
+void Editor::ClearDocumentStyle() {
+ Decoration *deco = pdoc->decorations.root;
+ while (deco) {
+ // Save next in case deco deleted
+ Decoration *decoNext = deco->next;
+ if (deco->indicator < INDIC_CONTAINER) {
+ pdoc->decorations.SetCurrentIndicator(deco->indicator);
+ pdoc->DecorationFillRange(0, 0, pdoc->Length());
+ }
+ deco = decoNext;
+ }
+ pdoc->StartStyling(0, '\377');
+ pdoc->SetStyleFor(pdoc->Length(), 0);
+ cs.ShowAll();
+ pdoc->ClearLevels();
+}
+
+void Editor::CopyAllowLine() {
+ SelectionText selectedText;
+ CopySelectionRange(&selectedText, true);
+ CopyToClipboard(selectedText);
+}
+
+void Editor::Cut() {
+ pdoc->CheckReadOnly();
+ if (!pdoc->IsReadOnly() && !SelectionContainsProtected()) {
+ Copy();
+ ClearSelection();
+ }
+}
+
+void Editor::PasteRectangular(SelectionPosition pos, const char *ptr, int len) {
+ if (pdoc->IsReadOnly() || SelectionContainsProtected()) {
+ return;
+ }
+ sel.Clear();
+ sel.RangeMain() = SelectionRange(pos);
+ int line = pdoc->LineFromPosition(sel.MainCaret());
+ UndoGroup ug(pdoc);
+ sel.RangeMain().caret = SelectionPosition(
+ InsertSpace(sel.RangeMain().caret.Position(), sel.RangeMain().caret.VirtualSpace()));
+ int xInsert = XFromPosition(sel.RangeMain().caret);
+ bool prevCr = false;
+ while ((len > 0) && IsEOLChar(ptr[len-1]))
+ len--;
+ for (int i = 0; i < len; i++) {
+ if (IsEOLChar(ptr[i])) {
+ if ((ptr[i] == '\r') || (!prevCr))
+ line++;
+ if (line >= pdoc->LinesTotal()) {
+ if (pdoc->eolMode != SC_EOL_LF)
+ pdoc->InsertChar(pdoc->Length(), '\r');
+ if (pdoc->eolMode != SC_EOL_CR)
+ pdoc->InsertChar(pdoc->Length(), '\n');
+ }
+ // Pad the end of lines with spaces if required
+ sel.RangeMain().caret.SetPosition(PositionFromLineX(line, xInsert));
+ if ((XFromPosition(sel.MainCaret()) < xInsert) && (i + 1 < len)) {
+ while (XFromPosition(sel.MainCaret()) < xInsert) {
+ pdoc->InsertChar(sel.MainCaret(), ' ');
+ sel.RangeMain().caret.Add(1);
+ }
+ }
+ prevCr = ptr[i] == '\r';
+ } else {
+ pdoc->InsertString(sel.MainCaret(), ptr + i, 1);
+ sel.RangeMain().caret.Add(1);
+ prevCr = false;
+ }
+ }
+ SetEmptySelection(pos);
+}
+
+bool Editor::CanPaste() {
+ return !pdoc->IsReadOnly() && !SelectionContainsProtected();
+}
+
+void Editor::Clear() {
+ // If multiple selections, don't delete EOLS
+ if (sel.Empty()) {
+ bool singleVirtual = false;
+ if ((sel.Count() == 1) &&
+ !RangeContainsProtected(sel.MainCaret(), sel.MainCaret() + 1) &&
+ sel.RangeMain().Start().VirtualSpace()) {
+ singleVirtual = true;
+ }
+ UndoGroup ug(pdoc, (sel.Count() > 1) || singleVirtual);
+ for (size_t r=0; r<sel.Count(); r++) {
+ if (!RangeContainsProtected(sel.Range(r).caret.Position(), sel.Range(r).caret.Position() + 1)) {
+ if (sel.Range(r).Start().VirtualSpace()) {
+ if (sel.Range(r).anchor < sel.Range(r).caret)
+ sel.Range(r) = SelectionPosition(InsertSpace(sel.Range(r).anchor.Position(), sel.Range(r).anchor.VirtualSpace()));
+ else
+ sel.Range(r) = SelectionPosition(InsertSpace(sel.Range(r).caret.Position(), sel.Range(r).caret.VirtualSpace()));
+ }
+ if ((sel.Count() == 1) || !pdoc->IsPositionInLineEnd(sel.Range(r).caret.Position())) {
+ pdoc->DelChar(sel.Range(r).caret.Position());
+ sel.Range(r).ClearVirtualSpace();
+ } // else multiple selection so don't eat line ends
+ } else {
+ sel.Range(r).ClearVirtualSpace();
+ }
+ }
+ } else {
+ ClearSelection();
+ }
+ sel.RemoveDuplicates();
+}
+
+void Editor::SelectAll() {
+ sel.Clear();
+ SetSelection(0, pdoc->Length());
+ Redraw();
+}
+
+void Editor::Undo() {
+ if (pdoc->CanUndo()) {
+ InvalidateCaret();
+ int newPos = pdoc->Undo();
+ if (newPos >= 0)
+ SetEmptySelection(newPos);
+ EnsureCaretVisible();
+ }
+}
+
+void Editor::Redo() {
+ if (pdoc->CanRedo()) {
+ int newPos = pdoc->Redo();
+ if (newPos >= 0)
+ SetEmptySelection(newPos);
+ EnsureCaretVisible();
+ }
+}
+
+void Editor::DelChar() {
+ if (!RangeContainsProtected(sel.MainCaret(), sel.MainCaret() + 1)) {
+ pdoc->DelChar(sel.MainCaret());
+ }
+ // Avoid blinking during rapid typing:
+ ShowCaretAtCurrentPosition();
+}
+
+void Editor::DelCharBack(bool allowLineStartDeletion) {
+ if (!sel.IsRectangular())
+ FilterSelections();
+ if (sel.IsRectangular())
+ allowLineStartDeletion = false;
+ UndoGroup ug(pdoc, (sel.Count() > 1) || !sel.Empty());
+ if (sel.Empty()) {
+ for (size_t r=0; r<sel.Count(); r++) {
+ if (!RangeContainsProtected(sel.Range(r).caret.Position() - 1, sel.Range(r).caret.Position())) {
+ if (sel.Range(r).caret.VirtualSpace()) {
+ sel.Range(r).caret.SetVirtualSpace(sel.Range(r).caret.VirtualSpace() - 1);
+ sel.Range(r).anchor.SetVirtualSpace(sel.Range(r).caret.VirtualSpace());
+ } else {
+ int lineCurrentPos = pdoc->LineFromPosition(sel.Range(r).caret.Position());
+ if (allowLineStartDeletion || (pdoc->LineStart(lineCurrentPos) != sel.Range(r).caret.Position())) {
+ if (pdoc->GetColumn(sel.Range(r).caret.Position()) <= pdoc->GetLineIndentation(lineCurrentPos) &&
+ pdoc->GetColumn(sel.Range(r).caret.Position()) > 0 && pdoc->backspaceUnindents) {
+ UndoGroup ugInner(pdoc, !ug.Needed());
+ int indentation = pdoc->GetLineIndentation(lineCurrentPos);
+ int indentationStep = pdoc->IndentSize();
+ if (indentation % indentationStep == 0) {
+ pdoc->SetLineIndentation(lineCurrentPos, indentation - indentationStep);
+ } else {
+ pdoc->SetLineIndentation(lineCurrentPos, indentation - (indentation % indentationStep));
+ }
+ // SetEmptySelection
+ sel.Range(r) = SelectionRange(pdoc->GetLineIndentPosition(lineCurrentPos),
+ pdoc->GetLineIndentPosition(lineCurrentPos));
+ } else {
+ pdoc->DelCharBack(sel.Range(r).caret.Position());
+ }
+ }
+ }
+ } else {
+ sel.Range(r).ClearVirtualSpace();
+ }
+ }
+ ThinRectangularRange();
+ } else {
+ ClearSelection();
+ }
+ sel.RemoveDuplicates();
+ ContainerNeedsUpdate(SC_UPDATE_SELECTION);
+ // Avoid blinking during rapid typing:
+ ShowCaretAtCurrentPosition();
+}
+
+void Editor::NotifyFocus(bool) {}
+
+void Editor::SetCtrlID(int identifier) {
+ ctrlID = identifier;
+}
+
+void Editor::NotifyStyleToNeeded(int endStyleNeeded) {
+ SCNotification scn = {0};
+ scn.nmhdr.code = SCN_STYLENEEDED;
+ scn.position = endStyleNeeded;
+ NotifyParent(scn);
+}
+
+void Editor::NotifyStyleNeeded(Document *, void *, int endStyleNeeded) {
+ NotifyStyleToNeeded(endStyleNeeded);
+}
+
+void Editor::NotifyLexerChanged(Document *, void *) {
+}
+
+void Editor::NotifyErrorOccurred(Document *, void *, int status) {
+ errorStatus = status;
+}
+
+void Editor::NotifyChar(int ch) {
+ SCNotification scn = {0};
+ scn.nmhdr.code = SCN_CHARADDED;
+ scn.ch = ch;
+ NotifyParent(scn);
+}
+
+void Editor::NotifySavePoint(bool isSavePoint) {
+ SCNotification scn = {0};
+ if (isSavePoint) {
+ scn.nmhdr.code = SCN_SAVEPOINTREACHED;
+ } else {
+ scn.nmhdr.code = SCN_SAVEPOINTLEFT;
+ }
+ NotifyParent(scn);
+}
+
+void Editor::NotifyModifyAttempt() {
+ SCNotification scn = {0};
+ scn.nmhdr.code = SCN_MODIFYATTEMPTRO;
+ NotifyParent(scn);
+}
+
+void Editor::NotifyDoubleClick(Point pt, bool shift, bool ctrl, bool alt) {
+ SCNotification scn = {0};
+ scn.nmhdr.code = SCN_DOUBLECLICK;
+ scn.line = LineFromLocation(pt);
+ scn.position = PositionFromLocation(pt, true);
+ scn.modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |
+ (alt ? SCI_ALT : 0);
+ NotifyParent(scn);
+}
+
+void Editor::NotifyHotSpotDoubleClicked(int position, bool shift, bool ctrl, bool alt) {
+ SCNotification scn = {0};
+ scn.nmhdr.code = SCN_HOTSPOTDOUBLECLICK;
+ scn.position = position;
+ scn.modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |
+ (alt ? SCI_ALT : 0);
+ NotifyParent(scn);
+}
+
+void Editor::NotifyHotSpotClicked(int position, bool shift, bool ctrl, bool alt) {
+ SCNotification scn = {0};
+ scn.nmhdr.code = SCN_HOTSPOTCLICK;
+ scn.position = position;
+ scn.modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |
+ (alt ? SCI_ALT : 0);
+ NotifyParent(scn);
+}
+
+void Editor::NotifyHotSpotReleaseClick(int position, bool shift, bool ctrl, bool alt) {
+ SCNotification scn = {0};
+ scn.nmhdr.code = SCN_HOTSPOTRELEASECLICK;
+ scn.position = position;
+ scn.modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |
+ (alt ? SCI_ALT : 0);
+ NotifyParent(scn);
+}
+
+bool Editor::NotifyUpdateUI() {
+ if (needUpdateUI) {
+ SCNotification scn = {0};
+ scn.nmhdr.code = SCN_UPDATEUI;
+ scn.updated = needUpdateUI;
+ NotifyParent(scn);
+ needUpdateUI = 0;
+ return true;
+ }
+ return false;
+}
+
+void Editor::NotifyPainted() {
+ SCNotification scn = {0};
+ scn.nmhdr.code = SCN_PAINTED;
+ NotifyParent(scn);
+}
+
+void Editor::NotifyIndicatorClick(bool click, int position, bool shift, bool ctrl, bool alt) {
+ int mask = pdoc->decorations.AllOnFor(position);
+ if ((click && mask) || pdoc->decorations.clickNotified) {
+ SCNotification scn = {0};
+ pdoc->decorations.clickNotified = click;
+ scn.nmhdr.code = click ? SCN_INDICATORCLICK : SCN_INDICATORRELEASE;
+ scn.modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) | (alt ? SCI_ALT : 0);
+ scn.position = position;
+ NotifyParent(scn);
+ }
+}
+
+bool Editor::NotifyMarginClick(Point pt, bool shift, bool ctrl, bool alt) {
+ int marginClicked = -1;
+ int x = vs.textStart - vs.fixedColumnWidth;
+ for (int margin = 0; margin <= SC_MAX_MARGIN; margin++) {
+ if ((pt.x >= x) && (pt.x < x + vs.ms[margin].width))
+ marginClicked = margin;
+ x += vs.ms[margin].width;
+ }
+ if ((marginClicked >= 0) && vs.ms[marginClicked].sensitive) {
+ int position = pdoc->LineStart(LineFromLocation(pt));
+ if ((vs.ms[marginClicked].mask & SC_MASK_FOLDERS) && (foldAutomatic & SC_AUTOMATICFOLD_CLICK)) {
+ int lineClick = pdoc->LineFromPosition(position);
+ if (shift && ctrl) {
+ FoldAll(SC_FOLDACTION_TOGGLE);
+ } else {
+ int levelClick = pdoc->GetLevel(lineClick);
+ if (levelClick & SC_FOLDLEVELHEADERFLAG) {
+ if (shift) {
+ // Ensure all children visible
+ FoldExpand(lineClick, SC_FOLDACTION_EXPAND, levelClick);
+ } else if (ctrl) {
+ FoldExpand(lineClick, SC_FOLDACTION_TOGGLE, levelClick);
+ } else {
+ // Toggle this line
+ FoldLine(lineClick, SC_FOLDACTION_TOGGLE);
+ }
+ }
+ }
+ return true;
+ }
+ SCNotification scn = {0};
+ scn.nmhdr.code = SCN_MARGINCLICK;
+ scn.modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |
+ (alt ? SCI_ALT : 0);
+ scn.position = position;
+ scn.margin = marginClicked;
+ NotifyParent(scn);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void Editor::NotifyNeedShown(int pos, int len) {
+ SCNotification scn = {0};
+ scn.nmhdr.code = SCN_NEEDSHOWN;
+ scn.position = pos;
+ scn.length = len;
+ NotifyParent(scn);
+}
+
+void Editor::NotifyDwelling(Point pt, bool state) {
+ SCNotification scn = {0};
+ scn.nmhdr.code = state ? SCN_DWELLSTART : SCN_DWELLEND;
+ scn.position = PositionFromLocation(pt, true);
+ scn.x = pt.x + vs.ExternalMarginWidth();
+ scn.y = pt.y;
+ NotifyParent(scn);
+}
+
+void Editor::NotifyZoom() {
+ SCNotification scn = {0};
+ scn.nmhdr.code = SCN_ZOOM;
+ NotifyParent(scn);
+}
+
+// Notifications from document
+void Editor::NotifyModifyAttempt(Document *, void *) {
+ //Platform::DebugPrintf("** Modify Attempt\n");
+ NotifyModifyAttempt();
+}
+
+void Editor::NotifySavePoint(Document *, void *, bool atSavePoint) {
+ //Platform::DebugPrintf("** Save Point %s\n", atSavePoint ? "On" : "Off");
+ NotifySavePoint(atSavePoint);
+}
+
+void Editor::CheckModificationForWrap(DocModification mh) {
+ if (mh.modificationType & (SC_MOD_INSERTTEXT | SC_MOD_DELETETEXT)) {
+ llc.Invalidate(LineLayout::llCheckTextAndStyle);
+ int lineDoc = pdoc->LineFromPosition(mh.position);
+ int lines = Platform::Maximum(0, mh.linesAdded);
+ if (Wrapping()) {
+ NeedWrapping(lineDoc, lineDoc + lines + 1);
+ }
+ RefreshStyleData();
+ // Fix up annotation heights
+ SetAnnotationHeights(lineDoc, lineDoc + lines + 2);
+ }
+}
+
+// Move a position so it is still after the same character as before the insertion.
+static inline int MovePositionForInsertion(int position, int startInsertion, int length) {
+ if (position > startInsertion) {
+ return position + length;
+ }
+ return position;
+}
+
+// Move a position so it is still after the same character as before the deletion if that
+// character is still present else after the previous surviving character.
+static inline int MovePositionForDeletion(int position, int startDeletion, int length) {
+ if (position > startDeletion) {
+ int endDeletion = startDeletion + length;
+ if (position > endDeletion) {
+ return position - length;
+ } else {
+ return startDeletion;
+ }
+ } else {
+ return position;
+ }
+}
+
+void Editor::NotifyModified(Document *, DocModification mh, void *) {
+ ContainerNeedsUpdate(SC_UPDATE_CONTENT);
+ if (paintState == painting) {
+ CheckForChangeOutsidePaint(Range(mh.position, mh.position + mh.length));
+ }
+ if (mh.modificationType & SC_MOD_CHANGELINESTATE) {
+ if (paintState == painting) {
+ CheckForChangeOutsidePaint(
+ Range(pdoc->LineStart(mh.line), pdoc->LineStart(mh.line + 1)));
+ } else {
+ // Could check that change is before last visible line.
+ Redraw();
+ }
+ }
+ if (mh.modificationType & SC_MOD_LEXERSTATE) {
+ if (paintState == painting) {
+ CheckForChangeOutsidePaint(
+ Range(mh.position, mh.position + mh.length));
+ } else {
+ Redraw();
+ }
+ }
+ if (mh.modificationType & (SC_MOD_CHANGESTYLE | SC_MOD_CHANGEINDICATOR)) {
+ if (mh.modificationType & SC_MOD_CHANGESTYLE) {
+ pdoc->IncrementStyleClock();
+ }
+ if (paintState == notPainting) {
+ if (mh.position < pdoc->LineStart(topLine)) {
+ // Styling performed before this view
+ Redraw();
+ } else {
+ InvalidateRange(mh.position, mh.position + mh.length);
+ }
+ }
+ if (mh.modificationType & SC_MOD_CHANGESTYLE) {
+ llc.Invalidate(LineLayout::llCheckTextAndStyle);
+ }
+ } else {
+ // Move selection and brace highlights
+ if (mh.modificationType & SC_MOD_INSERTTEXT) {
+ sel.MovePositions(true, mh.position, mh.length);
+ braces[0] = MovePositionForInsertion(braces[0], mh.position, mh.length);
+ braces[1] = MovePositionForInsertion(braces[1], mh.position, mh.length);
+ } else if (mh.modificationType & SC_MOD_DELETETEXT) {
+ sel.MovePositions(false, mh.position, mh.length);
+ braces[0] = MovePositionForDeletion(braces[0], mh.position, mh.length);
+ braces[1] = MovePositionForDeletion(braces[1], mh.position, mh.length);
+ }
+ if ((mh.modificationType & (SC_MOD_BEFOREINSERT | SC_MOD_BEFOREDELETE)) && cs.HiddenLines()) {
+ // Some lines are hidden so may need shown.
+ // TODO: check if the modified area is hidden.
+ if (mh.modificationType & SC_MOD_BEFOREINSERT) {
+ int lineOfPos = pdoc->LineFromPosition(mh.position);
+ bool insertingNewLine = false;
+ for (int i=0; i < mh.length; i++) {
+ if ((mh.text[i] == '\n') || (mh.text[i] == '\r'))
+ insertingNewLine = true;
+ }
+ if (insertingNewLine && (mh.position != pdoc->LineStart(lineOfPos)))
+ NeedShown(mh.position, pdoc->LineStart(lineOfPos+1) - mh.position);
+ else
+ NeedShown(mh.position, 0);
+ } else if (mh.modificationType & SC_MOD_BEFOREDELETE) {
+ NeedShown(mh.position, mh.length);
+ }
+ }
+ if (mh.linesAdded != 0) {
+ // Update contraction state for inserted and removed lines
+ // lineOfPos should be calculated in context of state before modification, shouldn't it
+ int lineOfPos = pdoc->LineFromPosition(mh.position);
+ if (mh.position > pdoc->LineStart(lineOfPos))
+ lineOfPos++; // Affecting subsequent lines
+ if (mh.linesAdded > 0) {
+ cs.InsertLines(lineOfPos, mh.linesAdded);
+ } else {
+ cs.DeleteLines(lineOfPos, -mh.linesAdded);
+ }
+ }
+ if (mh.modificationType & SC_MOD_CHANGEANNOTATION) {
+ int lineDoc = pdoc->LineFromPosition(mh.position);
+ if (vs.annotationVisible) {
+ cs.SetHeight(lineDoc, cs.GetHeight(lineDoc) + mh.annotationLinesAdded);
+ Redraw();
+ }
+ }
+ CheckModificationForWrap(mh);
+ if (mh.linesAdded != 0) {
+ // Avoid scrolling of display if change before current display
+ if (mh.position < posTopLine && !CanDeferToLastStep(mh)) {
+ int newTop = Platform::Clamp(topLine + mh.linesAdded, 0, MaxScrollPos());
+ if (newTop != topLine) {
+ SetTopLine(newTop);
+ SetVerticalScrollPos();
+ }
+ }
+
+ if (paintState == notPainting && !CanDeferToLastStep(mh)) {
+ QueueIdleWork(WorkNeeded::workStyle, pdoc->Length());
+ Redraw();
+ }
+ } else {
+ if (paintState == notPainting && mh.length && !CanEliminate(mh)) {
+ QueueIdleWork(WorkNeeded::workStyle, mh.position + mh.length);
+ InvalidateRange(mh.position, mh.position + mh.length);
+ }
+ }
+ }
+
+ if (mh.linesAdded != 0 && !CanDeferToLastStep(mh)) {
+ SetScrollBars();
+ }
+
+ if ((mh.modificationType & SC_MOD_CHANGEMARKER) || (mh.modificationType & SC_MOD_CHANGEMARGIN)) {
+ if ((!willRedrawAll) && ((paintState == notPainting) || !PaintContainsMargin())) {
+ if (mh.modificationType & SC_MOD_CHANGEFOLD) {
+ // Fold changes can affect the drawing of following lines so redraw whole margin
+ RedrawSelMargin(highlightDelimiter.isEnabled ? -1 : mh.line-1, true);
+ } else {
+ RedrawSelMargin(mh.line);
+ }
+ }
+ }
+ if ((mh.modificationType & SC_MOD_CHANGEFOLD) && (foldAutomatic & SC_AUTOMATICFOLD_CHANGE)) {
+ FoldChanged(mh.line, mh.foldLevelNow, mh.foldLevelPrev);
+ }
+
+ // NOW pay the piper WRT "deferred" visual updates
+ if (IsLastStep(mh)) {
+ SetScrollBars();
+ Redraw();
+ }
+
+ // If client wants to see this modification
+ if (mh.modificationType & modEventMask) {
+ if ((mh.modificationType & (SC_MOD_CHANGESTYLE | SC_MOD_CHANGEINDICATOR)) == 0) {
+ // Real modification made to text of document.
+ NotifyChange(); // Send EN_CHANGE
+ }
+
+ SCNotification scn = {0};
+ scn.nmhdr.code = SCN_MODIFIED;
+ scn.position = mh.position;
+ scn.modificationType = mh.modificationType;
+ scn.text = mh.text;
+ scn.length = mh.length;
+ scn.linesAdded = mh.linesAdded;
+ scn.line = mh.line;
+ scn.foldLevelNow = mh.foldLevelNow;
+ scn.foldLevelPrev = mh.foldLevelPrev;
+ scn.token = mh.token;
+ scn.annotationLinesAdded = mh.annotationLinesAdded;
+ NotifyParent(scn);
+ }
+}
+
+void Editor::NotifyDeleted(Document *, void *) {
+ /* Do nothing */
+}
+
+void Editor::NotifyMacroRecord(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
+
+ // Enumerates all macroable messages
+ switch (iMessage) {
+ case SCI_CUT:
+ case SCI_COPY:
+ case SCI_PASTE:
+ case SCI_CLEAR:
+ case SCI_REPLACESEL:
+ case SCI_ADDTEXT:
+ case SCI_INSERTTEXT:
+ case SCI_APPENDTEXT:
+ case SCI_CLEARALL:
+ case SCI_SELECTALL:
+ case SCI_GOTOLINE:
+ case SCI_GOTOPOS:
+ case SCI_SEARCHANCHOR:
+ case SCI_SEARCHNEXT:
+ case SCI_SEARCHPREV:
+ case SCI_LINEDOWN:
+ case SCI_LINEDOWNEXTEND:
+ case SCI_PARADOWN:
+ case SCI_PARADOWNEXTEND:
+ case SCI_LINEUP:
+ case SCI_LINEUPEXTEND:
+ case SCI_PARAUP:
+ case SCI_PARAUPEXTEND:
+ case SCI_CHARLEFT:
+ case SCI_CHARLEFTEXTEND:
+ case SCI_CHARRIGHT:
+ case SCI_CHARRIGHTEXTEND:
+ case SCI_WORDLEFT:
+ case SCI_WORDLEFTEXTEND:
+ case SCI_WORDRIGHT:
+ case SCI_WORDRIGHTEXTEND:
+ case SCI_WORDPARTLEFT:
+ case SCI_WORDPARTLEFTEXTEND:
+ case SCI_WORDPARTRIGHT:
+ case SCI_WORDPARTRIGHTEXTEND:
+ case SCI_WORDLEFTEND:
+ case SCI_WORDLEFTENDEXTEND:
+ case SCI_WORDRIGHTEND:
+ case SCI_WORDRIGHTENDEXTEND:
+ case SCI_HOME:
+ case SCI_HOMEEXTEND:
+ case SCI_LINEEND:
+ case SCI_LINEENDEXTEND:
+ case SCI_HOMEWRAP:
+ case SCI_HOMEWRAPEXTEND:
+ case SCI_LINEENDWRAP:
+ case SCI_LINEENDWRAPEXTEND:
+ case SCI_DOCUMENTSTART:
+ case SCI_DOCUMENTSTARTEXTEND:
+ case SCI_DOCUMENTEND:
+ case SCI_DOCUMENTENDEXTEND:
+ case SCI_STUTTEREDPAGEUP:
+ case SCI_STUTTEREDPAGEUPEXTEND:
+ case SCI_STUTTEREDPAGEDOWN:
+ case SCI_STUTTEREDPAGEDOWNEXTEND:
+ case SCI_PAGEUP:
+ case SCI_PAGEUPEXTEND:
+ case SCI_PAGEDOWN:
+ case SCI_PAGEDOWNEXTEND:
+ case SCI_EDITTOGGLEOVERTYPE:
+ case SCI_CANCEL:
+ case SCI_DELETEBACK:
+ case SCI_TAB:
+ case SCI_BACKTAB:
+ case SCI_FORMFEED:
+ case SCI_VCHOME:
+ case SCI_VCHOMEEXTEND:
+ case SCI_VCHOMEWRAP:
+ case SCI_VCHOMEWRAPEXTEND:
+ case SCI_VCHOMEDISPLAY:
+ case SCI_VCHOMEDISPLAYEXTEND:
+ case SCI_DELWORDLEFT:
+ case SCI_DELWORDRIGHT:
+ case SCI_DELWORDRIGHTEND:
+ case SCI_DELLINELEFT:
+ case SCI_DELLINERIGHT:
+ case SCI_LINECOPY:
+ case SCI_LINECUT:
+ case SCI_LINEDELETE:
+ case SCI_LINETRANSPOSE:
+ case SCI_LINEDUPLICATE:
+ case SCI_LOWERCASE:
+ case SCI_UPPERCASE:
+ case SCI_LINESCROLLDOWN:
+ case SCI_LINESCROLLUP:
+ case SCI_DELETEBACKNOTLINE:
+ case SCI_HOMEDISPLAY:
+ case SCI_HOMEDISPLAYEXTEND:
+ case SCI_LINEENDDISPLAY:
+ case SCI_LINEENDDISPLAYEXTEND:
+ case SCI_SETSELECTIONMODE:
+ case SCI_LINEDOWNRECTEXTEND:
+ case SCI_LINEUPRECTEXTEND:
+ case SCI_CHARLEFTRECTEXTEND:
+ case SCI_CHARRIGHTRECTEXTEND:
+ case SCI_HOMERECTEXTEND:
+ case SCI_VCHOMERECTEXTEND:
+ case SCI_LINEENDRECTEXTEND:
+ case SCI_PAGEUPRECTEXTEND:
+ case SCI_PAGEDOWNRECTEXTEND:
+ case SCI_SELECTIONDUPLICATE:
+ case SCI_COPYALLOWLINE:
+ case SCI_VERTICALCENTRECARET:
+ case SCI_MOVESELECTEDLINESUP:
+ case SCI_MOVESELECTEDLINESDOWN:
+ case SCI_SCROLLTOSTART:
+ case SCI_SCROLLTOEND:
+ break;
+
+ // Filter out all others like display changes. Also, newlines are redundant
+ // with char insert messages.
+ case SCI_NEWLINE:
+ default:
+ // printf("Filtered out %ld of macro recording\n", iMessage);
+ return ;
+ }
+
+ // Send notification
+ SCNotification scn = {0};
+ scn.nmhdr.code = SCN_MACRORECORD;
+ scn.message = iMessage;
+ scn.wParam = wParam;
+ scn.lParam = lParam;
+ NotifyParent(scn);
+}
+
+// Something has changed that the container should know about
+void Editor::ContainerNeedsUpdate(int flags) {
+ needUpdateUI |= flags;
+}
+
+/**
+ * Force scroll and keep position relative to top of window.
+ *
+ * If stuttered = true and not already at first/last row, move to first/last row of window.
+ * If stuttered = true and already at first/last row, scroll as normal.
+ */
+void Editor::PageMove(int direction, Selection::selTypes selt, bool stuttered) {
+ int topLineNew;
+ SelectionPosition newPos;
+
+ int currentLine = pdoc->LineFromPosition(sel.MainCaret());
+ int topStutterLine = topLine + caretYSlop;
+ int bottomStutterLine =
+ pdoc->LineFromPosition(PositionFromLocation(
+ Point(lastXChosen - xOffset, direction * vs.lineHeight * LinesToScroll())))
+ - caretYSlop - 1;
+
+ if (stuttered && (direction < 0 && currentLine > topStutterLine)) {
+ topLineNew = topLine;
+ newPos = SPositionFromLocation(Point(lastXChosen - xOffset, vs.lineHeight * caretYSlop),
+ false, false, UserVirtualSpace());
+
+ } else if (stuttered && (direction > 0 && currentLine < bottomStutterLine)) {
+ topLineNew = topLine;
+ newPos = SPositionFromLocation(Point(lastXChosen - xOffset, vs.lineHeight * (LinesToScroll() - caretYSlop)),
+ false, false, UserVirtualSpace());
+
+ } else {
+ Point pt = LocationFromPosition(sel.MainCaret());
+
+ topLineNew = Platform::Clamp(
+ topLine + direction * LinesToScroll(), 0, MaxScrollPos());
+ newPos = SPositionFromLocation(
+ Point(lastXChosen - xOffset, pt.y + direction * (vs.lineHeight * LinesToScroll())),
+ false, false, UserVirtualSpace());
+ }
+
+ if (topLineNew != topLine) {
+ SetTopLine(topLineNew);
+ MovePositionTo(newPos, selt);
+ Redraw();
+ SetVerticalScrollPos();
+ } else {
+ MovePositionTo(newPos, selt);
+ }
+}
+
+void Editor::ChangeCaseOfSelection(int caseMapping) {
+ UndoGroup ug(pdoc);
+ for (size_t r=0; r<sel.Count(); r++) {
+ SelectionRange current = sel.Range(r);
+ SelectionRange currentNoVS = current;
+ currentNoVS.ClearVirtualSpace();
+ size_t rangeBytes = currentNoVS.Length();
+ if (rangeBytes > 0) {
+ std::string sText = RangeText(currentNoVS.Start().Position(), currentNoVS.End().Position());
+
+ std::string sMapped = CaseMapString(sText, caseMapping);
+
+ if (sMapped != sText) {
+ size_t firstDifference = 0;
+ while (sMapped[firstDifference] == sText[firstDifference])
+ firstDifference++;
+ size_t lastDifferenceText = sText.size() - 1;
+ size_t lastDifferenceMapped = sMapped.size() - 1;
+ while (sMapped[lastDifferenceMapped] == sText[lastDifferenceText]) {
+ lastDifferenceText--;
+ lastDifferenceMapped--;
+ }
+ size_t endDifferenceText = sText.size() - 1 - lastDifferenceText;
+ pdoc->DeleteChars(
+ static_cast<int>(currentNoVS.Start().Position() + firstDifference),
+ static_cast<int>(rangeBytes - firstDifference - endDifferenceText));
+ pdoc->InsertString(
+ static_cast<int>(currentNoVS.Start().Position() + firstDifference),
+ sMapped.c_str() + firstDifference,
+ static_cast<int>(lastDifferenceMapped - firstDifference + 1));
+ // Automatic movement changes selection so reset to exactly the same as it was.
+ int diffSizes = static_cast<int>(sMapped.size() - sText.size());
+ if (diffSizes != 0) {
+ if (current.anchor > current.caret)
+ current.anchor.Add(diffSizes);
+ else
+ current.caret.Add(diffSizes);
+ }
+ sel.Range(r) = current;
+ }
+ }
+ }
+}
+
+void Editor::LineTranspose() {
+ int line = pdoc->LineFromPosition(sel.MainCaret());
+ if (line > 0) {
+ UndoGroup ug(pdoc);
+ int startPrev = pdoc->LineStart(line - 1);
+ int endPrev = pdoc->LineEnd(line - 1);
+ int start = pdoc->LineStart(line);
+ int end = pdoc->LineEnd(line);
+ std::string line1 = RangeText(startPrev, endPrev);
+ int len1 = endPrev - startPrev;
+ std::string line2 = RangeText(start, end);
+ int len2 = end - start;
+ pdoc->DeleteChars(start, len2);
+ pdoc->DeleteChars(startPrev, len1);
+ pdoc->InsertString(startPrev, line2.c_str(), len2);
+ pdoc->InsertString(start - len1 + len2, line1.c_str(), len1);
+ MovePositionTo(SelectionPosition(start - len1 + len2));
+ }
+}
+
+void Editor::Duplicate(bool forLine) {
+ if (sel.Empty()) {
+ forLine = true;
+ }
+ UndoGroup ug(pdoc);
+ const char *eol = "";
+ int eolLen = 0;
+ if (forLine) {
+ eol = StringFromEOLMode(pdoc->eolMode);
+ eolLen = istrlen(eol);
+ }
+ for (size_t r=0; r<sel.Count(); r++) {
+ SelectionPosition start = sel.Range(r).Start();
+ SelectionPosition end = sel.Range(r).End();
+ if (forLine) {
+ int line = pdoc->LineFromPosition(sel.Range(r).caret.Position());
+ start = SelectionPosition(pdoc->LineStart(line));
+ end = SelectionPosition(pdoc->LineEnd(line));
+ }
+ std::string text = RangeText(start.Position(), end.Position());
+ if (forLine)
+ pdoc->InsertString(end.Position(), eol, eolLen);
+ pdoc->InsertString(end.Position() + eolLen, text.c_str(), SelectionRange(end, start).Length());
+ }
+ if (sel.Count() && sel.IsRectangular()) {
+ SelectionPosition last = sel.Last();
+ if (forLine) {
+ int line = pdoc->LineFromPosition(last.Position());
+ last = SelectionPosition(last.Position() + pdoc->LineStart(line+1) - pdoc->LineStart(line));
+ }
+ if (sel.Rectangular().anchor > sel.Rectangular().caret)
+ sel.Rectangular().anchor = last;
+ else
+ sel.Rectangular().caret = last;
+ SetRectangularRange();
+ }
+}
+
+void Editor::CancelModes() {
+ sel.SetMoveExtends(false);
+}
+
+void Editor::NewLine() {
+ // Remove non-main ranges
+ InvalidateSelection(sel.RangeMain(), true);
+ sel.SetSelection(sel.RangeMain());
+
+ // Clear main range and insert line end
+ bool needGroupUndo = !sel.Empty();
+ if (needGroupUndo)
+ pdoc->BeginUndoAction();
+
+ if (!sel.Empty())
+ ClearSelection();
+ const char *eol = "\n";
+ if (pdoc->eolMode == SC_EOL_CRLF) {
+ eol = "\r\n";
+ } else if (pdoc->eolMode == SC_EOL_CR) {
+ eol = "\r";
+ } // else SC_EOL_LF -> "\n" already set
+ bool inserted = pdoc->InsertCString(sel.MainCaret(), eol);
+ // Want to end undo group before NotifyChar as applications often modify text here
+ if (needGroupUndo)
+ pdoc->EndUndoAction();
+ if (inserted) {
+ SetEmptySelection(sel.MainCaret() + istrlen(eol));
+ while (*eol) {
+ NotifyChar(*eol);
+ if (recordingMacro) {
+ char txt[2];
+ txt[0] = *eol;
+ txt[1] = '\0';
+ NotifyMacroRecord(SCI_REPLACESEL, 0, reinterpret_cast<sptr_t>(txt));
+ }
+ eol++;
+ }
+ }
+ SetLastXChosen();
+ SetScrollBars();
+ EnsureCaretVisible();
+ // Avoid blinking during rapid typing:
+ ShowCaretAtCurrentPosition();
+}
+
+void Editor::CursorUpOrDown(int direction, Selection::selTypes selt) {
+ SelectionPosition caretToUse = sel.Range(sel.Main()).caret;
+ if (sel.IsRectangular()) {
+ if (selt == Selection::noSel) {
+ caretToUse = (direction > 0) ? sel.Limits().end : sel.Limits().start;
+ } else {
+ caretToUse = sel.Rectangular().caret;
+ }
+ }
+
+ Point pt = LocationFromPosition(caretToUse);
+ int skipLines = 0;
+
+ if (vs.annotationVisible) {
+ int lineDoc = pdoc->LineFromPosition(caretToUse.Position());
+ Point ptStartLine = LocationFromPosition(pdoc->LineStart(lineDoc));
+ int subLine = (pt.y - ptStartLine.y) / vs.lineHeight;
+
+ if (direction < 0 && subLine == 0) {
+ int lineDisplay = cs.DisplayFromDoc(lineDoc);
+ if (lineDisplay > 0) {
+ skipLines = pdoc->AnnotationLines(cs.DocFromDisplay(lineDisplay - 1));
+ }
+ } else if (direction > 0 && subLine >= (cs.GetHeight(lineDoc) - 1 - pdoc->AnnotationLines(lineDoc))) {
+ skipLines = pdoc->AnnotationLines(lineDoc);
+ }
+ }
+
+ int newY = pt.y + (1 + skipLines) * direction * vs.lineHeight;
+ SelectionPosition posNew = SPositionFromLocation(
+ Point(lastXChosen - xOffset, newY), false, false, UserVirtualSpace());
+
+ if (direction < 0) {
+ // Line wrapping may lead to a location on the same line, so
+ // seek back if that is the case.
+ Point ptNew = LocationFromPosition(posNew.Position());
+ while ((posNew.Position() > 0) && (pt.y == ptNew.y)) {
+ posNew.Add(-1);
+ posNew.SetVirtualSpace(0);
+ ptNew = LocationFromPosition(posNew.Position());
+ }
+ } else if (direction > 0 && posNew.Position() != pdoc->Length()) {
+ // There is an equivalent case when moving down which skips
+ // over a line.
+ Point ptNew = LocationFromPosition(posNew.Position());
+ while ((posNew.Position() > caretToUse.Position()) && (ptNew.y > newY)) {
+ posNew.Add(-1);
+ posNew.SetVirtualSpace(0);
+ ptNew = LocationFromPosition(posNew.Position());
+ }
+ }
+
+ MovePositionTo(MovePositionSoVisible(posNew, direction), selt);
+}
+
+void Editor::ParaUpOrDown(int direction, Selection::selTypes selt) {
+ int lineDoc, savedPos = sel.MainCaret();
+ do {
+ MovePositionTo(SelectionPosition(direction > 0 ? pdoc->ParaDown(sel.MainCaret()) : pdoc->ParaUp(sel.MainCaret())), selt);
+ lineDoc = pdoc->LineFromPosition(sel.MainCaret());
+ if (direction > 0) {
+ if (sel.MainCaret() >= pdoc->Length() && !cs.GetVisible(lineDoc)) {
+ if (selt == Selection::noSel) {
+ MovePositionTo(SelectionPosition(pdoc->LineEndPosition(savedPos)));
+ }
+ break;
+ }
+ }
+ } while (!cs.GetVisible(lineDoc));
+}
+
+int Editor::StartEndDisplayLine(int pos, bool start) {
+ RefreshStyleData();
+ int line = pdoc->LineFromPosition(pos);
+ AutoSurface surface(this);
+ AutoLineLayout ll(llc, RetrieveLineLayout(line));
+ int posRet = INVALID_POSITION;
+ if (surface && ll) {
+ unsigned int posLineStart = pdoc->LineStart(line);
+ LayoutLine(line, surface, vs, ll, wrapWidth);
+ int posInLine = pos - posLineStart;
+ if (posInLine <= ll->maxLineLength) {
+ for (int subLine = 0; subLine < ll->lines; subLine++) {
+ if ((posInLine >= ll->LineStart(subLine)) && (posInLine <= ll->LineStart(subLine + 1))) {
+ if (start) {
+ posRet = ll->LineStart(subLine) + posLineStart;
+ } else {
+ if (subLine == ll->lines - 1)
+ posRet = ll->LineStart(subLine + 1) + posLineStart;
+ else
+ posRet = ll->LineStart(subLine + 1) + posLineStart - 1;
+ }
+ }
+ }
+ }
+ }
+ if (posRet == INVALID_POSITION) {
+ return pos;
+ } else {
+ return posRet;
+ }
+}
+
+int Editor::KeyCommand(unsigned int iMessage) {
+ switch (iMessage) {
+ case SCI_LINEDOWN:
+ CursorUpOrDown(1);
+ break;
+ case SCI_LINEDOWNEXTEND:
+ CursorUpOrDown(1, Selection::selStream);
+ break;
+ case SCI_LINEDOWNRECTEXTEND:
+ CursorUpOrDown(1, Selection::selRectangle);
+ break;
+ case SCI_PARADOWN:
+ ParaUpOrDown(1);
+ break;
+ case SCI_PARADOWNEXTEND:
+ ParaUpOrDown(1, Selection::selStream);
+ break;
+ case SCI_LINESCROLLDOWN:
+ ScrollTo(topLine + 1);
+ MoveCaretInsideView(false);
+ break;
+ case SCI_LINEUP:
+ CursorUpOrDown(-1);
+ break;
+ case SCI_LINEUPEXTEND:
+ CursorUpOrDown(-1, Selection::selStream);
+ break;
+ case SCI_LINEUPRECTEXTEND:
+ CursorUpOrDown(-1, Selection::selRectangle);
+ break;
+ case SCI_PARAUP:
+ ParaUpOrDown(-1);
+ break;
+ case SCI_PARAUPEXTEND:
+ ParaUpOrDown(-1, Selection::selStream);
+ break;
+ case SCI_LINESCROLLUP:
+ ScrollTo(topLine - 1);
+ MoveCaretInsideView(false);
+ break;
+ case SCI_CHARLEFT:
+ if (SelectionEmpty() || sel.MoveExtends()) {
+ if ((sel.Count() == 1) && pdoc->IsLineEndPosition(sel.MainCaret()) && sel.RangeMain().caret.VirtualSpace()) {
+ SelectionPosition spCaret = sel.RangeMain().caret;
+ spCaret.SetVirtualSpace(spCaret.VirtualSpace() - 1);
+ MovePositionTo(spCaret);
+ } else if (sel.MoveExtends() && sel.selType == Selection::selStream) {
+ MovePositionTo(MovePositionSoVisible(SelectionPosition(sel.MainCaret() - 1), -1));
+ } else {
+ MovePositionTo(MovePositionSoVisible(
+ SelectionPosition((sel.LimitsForRectangularElseMain().start).Position() - 1), -1));
+ }
+ } else {
+ MovePositionTo(sel.LimitsForRectangularElseMain().start);
+ }
+ SetLastXChosen();
+ break;
+ case SCI_CHARLEFTEXTEND:
+ if (pdoc->IsLineEndPosition(sel.MainCaret()) && sel.RangeMain().caret.VirtualSpace()) {
+ SelectionPosition spCaret = sel.RangeMain().caret;
+ spCaret.SetVirtualSpace(spCaret.VirtualSpace() - 1);
+ MovePositionTo(spCaret, Selection::selStream);
+ } else {
+ MovePositionTo(MovePositionSoVisible(SelectionPosition(sel.MainCaret() - 1), -1), Selection::selStream);
+ }
+ SetLastXChosen();
+ break;
+ case SCI_CHARLEFTRECTEXTEND:
+ if (pdoc->IsLineEndPosition(sel.MainCaret()) && sel.RangeMain().caret.VirtualSpace()) {
+ SelectionPosition spCaret = sel.RangeMain().caret;
+ spCaret.SetVirtualSpace(spCaret.VirtualSpace() - 1);
+ MovePositionTo(spCaret, Selection::selRectangle);
+ } else {
+ MovePositionTo(MovePositionSoVisible(SelectionPosition(sel.MainCaret() - 1), -1), Selection::selRectangle);
+ }
+ SetLastXChosen();
+ break;
+ case SCI_CHARRIGHT:
+ if (SelectionEmpty() || sel.MoveExtends()) {
+ if ((virtualSpaceOptions & SCVS_USERACCESSIBLE) && pdoc->IsLineEndPosition(sel.MainCaret())) {
+ SelectionPosition spCaret = sel.RangeMain().caret;
+ spCaret.SetVirtualSpace(spCaret.VirtualSpace() + 1);
+ MovePositionTo(spCaret);
+ } else if (sel.MoveExtends() && sel.selType == Selection::selStream) {
+ MovePositionTo(MovePositionSoVisible(SelectionPosition(sel.MainCaret() + 1), 1));
+ } else {
+ MovePositionTo(MovePositionSoVisible(
+ SelectionPosition((sel.LimitsForRectangularElseMain().end).Position() + 1), 1));
+ }
+ } else {
+ MovePositionTo(sel.LimitsForRectangularElseMain().end);
+ }
+ SetLastXChosen();
+ break;
+ case SCI_CHARRIGHTEXTEND:
+ if ((virtualSpaceOptions & SCVS_USERACCESSIBLE) && pdoc->IsLineEndPosition(sel.MainCaret())) {
+ SelectionPosition spCaret = sel.RangeMain().caret;
+ spCaret.SetVirtualSpace(spCaret.VirtualSpace() + 1);
+ MovePositionTo(spCaret, Selection::selStream);
+ } else {
+ MovePositionTo(MovePositionSoVisible(SelectionPosition(sel.MainCaret() + 1), 1), Selection::selStream);
+ }
+ SetLastXChosen();
+ break;
+ case SCI_CHARRIGHTRECTEXTEND:
+ if ((virtualSpaceOptions & SCVS_RECTANGULARSELECTION) && pdoc->IsLineEndPosition(sel.MainCaret())) {
+ SelectionPosition spCaret = sel.RangeMain().caret;
+ spCaret.SetVirtualSpace(spCaret.VirtualSpace() + 1);
+ MovePositionTo(spCaret, Selection::selRectangle);
+ } else {
+ MovePositionTo(MovePositionSoVisible(SelectionPosition(sel.MainCaret() + 1), 1), Selection::selRectangle);
+ }
+ SetLastXChosen();
+ break;
+ case SCI_WORDLEFT:
+ MovePositionTo(MovePositionSoVisible(pdoc->NextWordStart(sel.MainCaret(), -1), -1));
+ SetLastXChosen();
+ break;
+ case SCI_WORDLEFTEXTEND:
+ MovePositionTo(MovePositionSoVisible(pdoc->NextWordStart(sel.MainCaret(), -1), -1), Selection::selStream);
+ SetLastXChosen();
+ break;
+ case SCI_WORDRIGHT:
+ MovePositionTo(MovePositionSoVisible(pdoc->NextWordStart(sel.MainCaret(), 1), 1));
+ SetLastXChosen();
+ break;
+ case SCI_WORDRIGHTEXTEND:
+ MovePositionTo(MovePositionSoVisible(pdoc->NextWordStart(sel.MainCaret(), 1), 1), Selection::selStream);
+ SetLastXChosen();
+ break;
+
+ case SCI_WORDLEFTEND:
+ MovePositionTo(MovePositionSoVisible(pdoc->NextWordEnd(sel.MainCaret(), -1), -1));
+ SetLastXChosen();
+ break;
+ case SCI_WORDLEFTENDEXTEND:
+ MovePositionTo(MovePositionSoVisible(pdoc->NextWordEnd(sel.MainCaret(), -1), -1), Selection::selStream);
+ SetLastXChosen();
+ break;
+ case SCI_WORDRIGHTEND:
+ MovePositionTo(MovePositionSoVisible(pdoc->NextWordEnd(sel.MainCaret(), 1), 1));
+ SetLastXChosen();
+ break;
+ case SCI_WORDRIGHTENDEXTEND:
+ MovePositionTo(MovePositionSoVisible(pdoc->NextWordEnd(sel.MainCaret(), 1), 1), Selection::selStream);
+ SetLastXChosen();
+ break;
+
+ case SCI_HOME:
+ MovePositionTo(pdoc->LineStart(pdoc->LineFromPosition(sel.MainCaret())));
+ SetLastXChosen();
+ break;
+ case SCI_HOMEEXTEND:
+ MovePositionTo(pdoc->LineStart(pdoc->LineFromPosition(sel.MainCaret())), Selection::selStream);
+ SetLastXChosen();
+ break;
+ case SCI_HOMERECTEXTEND:
+ MovePositionTo(pdoc->LineStart(pdoc->LineFromPosition(sel.MainCaret())), Selection::selRectangle);
+ SetLastXChosen();
+ break;
+ case SCI_LINEEND:
+ MovePositionTo(pdoc->LineEndPosition(sel.MainCaret()));
+ SetLastXChosen();
+ break;
+ case SCI_LINEENDEXTEND:
+ MovePositionTo(pdoc->LineEndPosition(sel.MainCaret()), Selection::selStream);
+ SetLastXChosen();
+ break;
+ case SCI_LINEENDRECTEXTEND:
+ MovePositionTo(pdoc->LineEndPosition(sel.MainCaret()), Selection::selRectangle);
+ SetLastXChosen();
+ break;
+ case SCI_HOMEWRAP: {
+ SelectionPosition homePos = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), true), -1);
+ if (sel.RangeMain().caret <= homePos)
+ homePos = SelectionPosition(pdoc->LineStart(pdoc->LineFromPosition(sel.MainCaret())));
+ MovePositionTo(homePos);
+ SetLastXChosen();
+ }
+ break;
+ case SCI_HOMEWRAPEXTEND: {
+ SelectionPosition homePos = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), true), -1);
+ if (sel.RangeMain().caret <= homePos)
+ homePos = SelectionPosition(pdoc->LineStart(pdoc->LineFromPosition(sel.MainCaret())));
+ MovePositionTo(homePos, Selection::selStream);
+ SetLastXChosen();
+ }
+ break;
+ case SCI_LINEENDWRAP: {
+ SelectionPosition endPos = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), false), 1);
+ SelectionPosition realEndPos = SelectionPosition(pdoc->LineEndPosition(sel.MainCaret()));
+ if (endPos > realEndPos // if moved past visible EOLs
+ || sel.RangeMain().caret >= endPos) // if at end of display line already
+ endPos = realEndPos;
+ MovePositionTo(endPos);
+ SetLastXChosen();
+ }
+ break;
+ case SCI_LINEENDWRAPEXTEND: {
+ SelectionPosition endPos = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), false), 1);
+ SelectionPosition realEndPos = SelectionPosition(pdoc->LineEndPosition(sel.MainCaret()));
+ if (endPos > realEndPos // if moved past visible EOLs
+ || sel.RangeMain().caret >= endPos) // if at end of display line already
+ endPos = realEndPos;
+ MovePositionTo(endPos, Selection::selStream);
+ SetLastXChosen();
+ }
+ break;
+ case SCI_DOCUMENTSTART:
+ MovePositionTo(0);
+ SetLastXChosen();
+ break;
+ case SCI_DOCUMENTSTARTEXTEND:
+ MovePositionTo(0, Selection::selStream);
+ SetLastXChosen();
+ break;
+ case SCI_DOCUMENTEND:
+ MovePositionTo(pdoc->Length());
+ SetLastXChosen();
+ break;
+ case SCI_DOCUMENTENDEXTEND:
+ MovePositionTo(pdoc->Length(), Selection::selStream);
+ SetLastXChosen();
+ break;
+ case SCI_STUTTEREDPAGEUP:
+ PageMove(-1, Selection::noSel, true);
+ break;
+ case SCI_STUTTEREDPAGEUPEXTEND:
+ PageMove(-1, Selection::selStream, true);
+ break;
+ case SCI_STUTTEREDPAGEDOWN:
+ PageMove(1, Selection::noSel, true);
+ break;
+ case SCI_STUTTEREDPAGEDOWNEXTEND:
+ PageMove(1, Selection::selStream, true);
+ break;
+ case SCI_PAGEUP:
+ PageMove(-1);
+ break;
+ case SCI_PAGEUPEXTEND:
+ PageMove(-1, Selection::selStream);
+ break;
+ case SCI_PAGEUPRECTEXTEND:
+ PageMove(-1, Selection::selRectangle);
+ break;
+ case SCI_PAGEDOWN:
+ PageMove(1);
+ break;
+ case SCI_PAGEDOWNEXTEND:
+ PageMove(1, Selection::selStream);
+ break;
+ case SCI_PAGEDOWNRECTEXTEND:
+ PageMove(1, Selection::selRectangle);
+ break;
+ case SCI_EDITTOGGLEOVERTYPE:
+ inOverstrike = !inOverstrike;
+ DropCaret();
+ ShowCaretAtCurrentPosition();
+ ContainerNeedsUpdate(SC_UPDATE_CONTENT);
+ NotifyUpdateUI();
+ break;
+ case SCI_CANCEL: // Cancel any modes - handled in subclass
+ // Also unselect text
+ CancelModes();
+ break;
+ case SCI_DELETEBACK:
+ DelCharBack(true);
+ if ((caretSticky == SC_CARETSTICKY_OFF) || (caretSticky == SC_CARETSTICKY_WHITESPACE)) {
+ SetLastXChosen();
+ }
+ EnsureCaretVisible();
+ break;
+ case SCI_DELETEBACKNOTLINE:
+ DelCharBack(false);
+ if ((caretSticky == SC_CARETSTICKY_OFF) || (caretSticky == SC_CARETSTICKY_WHITESPACE)) {
+ SetLastXChosen();
+ }
+ EnsureCaretVisible();
+ break;
+ case SCI_TAB:
+ Indent(true);
+ if (caretSticky == SC_CARETSTICKY_OFF) {
+ SetLastXChosen();
+ }
+ EnsureCaretVisible();
+ ShowCaretAtCurrentPosition(); // Avoid blinking
+ break;
+ case SCI_BACKTAB:
+ Indent(false);
+ if ((caretSticky == SC_CARETSTICKY_OFF) || (caretSticky == SC_CARETSTICKY_WHITESPACE)) {
+ SetLastXChosen();
+ }
+ EnsureCaretVisible();
+ ShowCaretAtCurrentPosition(); // Avoid blinking
+ break;
+ case SCI_NEWLINE:
+ NewLine();
+ break;
+ case SCI_FORMFEED:
+ AddChar('\f');
+ break;
+ case SCI_VCHOME:
+ MovePositionTo(pdoc->VCHomePosition(sel.MainCaret()));
+ SetLastXChosen();
+ break;
+ case SCI_VCHOMEEXTEND:
+ MovePositionTo(pdoc->VCHomePosition(sel.MainCaret()), Selection::selStream);
+ SetLastXChosen();
+ break;
+ case SCI_VCHOMERECTEXTEND:
+ MovePositionTo(pdoc->VCHomePosition(sel.MainCaret()), Selection::selRectangle);
+ SetLastXChosen();
+ break;
+ case SCI_VCHOMEWRAP: {
+ SelectionPosition homePos = SelectionPosition(pdoc->VCHomePosition(sel.MainCaret()));
+ SelectionPosition viewLineStart = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), true), -1);
+ if ((viewLineStart < sel.RangeMain().caret) && (viewLineStart > homePos))
+ homePos = viewLineStart;
+
+ MovePositionTo(homePos);
+ SetLastXChosen();
+ }
+ break;
+ case SCI_VCHOMEWRAPEXTEND: {
+ SelectionPosition homePos = SelectionPosition(pdoc->VCHomePosition(sel.MainCaret()));
+ SelectionPosition viewLineStart = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), true), -1);
+ if ((viewLineStart < sel.RangeMain().caret) && (viewLineStart > homePos))
+ homePos = viewLineStart;
+
+ MovePositionTo(homePos, Selection::selStream);
+ SetLastXChosen();
+ }
+ break;
+ case SCI_ZOOMIN:
+ if (vs.zoomLevel < 20) {
+ vs.zoomLevel++;
+ InvalidateStyleRedraw();
+ NotifyZoom();
+ }
+ break;
+ case SCI_ZOOMOUT:
+ if (vs.zoomLevel > -10) {
+ vs.zoomLevel--;
+ InvalidateStyleRedraw();
+ NotifyZoom();
+ }
+ break;
+ case SCI_DELWORDLEFT: {
+ int startWord = pdoc->NextWordStart(sel.MainCaret(), -1);
+ pdoc->DeleteChars(startWord, sel.MainCaret() - startWord);
+ sel.RangeMain().ClearVirtualSpace();
+ SetLastXChosen();
+ }
+ break;
+ case SCI_DELWORDRIGHT: {
+ UndoGroup ug(pdoc);
+ sel.RangeMain().caret = SelectionPosition(
+ InsertSpace(sel.RangeMain().caret.Position(), sel.RangeMain().caret.VirtualSpace()));
+ sel.RangeMain().anchor = sel.RangeMain().caret;
+ int endWord = pdoc->NextWordStart(sel.MainCaret(), 1);
+ pdoc->DeleteChars(sel.MainCaret(), endWord - sel.MainCaret());
+ }
+ break;
+ case SCI_DELWORDRIGHTEND: {
+ UndoGroup ug(pdoc);
+ sel.RangeMain().caret = SelectionPosition(
+ InsertSpace(sel.RangeMain().caret.Position(), sel.RangeMain().caret.VirtualSpace()));
+ int endWord = pdoc->NextWordEnd(sel.MainCaret(), 1);
+ pdoc->DeleteChars(sel.MainCaret(), endWord - sel.MainCaret());
+ }
+ break;
+ case SCI_DELLINELEFT: {
+ int line = pdoc->LineFromPosition(sel.MainCaret());
+ int start = pdoc->LineStart(line);
+ pdoc->DeleteChars(start, sel.MainCaret() - start);
+ sel.RangeMain().ClearVirtualSpace();
+ SetLastXChosen();
+ }
+ break;
+ case SCI_DELLINERIGHT: {
+ int line = pdoc->LineFromPosition(sel.MainCaret());
+ int end = pdoc->LineEnd(line);
+ pdoc->DeleteChars(sel.MainCaret(), end - sel.MainCaret());
+ }
+ break;
+ case SCI_LINECOPY: {
+ int lineStart = pdoc->LineFromPosition(SelectionStart().Position());
+ int lineEnd = pdoc->LineFromPosition(SelectionEnd().Position());
+ CopyRangeToClipboard(pdoc->LineStart(lineStart),
+ pdoc->LineStart(lineEnd + 1));
+ }
+ break;
+ case SCI_LINECUT: {
+ int lineStart = pdoc->LineFromPosition(SelectionStart().Position());
+ int lineEnd = pdoc->LineFromPosition(SelectionEnd().Position());
+ int start = pdoc->LineStart(lineStart);
+ int end = pdoc->LineStart(lineEnd + 1);
+ SetSelection(start, end);
+ Cut();
+ SetLastXChosen();
+ }
+ break;
+ case SCI_LINEDELETE: {
+ int line = pdoc->LineFromPosition(sel.MainCaret());
+ int start = pdoc->LineStart(line);
+ int end = pdoc->LineStart(line + 1);
+ pdoc->DeleteChars(start, end - start);
+ }
+ break;
+ case SCI_LINETRANSPOSE:
+ LineTranspose();
+ break;
+ case SCI_LINEDUPLICATE:
+ Duplicate(true);
+ break;
+ case SCI_SELECTIONDUPLICATE:
+ Duplicate(false);
+ break;
+ case SCI_LOWERCASE:
+ ChangeCaseOfSelection(cmLower);
+ break;
+ case SCI_UPPERCASE:
+ ChangeCaseOfSelection(cmUpper);
+ break;
+ case SCI_WORDPARTLEFT:
+ MovePositionTo(MovePositionSoVisible(pdoc->WordPartLeft(sel.MainCaret()), -1));
+ SetLastXChosen();
+ break;
+ case SCI_WORDPARTLEFTEXTEND:
+ MovePositionTo(MovePositionSoVisible(pdoc->WordPartLeft(sel.MainCaret()), -1), Selection::selStream);
+ SetLastXChosen();
+ break;
+ case SCI_WORDPARTRIGHT:
+ MovePositionTo(MovePositionSoVisible(pdoc->WordPartRight(sel.MainCaret()), 1));
+ SetLastXChosen();
+ break;
+ case SCI_WORDPARTRIGHTEXTEND:
+ MovePositionTo(MovePositionSoVisible(pdoc->WordPartRight(sel.MainCaret()), 1), Selection::selStream);
+ SetLastXChosen();
+ break;
+ case SCI_HOMEDISPLAY:
+ MovePositionTo(MovePositionSoVisible(
+ StartEndDisplayLine(sel.MainCaret(), true), -1));
+ SetLastXChosen();
+ break;
+ case SCI_VCHOMEDISPLAY: {
+ SelectionPosition homePos = SelectionPosition(pdoc->VCHomePosition(sel.MainCaret()));
+ SelectionPosition viewLineStart = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), true), -1);
+ if (viewLineStart > homePos)
+ homePos = viewLineStart;
+
+ MovePositionTo(homePos);
+ SetLastXChosen();
+ }
+ break;
+ case SCI_HOMEDISPLAYEXTEND:
+ MovePositionTo(MovePositionSoVisible(
+ StartEndDisplayLine(sel.MainCaret(), true), -1), Selection::selStream);
+ SetLastXChosen();
+ break;
+ case SCI_VCHOMEDISPLAYEXTEND: {
+ SelectionPosition homePos = SelectionPosition(pdoc->VCHomePosition(sel.MainCaret()));
+ SelectionPosition viewLineStart = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), true), -1);
+ if (viewLineStart > homePos)
+ homePos = viewLineStart;
+
+ MovePositionTo(homePos, Selection::selStream);
+ SetLastXChosen();
+ }
+ break;
+ case SCI_LINEENDDISPLAY:
+ MovePositionTo(MovePositionSoVisible(
+ StartEndDisplayLine(sel.MainCaret(), false), 1));
+ SetLastXChosen();
+ break;
+ case SCI_LINEENDDISPLAYEXTEND:
+ MovePositionTo(MovePositionSoVisible(
+ StartEndDisplayLine(sel.MainCaret(), false), 1), Selection::selStream);
+ SetLastXChosen();
+ break;
+ case SCI_SCROLLTOSTART:
+ ScrollTo(0);
+ break;
+ case SCI_SCROLLTOEND:
+ ScrollTo(MaxScrollPos());
+ break;
+ }
+ return 0;
+}
+
+int Editor::KeyDefault(int, int) {
+ return 0;
+}
+
+int Editor::KeyDownWithModifiers(int key, int modifiers, bool *consumed) {
+ DwellEnd(false);
+ int msg = kmap.Find(key, modifiers);
+ if (msg) {
+ if (consumed)
+ *consumed = true;
+ return WndProc(msg, 0, 0);
+ } else {
+ if (consumed)
+ *consumed = false;
+ return KeyDefault(key, modifiers);
+ }
+}
+
+int Editor::KeyDown(int key, bool shift, bool ctrl, bool alt, bool *consumed) {
+ int modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |
+ (alt ? SCI_ALT : 0);
+ return KeyDownWithModifiers(key, modifiers, consumed);
+}
+
+void Editor::Indent(bool forwards) {
+ UndoGroup ug(pdoc);
+ for (size_t r=0; r<sel.Count(); r++) {
+ int lineOfAnchor = pdoc->LineFromPosition(sel.Range(r).anchor.Position());
+ int caretPosition = sel.Range(r).caret.Position();
+ int lineCurrentPos = pdoc->LineFromPosition(caretPosition);
+ if (lineOfAnchor == lineCurrentPos) {
+ if (forwards) {
+ pdoc->DeleteChars(sel.Range(r).Start().Position(), sel.Range(r).Length());
+ caretPosition = sel.Range(r).caret.Position();
+ if (pdoc->GetColumn(caretPosition) <= pdoc->GetColumn(pdoc->GetLineIndentPosition(lineCurrentPos)) &&
+ pdoc->tabIndents) {
+ int indentation = pdoc->GetLineIndentation(lineCurrentPos);
+ int indentationStep = pdoc->IndentSize();
+ pdoc->SetLineIndentation(lineCurrentPos, indentation + indentationStep - indentation % indentationStep);
+ sel.Range(r) = SelectionRange(pdoc->GetLineIndentPosition(lineCurrentPos));
+ } else {
+ if (pdoc->useTabs) {
+ pdoc->InsertChar(caretPosition, '\t');
+ sel.Range(r) = SelectionRange(caretPosition+1);
+ } else {
+ int numSpaces = (pdoc->tabInChars) -
+ (pdoc->GetColumn(caretPosition) % (pdoc->tabInChars));
+ if (numSpaces < 1)
+ numSpaces = pdoc->tabInChars;
+ for (int i = 0; i < numSpaces; i++) {
+ pdoc->InsertChar(caretPosition + i, ' ');
+ }
+ sel.Range(r) = SelectionRange(caretPosition+numSpaces);
+ }
+ }
+ } else {
+ if (pdoc->GetColumn(caretPosition) <= pdoc->GetLineIndentation(lineCurrentPos) &&
+ pdoc->tabIndents) {
+ int indentation = pdoc->GetLineIndentation(lineCurrentPos);
+ int indentationStep = pdoc->IndentSize();
+ pdoc->SetLineIndentation(lineCurrentPos, indentation - indentationStep);
+ sel.Range(r) = SelectionRange(pdoc->GetLineIndentPosition(lineCurrentPos));
+ } else {
+ int newColumn = ((pdoc->GetColumn(caretPosition) - 1) / pdoc->tabInChars) *
+ pdoc->tabInChars;
+ if (newColumn < 0)
+ newColumn = 0;
+ int newPos = caretPosition;
+ while (pdoc->GetColumn(newPos) > newColumn)
+ newPos--;
+ sel.Range(r) = SelectionRange(newPos);
+ }
+ }
+ } else { // Multiline
+ int anchorPosOnLine = sel.Range(r).anchor.Position() - pdoc->LineStart(lineOfAnchor);
+ int currentPosPosOnLine = caretPosition - pdoc->LineStart(lineCurrentPos);
+ // Multiple lines selected so indent / dedent
+ int lineTopSel = Platform::Minimum(lineOfAnchor, lineCurrentPos);
+ int lineBottomSel = Platform::Maximum(lineOfAnchor, lineCurrentPos);
+ if (pdoc->LineStart(lineBottomSel) == sel.Range(r).anchor.Position() || pdoc->LineStart(lineBottomSel) == caretPosition)
+ lineBottomSel--; // If not selecting any characters on a line, do not indent
+ pdoc->Indent(forwards, lineBottomSel, lineTopSel);
+ if (lineOfAnchor < lineCurrentPos) {
+ if (currentPosPosOnLine == 0)
+ sel.Range(r) = SelectionRange(pdoc->LineStart(lineCurrentPos), pdoc->LineStart(lineOfAnchor));
+ else
+ sel.Range(r) = SelectionRange(pdoc->LineStart(lineCurrentPos + 1), pdoc->LineStart(lineOfAnchor));
+ } else {
+ if (anchorPosOnLine == 0)
+ sel.Range(r) = SelectionRange(pdoc->LineStart(lineCurrentPos), pdoc->LineStart(lineOfAnchor));
+ else
+ sel.Range(r) = SelectionRange(pdoc->LineStart(lineCurrentPos), pdoc->LineStart(lineOfAnchor + 1));
+ }
+ }
+ }
+}
+
+class CaseFolderASCII : public CaseFolderTable {
+public:
+ CaseFolderASCII() {
+ StandardASCII();
+ }
+ ~CaseFolderASCII() {
+ }
+};
+
+
+CaseFolder *Editor::CaseFolderForEncoding() {
+ // Simple default that only maps ASCII upper case to lower case.
+ return new CaseFolderASCII();
+}
+
+/**
+ * Search of a text in the document, in the given range.
+ * @return The position of the found text, -1 if not found.
+ */
+long Editor::FindText(
+ uptr_t wParam, ///< Search modes : @c SCFIND_MATCHCASE, @c SCFIND_WHOLEWORD,
+ ///< @c SCFIND_WORDSTART, @c SCFIND_REGEXP or @c SCFIND_POSIX.
+ sptr_t lParam) { ///< @c TextToFind structure: The text to search for in the given range.
+
+ Sci_TextToFind *ft = reinterpret_cast<Sci_TextToFind *>(lParam);
+ int lengthFound = istrlen(ft->lpstrText);
+ if (!pdoc->HasCaseFolder())
+ pdoc->SetCaseFolder(CaseFolderForEncoding());
+ int pos = pdoc->FindText(ft->chrg.cpMin, ft->chrg.cpMax, ft->lpstrText,
+ (wParam & SCFIND_MATCHCASE) != 0,
+ (wParam & SCFIND_WHOLEWORD) != 0,
+ (wParam & SCFIND_WORDSTART) != 0,
+ (wParam & SCFIND_REGEXP) != 0,
+ wParam,
+ &lengthFound);
+ if (pos != -1) {
+ ft->chrgText.cpMin = pos;
+ ft->chrgText.cpMax = pos + lengthFound;
+ }
+ return pos;
+}
+
+/**
+ * Relocatable search support : Searches relative to current selection
+ * point and sets the selection to the found text range with
+ * each search.
+ */
+/**
+ * Anchor following searches at current selection start: This allows
+ * multiple incremental interactive searches to be macro recorded
+ * while still setting the selection to found text so the find/select
+ * operation is self-contained.
+ */
+void Editor::SearchAnchor() {
+ searchAnchor = SelectionStart().Position();
+}
+
+/**
+ * Find text from current search anchor: Must call @c SearchAnchor first.
+ * Used for next text and previous text requests.
+ * @return The position of the found text, -1 if not found.
+ */
+long Editor::SearchText(
+ unsigned int iMessage, ///< Accepts both @c SCI_SEARCHNEXT and @c SCI_SEARCHPREV.
+ uptr_t wParam, ///< Search modes : @c SCFIND_MATCHCASE, @c SCFIND_WHOLEWORD,
+ ///< @c SCFIND_WORDSTART, @c SCFIND_REGEXP or @c SCFIND_POSIX.
+ sptr_t lParam) { ///< The text to search for.
+
+ const char *txt = reinterpret_cast<char *>(lParam);
+ int pos;
+ int lengthFound = istrlen(txt);
+ if (!pdoc->HasCaseFolder())
+ pdoc->SetCaseFolder(CaseFolderForEncoding());
+ if (iMessage == SCI_SEARCHNEXT) {
+ pos = pdoc->FindText(searchAnchor, pdoc->Length(), txt,
+ (wParam & SCFIND_MATCHCASE) != 0,
+ (wParam & SCFIND_WHOLEWORD) != 0,
+ (wParam & SCFIND_WORDSTART) != 0,
+ (wParam & SCFIND_REGEXP) != 0,
+ wParam,
+ &lengthFound);
+ } else {
+ pos = pdoc->FindText(searchAnchor, 0, txt,
+ (wParam & SCFIND_MATCHCASE) != 0,
+ (wParam & SCFIND_WHOLEWORD) != 0,
+ (wParam & SCFIND_WORDSTART) != 0,
+ (wParam & SCFIND_REGEXP) != 0,
+ wParam,
+ &lengthFound);
+ }
+ if (pos != -1) {
+ SetSelection(pos, pos + lengthFound);
+ }
+
+ return pos;
+}
+
+std::string Editor::CaseMapString(const std::string &s, int caseMapping) {
+ std::string ret(s);
+ for (size_t i=0; i<ret.size(); i++) {
+ switch (caseMapping) {
+ case cmUpper:
+ if (ret[i] >= 'a' && ret[i] <= 'z')
+ ret[i] = static_cast<char>(ret[i] - 'a' + 'A');
+ break;
+ case cmLower:
+ if (ret[i] >= 'A' && ret[i] <= 'Z')
+ ret[i] = static_cast<char>(ret[i] - 'A' + 'a');
+ break;
+ }
+ }
+ return ret;
+}
+
+/**
+ * Search for text in the target range of the document.
+ * @return The position of the found text, -1 if not found.
+ */
+long Editor::SearchInTarget(const char *text, int length) {
+ int lengthFound = length;
+
+ if (!pdoc->HasCaseFolder())
+ pdoc->SetCaseFolder(CaseFolderForEncoding());
+ int pos = pdoc->FindText(targetStart, targetEnd, text,
+ (searchFlags & SCFIND_MATCHCASE) != 0,
+ (searchFlags & SCFIND_WHOLEWORD) != 0,
+ (searchFlags & SCFIND_WORDSTART) != 0,
+ (searchFlags & SCFIND_REGEXP) != 0,
+ searchFlags,
+ &lengthFound);
+ if (pos != -1) {
+ targetStart = pos;
+ targetEnd = pos + lengthFound;
+ }
+ return pos;
+}
+
+void Editor::GoToLine(int lineNo) {
+ if (lineNo > pdoc->LinesTotal())
+ lineNo = pdoc->LinesTotal();
+ if (lineNo < 0)
+ lineNo = 0;
+ SetEmptySelection(pdoc->LineStart(lineNo));
+ ShowCaretAtCurrentPosition();
+ EnsureCaretVisible();
+}
+
+static bool Close(Point pt1, Point pt2) {
+ if (abs(pt1.x - pt2.x) > 3)
+ return false;
+ if (abs(pt1.y - pt2.y) > 3)
+ return false;
+ return true;
+}
+
+std::string Editor::RangeText(int start, int end) const {
+ if (start < end) {
+ int len = end - start;
+ std::string ret(len, '\0');
+ for (int i = 0; i < len; i++) {
+ ret[i] = pdoc->CharAt(start + i);
+ }
+ return ret;
+ }
+ return std::string();
+}
+
+void Editor::CopySelectionRange(SelectionText *ss, bool allowLineCopy) {
+ if (sel.Empty()) {
+ if (allowLineCopy) {
+ int currentLine = pdoc->LineFromPosition(sel.MainCaret());
+ int start = pdoc->LineStart(currentLine);
+ int end = pdoc->LineEnd(currentLine);
+
+ std::string text = RangeText(start, end);
+ if (pdoc->eolMode != SC_EOL_LF)
+ text.push_back('\r');
+ if (pdoc->eolMode != SC_EOL_CR)
+ text.push_back('\n');
+ ss->Copy(text, pdoc->dbcsCodePage,
+ vs.styles[STYLE_DEFAULT].characterSet, false, true);
+ }
+ } else {
+ std::string text;
+ std::vector<SelectionRange> rangesInOrder = sel.RangesCopy();
+ if (sel.selType == Selection::selRectangle)
+ std::sort(rangesInOrder.begin(), rangesInOrder.end());
+ for (size_t r=0; r<rangesInOrder.size(); r++) {
+ SelectionRange current = rangesInOrder[r];
+ text.append(RangeText(current.Start().Position(), current.End().Position()));
+ if (sel.selType == Selection::selRectangle) {
+ if (pdoc->eolMode != SC_EOL_LF)
+ text.push_back('\r');
+ if (pdoc->eolMode != SC_EOL_CR)
+ text.push_back('\n');
+ }
+ }
+ ss->Copy(text, pdoc->dbcsCodePage,
+ vs.styles[STYLE_DEFAULT].characterSet, sel.IsRectangular(), sel.selType == Selection::selLines);
+ }
+}
+
+void Editor::CopyRangeToClipboard(int start, int end) {
+ start = pdoc->ClampPositionIntoDocument(start);
+ end = pdoc->ClampPositionIntoDocument(end);
+ SelectionText selectedText;
+ std::string text = RangeText(start, end);
+ selectedText.Copy(text,
+ pdoc->dbcsCodePage, vs.styles[STYLE_DEFAULT].characterSet, false, false);
+ CopyToClipboard(selectedText);
+}
+
+void Editor::CopyText(int length, const char *text) {
+ SelectionText selectedText;
+ selectedText.Copy(std::string(text, length),
+ pdoc->dbcsCodePage, vs.styles[STYLE_DEFAULT].characterSet, false, false);
+ CopyToClipboard(selectedText);
+}
+
+void Editor::SetDragPosition(SelectionPosition newPos) {
+ if (newPos.Position() >= 0) {
+ newPos = MovePositionOutsideChar(newPos, 1);
+ posDrop = newPos;
+ }
+ if (!(posDrag == newPos)) {
+ caret.on = true;
+ SetTicking(true);
+ InvalidateCaret();
+ posDrag = newPos;
+ InvalidateCaret();
+ }
+}
+
+void Editor::DisplayCursor(Window::Cursor c) {
+ if (cursorMode == SC_CURSORNORMAL)
+ wMain.SetCursor(c);
+ else
+ wMain.SetCursor(static_cast<Window::Cursor>(cursorMode));
+}
+
+bool Editor::DragThreshold(Point ptStart, Point ptNow) {
+ int xMove = ptStart.x - ptNow.x;
+ int yMove = ptStart.y - ptNow.y;
+ int distanceSquared = xMove * xMove + yMove * yMove;
+ return distanceSquared > 16;
+}
+
+void Editor::StartDrag() {
+ // Always handled by subclasses
+ //SetMouseCapture(true);
+ //DisplayCursor(Window::cursorArrow);
+}
+
+void Editor::DropAt(SelectionPosition position, const char *value, size_t lengthValue, bool moving, bool rectangular) {
+ //Platform::DebugPrintf("DropAt %d %d\n", inDragDrop, position);
+ if (inDragDrop == ddDragging)
+ dropWentOutside = false;
+
+ bool positionWasInSelection = PositionInSelection(position.Position());
+
+ bool positionOnEdgeOfSelection =
+ (position == SelectionStart()) || (position == SelectionEnd());
+
+ if ((inDragDrop != ddDragging) || !(positionWasInSelection) ||
+ (positionOnEdgeOfSelection && !moving)) {
+
+ SelectionPosition selStart = SelectionStart();
+ SelectionPosition selEnd = SelectionEnd();
+
+ UndoGroup ug(pdoc);
+
+ SelectionPosition positionAfterDeletion = position;
+ if ((inDragDrop == ddDragging) && moving) {
+ // Remove dragged out text
+ if (rectangular || sel.selType == Selection::selLines) {
+ for (size_t r=0; r<sel.Count(); r++) {
+ if (position >= sel.Range(r).Start()) {
+ if (position > sel.Range(r).End()) {
+ positionAfterDeletion.Add(-sel.Range(r).Length());
+ } else {
+ positionAfterDeletion.Add(-SelectionRange(position, sel.Range(r).Start()).Length());
+ }
+ }
+ }
+ } else {
+ if (position > selStart) {
+ positionAfterDeletion.Add(-SelectionRange(selEnd, selStart).Length());
+ }
+ }
+ ClearSelection();
+ }
+ position = positionAfterDeletion;
+
+ if (rectangular) {
+ PasteRectangular(position, value, static_cast<int>(lengthValue));
+ // Should try to select new rectangle but it may not be a rectangle now so just select the drop position
+ SetEmptySelection(position);
+ } else {
+ position = MovePositionOutsideChar(position, sel.MainCaret() - position.Position());
+ position = SelectionPosition(InsertSpace(position.Position(), position.VirtualSpace()));
+ if (pdoc->InsertString(position.Position(), value, static_cast<int>(lengthValue))) {
+ SelectionPosition posAfterInsertion = position;
+ posAfterInsertion.Add(static_cast<int>(lengthValue));
+ SetSelection(posAfterInsertion, position);
+ }
+ }
+ } else if (inDragDrop == ddDragging) {
+ SetEmptySelection(position);
+ }
+}
+
+void Editor::DropAt(SelectionPosition position, const char *value, bool moving, bool rectangular) {
+ DropAt(position, value, strlen(value), moving, rectangular);
+}
+
+/**
+ * @return true if given position is inside the selection,
+ */
+bool Editor::PositionInSelection(int pos) {
+ pos = MovePositionOutsideChar(pos, sel.MainCaret() - pos);
+ for (size_t r=0; r<sel.Count(); r++) {
+ if (sel.Range(r).Contains(pos))
+ return true;
+ }
+ return false;
+}
+
+bool Editor::PointInSelection(Point pt) {
+ SelectionPosition pos = SPositionFromLocation(pt, false, true);
+ Point ptPos = LocationFromPosition(pos);
+ for (size_t r=0; r<sel.Count(); r++) {
+ SelectionRange range = sel.Range(r);
+ if (range.Contains(pos)) {
+ bool hit = true;
+ if (pos == range.Start()) {
+ // see if just before selection
+ if (pt.x < ptPos.x) {
+ hit = false;
+ }
+ }
+ if (pos == range.End()) {
+ // see if just after selection
+ if (pt.x > ptPos.x) {
+ hit = false;
+ }
+ }
+ if (hit)
+ return true;
+ }
+ }
+ return false;
+}
+
+bool Editor::PointInSelMargin(Point pt) {
+ // Really means: "Point in a margin"
+ if (vs.fixedColumnWidth > 0) { // There is a margin
+ PRectangle rcSelMargin = GetClientRectangle();
+ rcSelMargin.right = vs.textStart - vs.leftMarginWidth;
+ rcSelMargin.left = vs.textStart - vs.fixedColumnWidth;
+ return rcSelMargin.Contains(pt);
+ } else {
+ return false;
+ }
+}
+
+Window::Cursor Editor::GetMarginCursor(Point pt) const {
+ int x = 0;
+ for (int margin = 0; margin <= SC_MAX_MARGIN; margin++) {
+ if ((pt.x >= x) && (pt.x < x + vs.ms[margin].width))
+ return static_cast<Window::Cursor>(vs.ms[margin].cursor);
+ x += vs.ms[margin].width;
+ }
+ return Window::cursorReverseArrow;
+}
+
+void Editor::TrimAndSetSelection(int currentPos_, int anchor_) {
+ sel.TrimSelection(SelectionRange(currentPos_, anchor_));
+ SetSelection(currentPos_, anchor_);
+}
+
+void Editor::LineSelection(int lineCurrentPos_, int lineAnchorPos_, bool wholeLine) {
+ int selCurrentPos, selAnchorPos;
+ if (wholeLine) {
+ int lineCurrent_ = pdoc->LineFromPosition(lineCurrentPos_);
+ int lineAnchor_ = pdoc->LineFromPosition(lineAnchorPos_);
+ if (lineAnchorPos_ < lineCurrentPos_) {
+ selCurrentPos = pdoc->LineStart(lineCurrent_ + 1);
+ selAnchorPos = pdoc->LineStart(lineAnchor_);
+ } else if (lineAnchorPos_ > lineCurrentPos_) {
+ selCurrentPos = pdoc->LineStart(lineCurrent_);
+ selAnchorPos = pdoc->LineStart(lineAnchor_ + 1);
+ } else { // Same line, select it
+ selCurrentPos = pdoc->LineStart(lineAnchor_ + 1);
+ selAnchorPos = pdoc->LineStart(lineAnchor_);
+ }
+ } else {
+ if (lineAnchorPos_ < lineCurrentPos_) {
+ selCurrentPos = StartEndDisplayLine(lineCurrentPos_, false) + 1;
+ selCurrentPos = pdoc->MovePositionOutsideChar(selCurrentPos, 1);
+ selAnchorPos = StartEndDisplayLine(lineAnchorPos_, true);
+ } else if (lineAnchorPos_ > lineCurrentPos_) {
+ selCurrentPos = StartEndDisplayLine(lineCurrentPos_, true);
+ selAnchorPos = StartEndDisplayLine(lineAnchorPos_, false) + 1;
+ selAnchorPos = pdoc->MovePositionOutsideChar(selAnchorPos, 1);
+ } else { // Same line, select it
+ selCurrentPos = StartEndDisplayLine(lineAnchorPos_, false) + 1;
+ selCurrentPos = pdoc->MovePositionOutsideChar(selCurrentPos, 1);
+ selAnchorPos = StartEndDisplayLine(lineAnchorPos_, true);
+ }
+ }
+ TrimAndSetSelection(selCurrentPos, selAnchorPos);
+}
+
+void Editor::WordSelection(int pos) {
+ if (pos < wordSelectAnchorStartPos) {
+ // Extend backward to the word containing pos.
+ // Skip ExtendWordSelect if the line is empty or if pos is after the last character.
+ // This ensures that a series of empty lines isn't counted as a single "word".
+ if (!pdoc->IsLineEndPosition(pos))
+ pos = pdoc->ExtendWordSelect(pdoc->MovePositionOutsideChar(pos + 1, 1), -1);
+ TrimAndSetSelection(pos, wordSelectAnchorEndPos);
+ } else if (pos > wordSelectAnchorEndPos) {
+ // Extend forward to the word containing the character to the left of pos.
+ // Skip ExtendWordSelect if the line is empty or if pos is the first position on the line.
+ // This ensures that a series of empty lines isn't counted as a single "word".
+ if (pos > pdoc->LineStart(pdoc->LineFromPosition(pos)))
+ pos = pdoc->ExtendWordSelect(pdoc->MovePositionOutsideChar(pos - 1, -1), 1);
+ TrimAndSetSelection(pos, wordSelectAnchorStartPos);
+ } else {
+ // Select only the anchored word
+ if (pos >= originalAnchorPos)
+ TrimAndSetSelection(wordSelectAnchorEndPos, wordSelectAnchorStartPos);
+ else
+ TrimAndSetSelection(wordSelectAnchorStartPos, wordSelectAnchorEndPos);
+ }
+}
+
+void Editor::DwellEnd(bool mouseMoved) {
+ if (mouseMoved)
+ ticksToDwell = dwellDelay;
+ else
+ ticksToDwell = SC_TIME_FOREVER;
+ if (dwelling && (dwellDelay < SC_TIME_FOREVER)) {
+ dwelling = false;
+ NotifyDwelling(ptMouseLast, dwelling);
+ }
+}
+
+void Editor::MouseLeave() {
+ SetHotSpotRange(NULL);
+ if (!HaveMouseCapture()) {
+ ptMouseLast = Point(-1,-1);
+ DwellEnd(true);
+ }
+}
+
+static bool AllowVirtualSpace(int virtualSpaceOptions, bool rectangular) {
+ return (!rectangular && ((virtualSpaceOptions & SCVS_USERACCESSIBLE) != 0))
+ || (rectangular && ((virtualSpaceOptions & SCVS_RECTANGULARSELECTION) != 0));
+}
+
+void Editor::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt) {
+ //Platform::DebugPrintf("ButtonDown %d %d = %d alt=%d %d\n", curTime, lastClickTime, curTime - lastClickTime, alt, inDragDrop);
+ ptMouseLast = pt;
+ SelectionPosition newPos = SPositionFromLocation(pt, false, false, AllowVirtualSpace(virtualSpaceOptions, alt));
+ newPos = MovePositionOutsideChar(newPos, sel.MainCaret() - newPos.Position());
+ inDragDrop = ddNone;
+ sel.SetMoveExtends(false);
+
+ if (NotifyMarginClick(pt, shift, ctrl, alt))
+ return;
+
+ NotifyIndicatorClick(true, newPos.Position(), shift, ctrl, alt);
+
+ bool inSelMargin = PointInSelMargin(pt);
+ // In margin ctrl+(double)click should always select everything
+ if (ctrl && inSelMargin) {
+ SelectAll();
+ lastClickTime = curTime;
+ lastClick = pt;
+ return;
+ }
+ if (shift && !inSelMargin) {
+ SetSelection(newPos);
+ }
+ if (((curTime - lastClickTime) < Platform::DoubleClickTime()) && Close(pt, lastClick)) {
+ //Platform::DebugPrintf("Double click %d %d = %d\n", curTime, lastClickTime, curTime - lastClickTime);
+ SetMouseCapture(true);
+ if (!ctrl || !multipleSelection || (selectionType != selChar && selectionType != selWord))
+ SetEmptySelection(newPos.Position());
+ bool doubleClick = false;
+ // Stop mouse button bounce changing selection type
+ if (!Platform::MouseButtonBounce() || curTime != lastClickTime) {
+ if (inSelMargin) {
+ // Inside margin selection type should be either selSubLine or selWholeLine.
+ if (selectionType == selSubLine) {
+ // If it is selSubLine, we're inside a *double* click and word wrap is enabled,
+ // so we switch to selWholeLine in order to select whole line.
+ selectionType = selWholeLine;
+ } else if (selectionType != selSubLine && selectionType != selWholeLine) {
+ // If it is neither, reset selection type to line selection.
+ selectionType = (Wrapping() && (marginOptions & SC_MARGINOPTION_SUBLINESELECT)) ? selSubLine : selWholeLine;
+ }
+ } else {
+ if (selectionType == selChar) {
+ selectionType = selWord;
+ doubleClick = true;
+ } else if (selectionType == selWord) {
+ // Since we ended up here, we're inside a *triple* click, which should always select
+ // whole line irregardless of word wrap being enabled or not.
+ selectionType = selWholeLine;
+ } else {
+ selectionType = selChar;
+ originalAnchorPos = sel.MainCaret();
+ }
+ }
+ }
+
+ if (selectionType == selWord) {
+ int charPos = originalAnchorPos;
+ if (sel.MainCaret() == originalAnchorPos) {
+ charPos = PositionFromLocation(pt, false, true);
+ charPos = MovePositionOutsideChar(charPos, -1);
+ }
+
+ int startWord, endWord;
+ if ((sel.MainCaret() >= originalAnchorPos) && !pdoc->IsLineEndPosition(charPos)) {
+ startWord = pdoc->ExtendWordSelect(pdoc->MovePositionOutsideChar(charPos + 1, 1), -1);
+ endWord = pdoc->ExtendWordSelect(charPos, 1);
+ } else {
+ // Selecting backwards, or anchor beyond last character on line. In these cases,
+ // we select the word containing the character to the *left* of the anchor.
+ if (charPos > pdoc->LineStart(pdoc->LineFromPosition(charPos))) {
+ startWord = pdoc->ExtendWordSelect(charPos, -1);
+ endWord = pdoc->ExtendWordSelect(startWord, 1);
+ } else {
+ // Anchor at start of line; select nothing to begin with.
+ startWord = charPos;
+ endWord = charPos;
+ }
+ }
+
+ wordSelectAnchorStartPos = startWord;
+ wordSelectAnchorEndPos = endWord;
+ wordSelectInitialCaretPos = sel.MainCaret();
+ WordSelection(wordSelectInitialCaretPos);
+ } else if (selectionType == selSubLine || selectionType == selWholeLine) {
+ lineAnchorPos = newPos.Position();
+ LineSelection(lineAnchorPos, lineAnchorPos, selectionType == selWholeLine);
+ //Platform::DebugPrintf("Triple click: %d - %d\n", anchor, currentPos);
+ } else {
+ SetEmptySelection(sel.MainCaret());
+ }
+ //Platform::DebugPrintf("Double click: %d - %d\n", anchor, currentPos);
+ if (doubleClick) {
+ NotifyDoubleClick(pt, shift, ctrl, alt);
+ if (PositionIsHotspot(newPos.Position()))
+ NotifyHotSpotDoubleClicked(newPos.Position(), shift, ctrl, alt);
+ }
+ } else { // Single click
+ if (inSelMargin) {
+ sel.selType = Selection::selStream;
+ if (!shift) {
+ // Single click in margin: select whole line or only subline if word wrap is enabled
+ lineAnchorPos = newPos.Position();
+ selectionType = (Wrapping() && (marginOptions & SC_MARGINOPTION_SUBLINESELECT)) ? selSubLine : selWholeLine;
+ LineSelection(lineAnchorPos, lineAnchorPos, selectionType == selWholeLine);
+ } else {
+ // Single shift+click in margin: select from line anchor to clicked line
+ if (sel.MainAnchor() > sel.MainCaret())
+ lineAnchorPos = sel.MainAnchor() - 1;
+ else
+ lineAnchorPos = sel.MainAnchor();
+ // Reset selection type if there is an empty selection.
+ // This ensures that we don't end up stuck in previous selection mode, which is no longer valid.
+ // Otherwise, if there's a non empty selection, reset selection type only if it differs from selSubLine and selWholeLine.
+ // This ensures that we continue selecting in the same selection mode.
+ if (sel.Empty() || (selectionType != selSubLine && selectionType != selWholeLine))
+ selectionType = (Wrapping() && (marginOptions & SC_MARGINOPTION_SUBLINESELECT)) ? selSubLine : selWholeLine;
+ LineSelection(newPos.Position(), lineAnchorPos, selectionType == selWholeLine);
+ }
+
+ SetDragPosition(SelectionPosition(invalidPosition));
+ SetMouseCapture(true);
+ } else {
+ if (PointIsHotspot(pt)) {
+ NotifyHotSpotClicked(newPos.Position(), shift, ctrl, alt);
+ hotSpotClickPos = PositionFromLocation(pt,true,false);
+ }
+ if (!shift) {
+ if (PointInSelection(pt) && !SelectionEmpty())
+ inDragDrop = ddInitial;
+ else
+ inDragDrop = ddNone;
+ }
+ SetMouseCapture(true);
+ if (inDragDrop != ddInitial) {
+ SetDragPosition(SelectionPosition(invalidPosition));
+ if (!shift) {
+ if (ctrl && multipleSelection) {
+ SelectionRange range(newPos);
+ sel.TentativeSelection(range);
+ InvalidateSelection(range, true);
+ } else {
+ InvalidateSelection(SelectionRange(newPos), true);
+ if (sel.Count() > 1)
+ Redraw();
+ if ((sel.Count() > 1) || (sel.selType != Selection::selStream))
+ sel.Clear();
+ sel.selType = alt ? Selection::selRectangle : Selection::selStream;
+ SetSelection(newPos, newPos);
+ }
+ }
+ SelectionPosition anchorCurrent = newPos;
+ if (shift)
+ anchorCurrent = sel.IsRectangular() ?
+ sel.Rectangular().anchor : sel.RangeMain().anchor;
+ sel.selType = alt ? Selection::selRectangle : Selection::selStream;
+ selectionType = selChar;
+ originalAnchorPos = sel.MainCaret();
+ sel.Rectangular() = SelectionRange(newPos, anchorCurrent);
+ SetRectangularRange();
+ }
+ }
+ }
+ lastClickTime = curTime;
+ lastClick = pt;
+ lastXChosen = pt.x + xOffset;
+ ShowCaretAtCurrentPosition();
+}
+
+bool Editor::PositionIsHotspot(int position) const {
+ return vs.styles[pdoc->StyleAt(position) & pdoc->stylingBitsMask].hotspot;
+}
+
+bool Editor::PointIsHotspot(Point pt) {
+ int pos = PositionFromLocation(pt, true);
+ if (pos == INVALID_POSITION)
+ return false;
+ return PositionIsHotspot(pos);
+}
+
+void Editor::SetHotSpotRange(Point *pt) {
+ if (pt) {
+ int pos = PositionFromLocation(*pt);
+
+ // If we don't limit this to word characters then the
+ // range can encompass more than the run range and then
+ // the underline will not be drawn properly.
+ int hsStart_ = pdoc->ExtendStyleRange(pos, -1, vs.hotspotSingleLine);
+ int hsEnd_ = pdoc->ExtendStyleRange(pos, 1, vs.hotspotSingleLine);
+
+ // Only invalidate the range if the hotspot range has changed...
+ if (hsStart_ != hsStart || hsEnd_ != hsEnd) {
+ if (hsStart != -1) {
+ InvalidateRange(hsStart, hsEnd);
+ }
+ hsStart = hsStart_;
+ hsEnd = hsEnd_;
+ InvalidateRange(hsStart, hsEnd);
+ }
+ } else {
+ if (hsStart != -1) {
+ int hsStart_ = hsStart;
+ int hsEnd_ = hsEnd;
+ hsStart = -1;
+ hsEnd = -1;
+ InvalidateRange(hsStart_, hsEnd_);
+ } else {
+ hsStart = -1;
+ hsEnd = -1;
+ }
+ }
+}
+
+void Editor::GetHotSpotRange(int &hsStart_, int &hsEnd_) const {
+ hsStart_ = hsStart;
+ hsEnd_ = hsEnd;
+}
+
+void Editor::ButtonMoveWithModifiers(Point pt, int modifiers) {
+ if ((ptMouseLast.x != pt.x) || (ptMouseLast.y != pt.y)) {
+ DwellEnd(true);
+ }
+
+ SelectionPosition movePos = SPositionFromLocation(pt, false, false,
+ AllowVirtualSpace(virtualSpaceOptions, sel.IsRectangular()));
+ movePos = MovePositionOutsideChar(movePos, sel.MainCaret() - movePos.Position());
+
+ if (inDragDrop == ddInitial) {
+ if (DragThreshold(ptMouseLast, pt)) {
+ SetMouseCapture(false);
+ SetDragPosition(movePos);
+ CopySelectionRange(&drag);
+ StartDrag();
+ }
+ return;
+ }
+
+ ptMouseLast = pt;
+ //Platform::DebugPrintf("Move %d %d\n", pt.x, pt.y);
+ if (HaveMouseCapture()) {
+
+ // Slow down autoscrolling/selection
+ autoScrollTimer.ticksToWait -= timer.tickSize;
+ if (autoScrollTimer.ticksToWait > 0)
+ return;
+ autoScrollTimer.ticksToWait = autoScrollDelay;
+
+ // Adjust selection
+ if (posDrag.IsValid()) {
+ SetDragPosition(movePos);
+ } else {
+ if (selectionType == selChar) {
+ if (sel.selType == Selection::selStream && (modifiers & SCI_ALT) && mouseSelectionRectangularSwitch) {
+ sel.selType = Selection::selRectangle;
+ }
+ if (sel.IsRectangular()) {
+ sel.Rectangular() = SelectionRange(movePos, sel.Rectangular().anchor);
+ SetSelection(movePos, sel.RangeMain().anchor);
+ } else if (sel.Count() > 1) {
+ InvalidateSelection(sel.RangeMain(), false);
+ SelectionRange range(movePos, sel.RangeMain().anchor);
+ sel.TentativeSelection(range);
+ InvalidateSelection(range, true);
+ } else {
+ SetSelection(movePos, sel.RangeMain().anchor);
+ }
+ } else if (selectionType == selWord) {
+ // Continue selecting by word
+ if (movePos.Position() == wordSelectInitialCaretPos) { // Didn't move
+ // No need to do anything. Previously this case was lumped
+ // in with "Moved forward", but that can be harmful in this
+ // case: a handler for the NotifyDoubleClick re-adjusts
+ // the selection for a fancier definition of "word" (for
+ // example, in Perl it is useful to include the leading
+ // '$', '%' or '@' on variables for word selection). In this
+ // the ButtonMove() called via Tick() for auto-scrolling
+ // could result in the fancier word selection adjustment
+ // being unmade.
+ } else {
+ wordSelectInitialCaretPos = -1;
+ WordSelection(movePos.Position());
+ }
+ } else {
+ // Continue selecting by line
+ LineSelection(movePos.Position(), lineAnchorPos, selectionType == selWholeLine);
+ }
+ }
+
+ // Autoscroll
+ PRectangle rcClient = GetClientRectangle();
+ Point ptOrigin = GetVisibleOriginInMain();
+ rcClient.Move(0, -ptOrigin.y);
+ int lineMove = DisplayFromPosition(movePos.Position());
+ if (pt.y > rcClient.bottom) {
+ ScrollTo(lineMove - LinesOnScreen() + 1);
+ Redraw();
+ } else if (pt.y < rcClient.top) {
+ ScrollTo(lineMove);
+ Redraw();
+ }
+ EnsureCaretVisible(false, false, true);
+
+ if (hsStart != -1 && !PositionIsHotspot(movePos.Position()))
+ SetHotSpotRange(NULL);
+
+ if (hotSpotClickPos != INVALID_POSITION && PositionFromLocation(pt,true,false) != hotSpotClickPos) {
+ if (inDragDrop == ddNone) {
+ DisplayCursor(Window::cursorText);
+ }
+ hotSpotClickPos = INVALID_POSITION;
+ }
+
+ } else {
+ if (vs.fixedColumnWidth > 0) { // There is a margin
+ if (PointInSelMargin(pt)) {
+ DisplayCursor(GetMarginCursor(pt));
+ SetHotSpotRange(NULL);
+ return; // No need to test for selection
+ }
+ }
+ // Display regular (drag) cursor over selection
+ if (PointInSelection(pt) && !SelectionEmpty()) {
+ DisplayCursor(Window::cursorArrow);
+ } else if (PointIsHotspot(pt)) {
+ DisplayCursor(Window::cursorHand);
+ SetHotSpotRange(&pt);
+ } else {
+ DisplayCursor(Window::cursorText);
+ SetHotSpotRange(NULL);
+ }
+ }
+}
+
+void Editor::ButtonMove(Point pt) {
+ ButtonMoveWithModifiers(pt, 0);
+}
+
+void Editor::ButtonUp(Point pt, unsigned int curTime, bool ctrl) {
+ //Platform::DebugPrintf("ButtonUp %d %d\n", HaveMouseCapture(), inDragDrop);
+ SelectionPosition newPos = SPositionFromLocation(pt, false, false,
+ AllowVirtualSpace(virtualSpaceOptions, sel.IsRectangular()));
+ newPos = MovePositionOutsideChar(newPos, sel.MainCaret() - newPos.Position());
+ if (inDragDrop == ddInitial) {
+ inDragDrop = ddNone;
+ SetEmptySelection(newPos);
+ selectionType = selChar;
+ originalAnchorPos = sel.MainCaret();
+ }
+ if (hotSpotClickPos != INVALID_POSITION && PointIsHotspot(pt)) {
+ hotSpotClickPos = INVALID_POSITION;
+ NotifyHotSpotReleaseClick(newPos.Position(), false, ctrl, false);
+ }
+ if (HaveMouseCapture()) {
+ if (PointInSelMargin(pt)) {
+ DisplayCursor(GetMarginCursor(pt));
+ } else {
+ DisplayCursor(Window::cursorText);
+ SetHotSpotRange(NULL);
+ }
+ ptMouseLast = pt;
+ SetMouseCapture(false);
+ NotifyIndicatorClick(false, newPos.Position(), false, false, false);
+ if (inDragDrop == ddDragging) {
+ SelectionPosition selStart = SelectionStart();
+ SelectionPosition selEnd = SelectionEnd();
+ if (selStart < selEnd) {
+ if (drag.Length()) {
+ if (ctrl) {
+ if (pdoc->InsertString(newPos.Position(), drag.Data(), static_cast<int>(drag.Length()))) {
+ SetSelection(newPos.Position(), newPos.Position() + static_cast<int>(drag.Length()));
+ }
+ } else if (newPos < selStart) {
+ pdoc->DeleteChars(selStart.Position(), static_cast<int>(drag.Length()));
+ if (pdoc->InsertString(newPos.Position(), drag.Data(), static_cast<int>(drag.Length()))) {
+ SetSelection(newPos.Position(), newPos.Position() + static_cast<int>(drag.Length()));
+ }
+ } else if (newPos > selEnd) {
+ pdoc->DeleteChars(selStart.Position(), static_cast<int>(drag.Length()));
+ newPos.Add(-static_cast<int>(drag.Length()));
+ if (pdoc->InsertString(newPos.Position(), drag.Data(), static_cast<int>(drag.Length()))) {
+ SetSelection(newPos.Position(), newPos.Position() + static_cast<int>(drag.Length()));
+ }
+ } else {
+ SetEmptySelection(newPos.Position());
+ }
+ drag.Clear();
+ }
+ selectionType = selChar;
+ }
+ } else {
+ if (selectionType == selChar) {
+ if (sel.Count() > 1) {
+ sel.RangeMain() =
+ SelectionRange(newPos, sel.Range(sel.Count() - 1).anchor);
+ InvalidateSelection(sel.RangeMain(), true);
+ } else {
+ SetSelection(newPos, sel.RangeMain().anchor);
+ }
+ }
+ sel.CommitTentative();
+ }
+ SetRectangularRange();
+ lastClickTime = curTime;
+ lastClick = pt;
+ lastXChosen = pt.x + xOffset;
+ if (sel.selType == Selection::selStream) {
+ SetLastXChosen();
+ }
+ inDragDrop = ddNone;
+ EnsureCaretVisible(false);
+ }
+}
+
+// Called frequently to perform background UI including
+// caret blinking and automatic scrolling.
+void Editor::Tick() {
+ if (HaveMouseCapture()) {
+ // Auto scroll
+ ButtonMove(ptMouseLast);
+ }
+ if (caret.period > 0) {
+ timer.ticksToWait -= timer.tickSize;
+ if (timer.ticksToWait <= 0) {
+ caret.on = !caret.on;
+ timer.ticksToWait = caret.period;
+ if (caret.active) {
+ InvalidateCaret();
+ }
+ }
+ }
+ if (horizontalScrollBarVisible && trackLineWidth && (lineWidthMaxSeen > scrollWidth)) {
+ scrollWidth = lineWidthMaxSeen;
+ SetScrollBars();
+ }
+ if ((dwellDelay < SC_TIME_FOREVER) &&
+ (ticksToDwell > 0) &&
+ (!HaveMouseCapture()) &&
+ (ptMouseLast.y >= 0)) {
+ ticksToDwell -= timer.tickSize;
+ if (ticksToDwell <= 0) {
+ dwelling = true;
+ NotifyDwelling(ptMouseLast, dwelling);
+ }
+ }
+}
+
+bool Editor::Idle() {
+
+ bool idleDone;
+
+ bool wrappingDone = !Wrapping();
+
+ if (!wrappingDone) {
+ // Wrap lines during idle.
+ WrapLines(wsIdle);
+ // No more wrapping
+ if (!wrapPending.NeedsWrap())
+ wrappingDone = true;
+ }
+
+ // Add more idle things to do here, but make sure idleDone is
+ // set correctly before the function returns. returning
+ // false will stop calling this idle funtion until SetIdle() is
+ // called again.
+
+ idleDone = wrappingDone; // && thatDone && theOtherThingDone...
+
+ return !idleDone;
+}
+
+void Editor::SetFocusState(bool focusState) {
+ hasFocus = focusState;
+ NotifyFocus(hasFocus);
+ if (hasFocus) {
+ ShowCaretAtCurrentPosition();
+ } else {
+ CancelModes();
+ DropCaret();
+ }
+}
+
+int Editor::PositionAfterArea(PRectangle rcArea) const {
+ // The start of the document line after the display line after the area
+ // This often means that the line after a modification is restyled which helps
+ // detect multiline comment additions and heals single line comments
+ int lineAfter = topLine + (rcArea.bottom - 1) / vs.lineHeight + 1;
+ if (lineAfter < cs.LinesDisplayed())
+ return pdoc->LineStart(cs.DocFromDisplay(lineAfter) + 1);
+ else
+ return pdoc->Length();
+}
+
+// Style to a position within the view. If this causes a change at end of last line then
+// affects later lines so style all the viewed text.
+void Editor::StyleToPositionInView(Position pos) {
+ int endWindow = (vs.marginInside) ? (PositionAfterArea(GetClientRectangle())) : (pdoc->Length());
+ if (pos > endWindow)
+ pos = endWindow;
+ int styleAtEnd = pdoc->StyleAt(pos-1);
+ pdoc->EnsureStyledTo(pos);
+ if ((endWindow > pos) && (styleAtEnd != pdoc->StyleAt(pos-1))) {
+ // Style at end of line changed so is multi-line change like starting a comment
+ // so require rest of window to be styled.
+ pdoc->EnsureStyledTo(endWindow);
+ }
+}
+
+void Editor::IdleWork() {
+ // Style the line after the modification as this allows modifications that change just the
+ // line of the modification to heal instead of propagating to the rest of the window.
+ if (workNeeded.items & WorkNeeded::workStyle)
+ StyleToPositionInView(pdoc->LineStart(pdoc->LineFromPosition(workNeeded.upTo) + 2));
+
+ NotifyUpdateUI();
+ workNeeded.Reset();
+}
+
+void Editor::QueueIdleWork(WorkNeeded::workItems items, int upTo) {
+ workNeeded.Need(items, upTo);
+}
+
+bool Editor::PaintContains(PRectangle rc) {
+ if (rc.Empty()) {
+ return true;
+ } else {
+ return rcPaint.Contains(rc);
+ }
+}
+
+bool Editor::PaintContainsMargin() {
+ if (wMargin.GetID()) {
+ // With separate margin view, paint of text view
+ // never contains margin.
+ return false;
+ }
+ PRectangle rcSelMargin = GetClientRectangle();
+ rcSelMargin.right = vs.textStart;
+ return PaintContains(rcSelMargin);
+}
+
+void Editor::CheckForChangeOutsidePaint(Range r) {
+ if (paintState == painting && !paintingAllText) {
+ //Platform::DebugPrintf("Checking range in paint %d-%d\n", r.start, r.end);
+ if (!r.Valid())
+ return;
+
+ PRectangle rcRange = RectangleFromRange(r.start, r.end);
+ PRectangle rcText = GetTextRectangle();
+ if (rcRange.top < rcText.top) {
+ rcRange.top = rcText.top;
+ }
+ if (rcRange.bottom > rcText.bottom) {
+ rcRange.bottom = rcText.bottom;
+ }
+
+ if (!PaintContains(rcRange)) {
+ AbandonPaint();
+ paintAbandonedByStyling = true;
+ }
+ }
+}
+
+void Editor::SetBraceHighlight(Position pos0, Position pos1, int matchStyle) {
+ if ((pos0 != braces[0]) || (pos1 != braces[1]) || (matchStyle != bracesMatchStyle)) {
+ if ((braces[0] != pos0) || (matchStyle != bracesMatchStyle)) {
+ CheckForChangeOutsidePaint(Range(braces[0]));
+ CheckForChangeOutsidePaint(Range(pos0));
+ braces[0] = pos0;
+ }
+ if ((braces[1] != pos1) || (matchStyle != bracesMatchStyle)) {
+ CheckForChangeOutsidePaint(Range(braces[1]));
+ CheckForChangeOutsidePaint(Range(pos1));
+ braces[1] = pos1;
+ }
+ bracesMatchStyle = matchStyle;
+ if (paintState == notPainting) {
+ Redraw();
+ }
+ }
+}
+
+void Editor::SetAnnotationHeights(int start, int end) {
+ if (vs.annotationVisible) {
+ bool changedHeight = false;
+ for (int line=start; line<end && line<pdoc->LinesTotal(); line++) {
+ int linesWrapped = 1;
+ if (Wrapping()) {
+ AutoSurface surface(this);
+ AutoLineLayout ll(llc, RetrieveLineLayout(line));
+ if (surface && ll) {
+ LayoutLine(line, surface, vs, ll, wrapWidth);
+ linesWrapped = ll->lines;
+ }
+ }
+ if (cs.SetHeight(line, pdoc->AnnotationLines(line) + linesWrapped))
+ changedHeight = true;
+ }
+ if (changedHeight) {
+ Redraw();
+ }
+ }
+}
+
+void Editor::SetDocPointer(Document *document) {
+ //Platform::DebugPrintf("** %x setdoc to %x\n", pdoc, document);
+ pdoc->RemoveWatcher(this, 0);
+ pdoc->Release();
+ if (document == NULL) {
+ pdoc = new Document();
+ } else {
+ pdoc = document;
+ }
+ pdoc->AddRef();
+
+ // Ensure all positions within document
+ sel.Clear();
+ targetStart = 0;
+ targetEnd = 0;
+
+ braces[0] = invalidPosition;
+ braces[1] = invalidPosition;
+
+ vs.ReleaseAllExtendedStyles();
+
+ SetRepresentations();
+
+ // Reset the contraction state to fully shown.
+ cs.Clear();
+ cs.InsertLines(0, pdoc->LinesTotal() - 1);
+ SetAnnotationHeights(0, pdoc->LinesTotal());
+ llc.Deallocate();
+ NeedWrapping();
+
+ pdoc->AddWatcher(this, 0);
+ SetScrollBars();
+ Redraw();
+}
+
+void Editor::SetAnnotationVisible(int visible) {
+ if (vs.annotationVisible != visible) {
+ bool changedFromOrToHidden = ((vs.annotationVisible != 0) != (visible != 0));
+ vs.annotationVisible = visible;
+ if (changedFromOrToHidden) {
+ int dir = vs.annotationVisible ? 1 : -1;
+ for (int line=0; line<pdoc->LinesTotal(); line++) {
+ int annotationLines = pdoc->AnnotationLines(line);
+ if (annotationLines > 0) {
+ cs.SetHeight(line, cs.GetHeight(line) + annotationLines * dir);
+ }
+ }
+ }
+ Redraw();
+ }
+}
+
+/**
+ * Recursively expand a fold, making lines visible except where they have an unexpanded parent.
+ */
+int Editor::ExpandLine(int line) {
+ int lineMaxSubord = pdoc->GetLastChild(line);
+ line++;
+ while (line <= lineMaxSubord) {
+ cs.SetVisible(line, line, true);
+ int level = pdoc->GetLevel(line);
+ if (level & SC_FOLDLEVELHEADERFLAG) {
+ if (cs.GetExpanded(line)) {
+ line = ExpandLine(line);
+ } else {
+ line = pdoc->GetLastChild(line);
+ }
+ }
+ line++;
+ }
+ return lineMaxSubord;
+}
+
+void Editor::SetFoldExpanded(int lineDoc, bool expanded) {
+ if (cs.SetExpanded(lineDoc, expanded)) {
+ RedrawSelMargin();
+ }
+}
+
+void Editor::FoldLine(int line, int action) {
+ if (line >= 0) {
+ if (action == SC_FOLDACTION_TOGGLE) {
+ if ((pdoc->GetLevel(line) & SC_FOLDLEVELHEADERFLAG) == 0) {
+ line = pdoc->GetFoldParent(line);
+ if (line < 0)
+ return;
+ }
+ action = (cs.GetExpanded(line)) ? SC_FOLDACTION_CONTRACT : SC_FOLDACTION_EXPAND;
+ }
+
+ if (action == SC_FOLDACTION_CONTRACT) {
+ int lineMaxSubord = pdoc->GetLastChild(line);
+ if (lineMaxSubord > line) {
+ cs.SetExpanded(line, 0);
+ cs.SetVisible(line + 1, lineMaxSubord, false);
+
+ int lineCurrent = pdoc->LineFromPosition(sel.MainCaret());
+ if (lineCurrent > line && lineCurrent <= lineMaxSubord) {
+ // This does not re-expand the fold
+ EnsureCaretVisible();
+ }
+ }
+
+ } else {
+ if (!(cs.GetVisible(line))) {
+ EnsureLineVisible(line, false);
+ GoToLine(line);
+ }
+ cs.SetExpanded(line, 1);
+ ExpandLine(line);
+ }
+
+ SetScrollBars();
+ Redraw();
+ }
+}
+
+void Editor::FoldExpand(int line, int action, int level) {
+ bool expanding = action == SC_FOLDACTION_EXPAND;
+ if (action == SC_FOLDACTION_TOGGLE) {
+ expanding = !cs.GetExpanded(line);
+ }
+ SetFoldExpanded(line, expanding);
+ if (expanding && (cs.HiddenLines() == 0))
+ // Nothing to do
+ return;
+ int lineMaxSubord = pdoc->GetLastChild(line, level & SC_FOLDLEVELNUMBERMASK);
+ line++;
+ cs.SetVisible(line, lineMaxSubord, expanding);
+ while (line <= lineMaxSubord) {
+ int levelLine = pdoc->GetLevel(line);
+ if (levelLine & SC_FOLDLEVELHEADERFLAG) {
+ SetFoldExpanded(line, expanding);
+ }
+ line++;
+ }
+ SetScrollBars();
+ Redraw();
+}
+
+int Editor::ContractedFoldNext(int lineStart) const {
+ for (int line = lineStart; line<pdoc->LinesTotal();) {
+ if (!cs.GetExpanded(line) && (pdoc->GetLevel(line) & SC_FOLDLEVELHEADERFLAG))
+ return line;
+ line = cs.ContractedNext(line+1);
+ if (line < 0)
+ return -1;
+ }
+
+ return -1;
+}
+
+/**
+ * Recurse up from this line to find any folds that prevent this line from being visible
+ * and unfold them all.
+ */
+void Editor::EnsureLineVisible(int lineDoc, bool enforcePolicy) {
+
+ // In case in need of wrapping to ensure DisplayFromDoc works.
+ if (lineDoc >= wrapPending.start)
+ WrapLines(wsAll);
+
+ if (!cs.GetVisible(lineDoc)) {
+ // Back up to find a non-blank line
+ int lookLine = lineDoc;
+ int lookLineLevel = pdoc->GetLevel(lookLine);
+ while ((lookLine > 0) && (lookLineLevel & SC_FOLDLEVELWHITEFLAG)) {
+ lookLineLevel = pdoc->GetLevel(--lookLine);
+ }
+ int lineParent = pdoc->GetFoldParent(lookLine);
+ if (lineParent < 0) {
+ // Backed up to a top level line, so try to find parent of initial line
+ lineParent = pdoc->GetFoldParent(lineDoc);
+ }
+ if (lineParent >= 0) {
+ if (lineDoc != lineParent)
+ EnsureLineVisible(lineParent, enforcePolicy);
+ if (!cs.GetExpanded(lineParent)) {
+ cs.SetExpanded(lineParent, 1);
+ ExpandLine(lineParent);
+ }
+ }
+ SetScrollBars();
+ Redraw();
+ }
+ if (enforcePolicy) {
+ int lineDisplay = cs.DisplayFromDoc(lineDoc);
+ if (visiblePolicy & VISIBLE_SLOP) {
+ if ((topLine > lineDisplay) || ((visiblePolicy & VISIBLE_STRICT) && (topLine + visibleSlop > lineDisplay))) {
+ SetTopLine(Platform::Clamp(lineDisplay - visibleSlop, 0, MaxScrollPos()));
+ SetVerticalScrollPos();
+ Redraw();
+ } else if ((lineDisplay > topLine + LinesOnScreen() - 1) ||
+ ((visiblePolicy & VISIBLE_STRICT) && (lineDisplay > topLine + LinesOnScreen() - 1 - visibleSlop))) {
+ SetTopLine(Platform::Clamp(lineDisplay - LinesOnScreen() + 1 + visibleSlop, 0, MaxScrollPos()));
+ SetVerticalScrollPos();
+ Redraw();
+ }
+ } else {
+ if ((topLine > lineDisplay) || (lineDisplay > topLine + LinesOnScreen() - 1) || (visiblePolicy & VISIBLE_STRICT)) {
+ SetTopLine(Platform::Clamp(lineDisplay - LinesOnScreen() / 2 + 1, 0, MaxScrollPos()));
+ SetVerticalScrollPos();
+ Redraw();
+ }
+ }
+ }
+}
+
+void Editor::FoldAll(int action) {
+ pdoc->EnsureStyledTo(pdoc->Length());
+ int maxLine = pdoc->LinesTotal();
+ bool expanding = action == SC_FOLDACTION_EXPAND;
+ if (action == SC_FOLDACTION_TOGGLE) {
+ // Discover current state
+ for (int lineSeek = 0; lineSeek < maxLine; lineSeek++) {
+ if (pdoc->GetLevel(lineSeek) & SC_FOLDLEVELHEADERFLAG) {
+ expanding = !cs.GetExpanded(lineSeek);
+ break;
+ }
+ }
+ }
+ if (expanding) {
+ cs.SetVisible(0, maxLine-1, true);
+ for (int line = 0; line < maxLine; line++) {
+ int levelLine = pdoc->GetLevel(line);
+ if (levelLine & SC_FOLDLEVELHEADERFLAG) {
+ SetFoldExpanded(line, true);
+ }
+ }
+ } else {
+ for (int line = 0; line < maxLine; line++) {
+ int level = pdoc->GetLevel(line);
+ if ((level & SC_FOLDLEVELHEADERFLAG) &&
+ (SC_FOLDLEVELBASE == (level & SC_FOLDLEVELNUMBERMASK))) {
+ SetFoldExpanded(line, false);
+ int lineMaxSubord = pdoc->GetLastChild(line, -1);
+ if (lineMaxSubord > line) {
+ cs.SetVisible(line + 1, lineMaxSubord, false);
+ }
+ }
+ }
+ }
+ SetScrollBars();
+ Redraw();
+}
+
+void Editor::FoldChanged(int line, int levelNow, int levelPrev) {
+ if (levelNow & SC_FOLDLEVELHEADERFLAG) {
+ if (!(levelPrev & SC_FOLDLEVELHEADERFLAG)) {
+ // Adding a fold point.
+ if (cs.SetExpanded(line, true)) {
+ RedrawSelMargin();
+ }
+ FoldExpand(line, SC_FOLDACTION_EXPAND, levelPrev);
+ }
+ } else if (levelPrev & SC_FOLDLEVELHEADERFLAG) {
+ if (!cs.GetExpanded(line)) {
+ // Removing the fold from one that has been contracted so should expand
+ // otherwise lines are left invisible with no way to make them visible
+ if (cs.SetExpanded(line, true)) {
+ RedrawSelMargin();
+ }
+ FoldExpand(line, SC_FOLDACTION_EXPAND, levelPrev);
+ }
+ }
+ if (!(levelNow & SC_FOLDLEVELWHITEFLAG) &&
+ ((levelPrev & SC_FOLDLEVELNUMBERMASK) > (levelNow & SC_FOLDLEVELNUMBERMASK))) {
+ if (cs.HiddenLines()) {
+ // See if should still be hidden
+ int parentLine = pdoc->GetFoldParent(line);
+ if ((parentLine < 0) || (cs.GetExpanded(parentLine) && cs.GetVisible(parentLine))) {
+ cs.SetVisible(line, line, true);
+ SetScrollBars();
+ Redraw();
+ }
+ }
+ }
+}
+
+void Editor::NeedShown(int pos, int len) {
+ if (foldAutomatic & SC_AUTOMATICFOLD_SHOW) {
+ int lineStart = pdoc->LineFromPosition(pos);
+ int lineEnd = pdoc->LineFromPosition(pos+len);
+ for (int line = lineStart; line <= lineEnd; line++) {
+ EnsureLineVisible(line, false);
+ }
+ } else {
+ NotifyNeedShown(pos, len);
+ }
+}
+
+int Editor::GetTag(char *tagValue, int tagNumber) {
+ const char *text = 0;
+ int length = 0;
+ if ((tagNumber >= 1) && (tagNumber <= 9)) {
+ char name[3] = "\\?";
+ name[1] = static_cast<char>(tagNumber + '0');
+ length = 2;
+ text = pdoc->SubstituteByPosition(name, &length);
+ }
+ if (tagValue) {
+ if (text)
+ memcpy(tagValue, text, length + 1);
+ else
+ *tagValue = '\0';
+ }
+ return length;
+}
+
+int Editor::ReplaceTarget(bool replacePatterns, const char *text, int length) {
+ UndoGroup ug(pdoc);
+ if (length == -1)
+ length = istrlen(text);
+ if (replacePatterns) {
+ text = pdoc->SubstituteByPosition(text, &length);
+ if (!text) {
+ return 0;
+ }
+ }
+ if (targetStart != targetEnd)
+ pdoc->DeleteChars(targetStart, targetEnd - targetStart);
+ targetEnd = targetStart;
+ pdoc->InsertString(targetStart, text, length);
+ targetEnd = targetStart + length;
+ return length;
+}
+
+bool Editor::IsUnicodeMode() const {
+ return pdoc && (SC_CP_UTF8 == pdoc->dbcsCodePage);
+}
+
+int Editor::CodePage() const {
+ if (pdoc)
+ return pdoc->dbcsCodePage;
+ else
+ return 0;
+}
+
+int Editor::WrapCount(int line) {
+ AutoSurface surface(this);
+ AutoLineLayout ll(llc, RetrieveLineLayout(line));
+
+ if (surface && ll) {
+ LayoutLine(line, surface, vs, ll, wrapWidth);
+ return ll->lines;
+ } else {
+ return 1;
+ }
+}
+
+void Editor::AddStyledText(char *buffer, int appendLength) {
+ // The buffer consists of alternating character bytes and style bytes
+ int textLength = appendLength / 2;
+ std::string text(textLength, '\0');
+ int i;
+ for (i = 0; i < textLength; i++) {
+ text[i] = buffer[i*2];
+ }
+ pdoc->InsertString(CurrentPosition(), text.c_str(), textLength);
+ for (i = 0; i < textLength; i++) {
+ text[i] = buffer[i*2+1];
+ }
+ pdoc->StartStyling(CurrentPosition(), static_cast<char>(0xff));
+ pdoc->SetStyles(textLength, text.c_str());
+ SetEmptySelection(sel.MainCaret() + textLength);
+}
+
+static bool ValidMargin(unsigned long wParam) {
+ return wParam <= SC_MAX_MARGIN;
+}
+
+static char *CharPtrFromSPtr(sptr_t lParam) {
+ return reinterpret_cast<char *>(lParam);
+}
+
+void Editor::StyleSetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
+ vs.EnsureStyle(wParam);
+ switch (iMessage) {
+ case SCI_STYLESETFORE:
+ vs.styles[wParam].fore = ColourDesired(lParam);
+ break;
+ case SCI_STYLESETBACK:
+ vs.styles[wParam].back = ColourDesired(lParam);
+ break;
+ case SCI_STYLESETBOLD:
+ vs.styles[wParam].weight = lParam != 0 ? SC_WEIGHT_BOLD : SC_WEIGHT_NORMAL;
+ break;
+ case SCI_STYLESETWEIGHT:
+ vs.styles[wParam].weight = lParam;
+ break;
+ case SCI_STYLESETITALIC:
+ vs.styles[wParam].italic = lParam != 0;
+ break;
+ case SCI_STYLESETEOLFILLED:
+ vs.styles[wParam].eolFilled = lParam != 0;
+ break;
+ case SCI_STYLESETSIZE:
+ vs.styles[wParam].size = lParam * SC_FONT_SIZE_MULTIPLIER;
+ break;
+ case SCI_STYLESETSIZEFRACTIONAL:
+ vs.styles[wParam].size = lParam;
+ break;
+ case SCI_STYLESETFONT:
+ if (lParam != 0) {
+ vs.SetStyleFontName(wParam, CharPtrFromSPtr(lParam));
+ }
+ break;
+ case SCI_STYLESETUNDERLINE:
+ vs.styles[wParam].underline = lParam != 0;
+ break;
+ case SCI_STYLESETCASE:
+ vs.styles[wParam].caseForce = static_cast<Style::ecaseForced>(lParam);
+ break;
+ case SCI_STYLESETCHARACTERSET:
+ vs.styles[wParam].characterSet = lParam;
+ pdoc->SetCaseFolder(NULL);
+ break;
+ case SCI_STYLESETVISIBLE:
+ vs.styles[wParam].visible = lParam != 0;
+ break;
+ case SCI_STYLESETCHANGEABLE:
+ vs.styles[wParam].changeable = lParam != 0;
+ break;
+ case SCI_STYLESETHOTSPOT:
+ vs.styles[wParam].hotspot = lParam != 0;
+ break;
+ }
+ InvalidateStyleRedraw();
+}
+
+sptr_t Editor::StyleGetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
+ vs.EnsureStyle(wParam);
+ switch (iMessage) {
+ case SCI_STYLEGETFORE:
+ return vs.styles[wParam].fore.AsLong();
+ case SCI_STYLEGETBACK:
+ return vs.styles[wParam].back.AsLong();
+ case SCI_STYLEGETBOLD:
+ return vs.styles[wParam].weight > SC_WEIGHT_NORMAL;
+ case SCI_STYLEGETWEIGHT:
+ return vs.styles[wParam].weight;
+ case SCI_STYLEGETITALIC:
+ return vs.styles[wParam].italic ? 1 : 0;
+ case SCI_STYLEGETEOLFILLED:
+ return vs.styles[wParam].eolFilled ? 1 : 0;
+ case SCI_STYLEGETSIZE:
+ return vs.styles[wParam].size / SC_FONT_SIZE_MULTIPLIER;
+ case SCI_STYLEGETSIZEFRACTIONAL:
+ return vs.styles[wParam].size;
+ case SCI_STYLEGETFONT:
+ if (!vs.styles[wParam].fontName)
+ return 0;
+ if (lParam != 0)
+ strcpy(CharPtrFromSPtr(lParam), vs.styles[wParam].fontName);
+ return strlen(vs.styles[wParam].fontName);
+ case SCI_STYLEGETUNDERLINE:
+ return vs.styles[wParam].underline ? 1 : 0;
+ case SCI_STYLEGETCASE:
+ return static_cast<int>(vs.styles[wParam].caseForce);
+ case SCI_STYLEGETCHARACTERSET:
+ return vs.styles[wParam].characterSet;
+ case SCI_STYLEGETVISIBLE:
+ return vs.styles[wParam].visible ? 1 : 0;
+ case SCI_STYLEGETCHANGEABLE:
+ return vs.styles[wParam].changeable ? 1 : 0;
+ case SCI_STYLEGETHOTSPOT:
+ return vs.styles[wParam].hotspot ? 1 : 0;
+ }
+ return 0;
+}
+
+sptr_t Editor::StringResult(sptr_t lParam, const char *val) {
+ const size_t n = strlen(val);
+ if (lParam != 0) {
+ char *ptr = reinterpret_cast<char *>(lParam);
+ strcpy(ptr, val);
+ }
+ return n; // Not including NUL
+}
+
+sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
+ //Platform::DebugPrintf("S start wnd proc %d %d %d\n",iMessage, wParam, lParam);
+
+ // Optional macro recording hook
+ if (recordingMacro)
+ NotifyMacroRecord(iMessage, wParam, lParam);
+
+ switch (iMessage) {
+
+ case SCI_GETTEXT: {
+ if (lParam == 0)
+ return pdoc->Length() + 1;
+ if (wParam == 0)
+ return 0;
+ char *ptr = CharPtrFromSPtr(lParam);
+ unsigned int iChar = 0;
+ for (; iChar < wParam - 1; iChar++)
+ ptr[iChar] = pdoc->CharAt(iChar);
+ ptr[iChar] = '\0';
+ return iChar;
+ }
+
+ case SCI_SETTEXT: {
+ if (lParam == 0)
+ return 0;
+ UndoGroup ug(pdoc);
+ pdoc->DeleteChars(0, pdoc->Length());
+ SetEmptySelection(0);
+ pdoc->InsertCString(0, CharPtrFromSPtr(lParam));
+ return 1;
+ }
+
+ case SCI_GETTEXTLENGTH:
+ return pdoc->Length();
+
+ case SCI_CUT:
+ Cut();
+ SetLastXChosen();
+ break;
+
+ case SCI_COPY:
+ Copy();
+ break;
+
+ case SCI_COPYALLOWLINE:
+ CopyAllowLine();
+ break;
+
+ case SCI_VERTICALCENTRECARET:
+ VerticalCentreCaret();
+ break;
+
+ case SCI_MOVESELECTEDLINESUP:
+ MoveSelectedLinesUp();
+ break;
+
+ case SCI_MOVESELECTEDLINESDOWN:
+ MoveSelectedLinesDown();
+ break;
+
+ case SCI_COPYRANGE:
+ CopyRangeToClipboard(wParam, lParam);
+ break;
+
+ case SCI_COPYTEXT:
+ CopyText(wParam, CharPtrFromSPtr(lParam));
+ break;
+
+ case SCI_PASTE:
+ Paste();
+ if ((caretSticky == SC_CARETSTICKY_OFF) || (caretSticky == SC_CARETSTICKY_WHITESPACE)) {
+ SetLastXChosen();
+ }
+ EnsureCaretVisible();
+ break;
+
+ case SCI_CLEAR:
+ Clear();
+ SetLastXChosen();
+ EnsureCaretVisible();
+ break;
+
+ case SCI_UNDO:
+ Undo();
+ SetLastXChosen();
+ break;
+
+ case SCI_CANUNDO:
+ return (pdoc->CanUndo() && !pdoc->IsReadOnly()) ? 1 : 0;
+
+ case SCI_EMPTYUNDOBUFFER:
+ pdoc->DeleteUndoHistory();
+ return 0;
+
+ case SCI_GETFIRSTVISIBLELINE:
+ return topLine;
+
+ case SCI_SETFIRSTVISIBLELINE:
+ ScrollTo(wParam);
+ break;
+
+ case SCI_GETLINE: { // Risk of overwriting the end of the buffer
+ int lineStart = pdoc->LineStart(wParam);
+ int lineEnd = pdoc->LineStart(wParam + 1);
+ if (lParam == 0) {
+ return lineEnd - lineStart;
+ }
+ char *ptr = CharPtrFromSPtr(lParam);
+ int iPlace = 0;
+ for (int iChar = lineStart; iChar < lineEnd; iChar++) {
+ ptr[iPlace++] = pdoc->CharAt(iChar);
+ }
+ return iPlace;
+ }
+
+ case SCI_GETLINECOUNT:
+ if (pdoc->LinesTotal() == 0)
+ return 1;
+ else
+ return pdoc->LinesTotal();
+
+ case SCI_GETMODIFY:
+ return !pdoc->IsSavePoint();
+
+ case SCI_SETSEL: {
+ int nStart = static_cast<int>(wParam);
+ int nEnd = static_cast<int>(lParam);
+ if (nEnd < 0)
+ nEnd = pdoc->Length();
+ if (nStart < 0)
+ nStart = nEnd; // Remove selection
+ InvalidateSelection(SelectionRange(nStart, nEnd));
+ sel.Clear();
+ sel.selType = Selection::selStream;
+ SetSelection(nEnd, nStart);
+ EnsureCaretVisible();
+ }
+ break;
+
+ case SCI_GETSELTEXT: {
+ SelectionText selectedText;
+ CopySelectionRange(&selectedText);
+ if (lParam == 0) {
+ return selectedText.LengthWithTerminator();
+ } else {
+ char *ptr = CharPtrFromSPtr(lParam);
+ unsigned int iChar = 0;
+ if (selectedText.Length()) {
+ for (; iChar < selectedText.LengthWithTerminator(); iChar++)
+ ptr[iChar] = selectedText.Data()[iChar];
+ } else {
+ ptr[0] = '\0';
+ }
+ return iChar;
+ }
+ }
+
+ case SCI_LINEFROMPOSITION:
+ if (static_cast<int>(wParam) < 0)
+ return 0;
+ return pdoc->LineFromPosition(wParam);
+
+ case SCI_POSITIONFROMLINE:
+ if (static_cast<int>(wParam) < 0)
+ wParam = pdoc->LineFromPosition(SelectionStart().Position());
+ if (wParam == 0)
+ return 0; // Even if there is no text, there is a first line that starts at 0
+ if (static_cast<int>(wParam) > pdoc->LinesTotal())
+ return -1;
+ //if (wParam > pdoc->LineFromPosition(pdoc->Length())) // Useful test, anyway...
+ // return -1;
+ return pdoc->LineStart(wParam);
+
+ // Replacement of the old Scintilla interpretation of EM_LINELENGTH
+ case SCI_LINELENGTH:
+ if ((static_cast<int>(wParam) < 0) ||
+ (static_cast<int>(wParam) > pdoc->LineFromPosition(pdoc->Length())))
+ return 0;
+ return pdoc->LineStart(wParam + 1) - pdoc->LineStart(wParam);
+
+ case SCI_REPLACESEL: {
+ if (lParam == 0)
+ return 0;
+ UndoGroup ug(pdoc);
+ ClearSelection();
+ char *replacement = CharPtrFromSPtr(lParam);
+ pdoc->InsertCString(sel.MainCaret(), replacement);
+ SetEmptySelection(sel.MainCaret() + istrlen(replacement));
+ EnsureCaretVisible();
+ }
+ break;
+
+ case SCI_SETTARGETSTART:
+ targetStart = wParam;
+ break;
+
+ case SCI_GETTARGETSTART:
+ return targetStart;
+
+ case SCI_SETTARGETEND:
+ targetEnd = wParam;
+ break;
+
+ case SCI_GETTARGETEND:
+ return targetEnd;
+
+ case SCI_TARGETFROMSELECTION:
+ if (sel.MainCaret() < sel.MainAnchor()) {
+ targetStart = sel.MainCaret();
+ targetEnd = sel.MainAnchor();
+ } else {
+ targetStart = sel.MainAnchor();
+ targetEnd = sel.MainCaret();
+ }
+ break;
+
+ case SCI_REPLACETARGET:
+ PLATFORM_ASSERT(lParam);
+ return ReplaceTarget(false, CharPtrFromSPtr(lParam), wParam);
+
+ case SCI_REPLACETARGETRE:
+ PLATFORM_ASSERT(lParam);
+ return ReplaceTarget(true, CharPtrFromSPtr(lParam), wParam);
+
+ case SCI_SEARCHINTARGET:
+ PLATFORM_ASSERT(lParam);
+ return SearchInTarget(CharPtrFromSPtr(lParam), wParam);
+
+ case SCI_SETSEARCHFLAGS:
+ searchFlags = wParam;
+ break;
+
+ case SCI_GETSEARCHFLAGS:
+ return searchFlags;
+
+ case SCI_GETTAG:
+ return GetTag(CharPtrFromSPtr(lParam), wParam);
+
+ case SCI_POSITIONBEFORE:
+ return pdoc->MovePositionOutsideChar(wParam - 1, -1, true);
+
+ case SCI_POSITIONAFTER:
+ return pdoc->MovePositionOutsideChar(wParam + 1, 1, true);
+
+ case SCI_POSITIONRELATIVE:
+ return Platform::Clamp(pdoc->GetRelativePosition(wParam, lParam), 0, pdoc->Length());
+
+ case SCI_LINESCROLL:
+ ScrollTo(topLine + lParam);
+ HorizontalScrollTo(xOffset + static_cast<int>(wParam) * vs.spaceWidth);
+ return 1;
+
+ case SCI_SETXOFFSET:
+ xOffset = wParam;
+ ContainerNeedsUpdate(SC_UPDATE_H_SCROLL);
+ SetHorizontalScrollPos();
+ Redraw();
+ break;
+
+ case SCI_GETXOFFSET:
+ return xOffset;
+
+ case SCI_CHOOSECARETX:
+ SetLastXChosen();
+ break;
+
+ case SCI_SCROLLCARET:
+ EnsureCaretVisible();
+ break;
+
+ case SCI_SETREADONLY:
+ pdoc->SetReadOnly(wParam != 0);
+ return 1;
+
+ case SCI_GETREADONLY:
+ return pdoc->IsReadOnly();
+
+ case SCI_CANPASTE:
+ return CanPaste();
+
+ case SCI_POINTXFROMPOSITION:
+ if (lParam < 0) {
+ return 0;
+ } else {
+ Point pt = LocationFromPosition(lParam);
+ // Convert to view-relative
+ return pt.x - vs.textStart + vs.fixedColumnWidth;
+ }
+
+ case SCI_POINTYFROMPOSITION:
+ if (lParam < 0) {
+ return 0;
+ } else {
+ Point pt = LocationFromPosition(lParam);
+ return pt.y;
+ }
+
+ case SCI_FINDTEXT:
+ return FindText(wParam, lParam);
+
+ case SCI_GETTEXTRANGE: {
+ if (lParam == 0)
+ return 0;
+ Sci_TextRange *tr = reinterpret_cast<Sci_TextRange *>(lParam);
+ int cpMax = tr->chrg.cpMax;
+ if (cpMax == -1)
+ cpMax = pdoc->Length();
+ PLATFORM_ASSERT(cpMax <= pdoc->Length());
+ int len = cpMax - tr->chrg.cpMin; // No -1 as cpMin and cpMax are referring to inter character positions
+ pdoc->GetCharRange(tr->lpstrText, tr->chrg.cpMin, len);
+ // Spec says copied text is terminated with a NUL
+ tr->lpstrText[len] = '\0';
+ return len; // Not including NUL
+ }
+
+ case SCI_HIDESELECTION:
+ hideSelection = wParam != 0;
+ Redraw();
+ break;
+
+ case SCI_FORMATRANGE:
+ return FormatRange(wParam != 0, reinterpret_cast<Sci_RangeToFormat *>(lParam));
+
+ case SCI_GETMARGINLEFT:
+ return vs.leftMarginWidth;
+
+ case SCI_GETMARGINRIGHT:
+ return vs.rightMarginWidth;
+
+ case SCI_SETMARGINLEFT:
+ lastXChosen += lParam - vs.leftMarginWidth;
+ vs.leftMarginWidth = lParam;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_SETMARGINRIGHT:
+ vs.rightMarginWidth = lParam;
+ InvalidateStyleRedraw();
+ break;
+
+ // Control specific mesages
+
+ case SCI_ADDTEXT: {
+ if (lParam == 0)
+ return 0;
+ pdoc->InsertString(CurrentPosition(), CharPtrFromSPtr(lParam), wParam);
+ SetEmptySelection(sel.MainCaret() + wParam);
+ return 0;
+ }
+
+ case SCI_ADDSTYLEDTEXT:
+ if (lParam)
+ AddStyledText(CharPtrFromSPtr(lParam), wParam);
+ return 0;
+
+ case SCI_INSERTTEXT: {
+ if (lParam == 0)
+ return 0;
+ int insertPos = wParam;
+ if (static_cast<int>(wParam) == -1)
+ insertPos = CurrentPosition();
+ int newCurrent = CurrentPosition();
+ char *sz = CharPtrFromSPtr(lParam);
+ pdoc->InsertCString(insertPos, sz);
+ if (newCurrent > insertPos)
+ newCurrent += istrlen(sz);
+ SetEmptySelection(newCurrent);
+ return 0;
+ }
+
+ case SCI_APPENDTEXT:
+ pdoc->InsertString(pdoc->Length(), CharPtrFromSPtr(lParam), wParam);
+ return 0;
+
+ case SCI_CLEARALL:
+ ClearAll();
+ return 0;
+
+ case SCI_DELETERANGE:
+ pdoc->DeleteChars(wParam, lParam);
+ return 0;
+
+ case SCI_CLEARDOCUMENTSTYLE:
+ ClearDocumentStyle();
+ return 0;
+
+ case SCI_SETUNDOCOLLECTION:
+ pdoc->SetUndoCollection(wParam != 0);
+ return 0;
+
+ case SCI_GETUNDOCOLLECTION:
+ return pdoc->IsCollectingUndo();
+
+ case SCI_BEGINUNDOACTION:
+ pdoc->BeginUndoAction();
+ return 0;
+
+ case SCI_ENDUNDOACTION:
+ pdoc->EndUndoAction();
+ return 0;
+
+ case SCI_GETCARETPERIOD:
+ return caret.period;
+
+ case SCI_SETCARETPERIOD:
+ caret.period = wParam;
+ break;
+
+ case SCI_GETWORDCHARS:
+ return pdoc->GetCharsOfClass(CharClassify::ccWord, reinterpret_cast<unsigned char *>(lParam));
+
+ case SCI_SETWORDCHARS: {
+ pdoc->SetDefaultCharClasses(false);
+ if (lParam == 0)
+ return 0;
+ pdoc->SetCharClasses(reinterpret_cast<unsigned char *>(lParam), CharClassify::ccWord);
+ }
+ break;
+
+ case SCI_GETWHITESPACECHARS:
+ return pdoc->GetCharsOfClass(CharClassify::ccSpace, reinterpret_cast<unsigned char *>(lParam));
+
+ case SCI_SETWHITESPACECHARS: {
+ if (lParam == 0)
+ return 0;
+ pdoc->SetCharClasses(reinterpret_cast<unsigned char *>(lParam), CharClassify::ccSpace);
+ }
+ break;
+
+ case SCI_GETPUNCTUATIONCHARS:
+ return pdoc->GetCharsOfClass(CharClassify::ccPunctuation, reinterpret_cast<unsigned char *>(lParam));
+
+ case SCI_SETPUNCTUATIONCHARS: {
+ if (lParam == 0)
+ return 0;
+ pdoc->SetCharClasses(reinterpret_cast<unsigned char *>(lParam), CharClassify::ccPunctuation);
+ }
+ break;
+
+ case SCI_SETCHARSDEFAULT:
+ pdoc->SetDefaultCharClasses(true);
+ break;
+
+ case SCI_GETLENGTH:
+ return pdoc->Length();
+
+ case SCI_ALLOCATE:
+ pdoc->Allocate(wParam);
+ break;
+
+ case SCI_GETCHARAT:
+ return pdoc->CharAt(wParam);
+
+ case SCI_SETCURRENTPOS:
+ if (sel.IsRectangular()) {
+ sel.Rectangular().caret.SetPosition(wParam);
+ SetRectangularRange();
+ Redraw();
+ } else {
+ SetSelection(wParam, sel.MainAnchor());
+ }
+ break;
+
+ case SCI_GETCURRENTPOS:
+ return sel.IsRectangular() ? sel.Rectangular().caret.Position() : sel.MainCaret();
+
+ case SCI_SETANCHOR:
+ if (sel.IsRectangular()) {
+ sel.Rectangular().anchor.SetPosition(wParam);
+ SetRectangularRange();
+ Redraw();
+ } else {
+ SetSelection(sel.MainCaret(), wParam);
+ }
+ break;
+
+ case SCI_GETANCHOR:
+ return sel.IsRectangular() ? sel.Rectangular().anchor.Position() : sel.MainAnchor();
+
+ case SCI_SETSELECTIONSTART:
+ SetSelection(Platform::Maximum(sel.MainCaret(), wParam), wParam);
+ break;
+
+ case SCI_GETSELECTIONSTART:
+ return sel.LimitsForRectangularElseMain().start.Position();
+
+ case SCI_SETSELECTIONEND:
+ SetSelection(wParam, Platform::Minimum(sel.MainAnchor(), wParam));
+ break;
+
+ case SCI_GETSELECTIONEND:
+ return sel.LimitsForRectangularElseMain().end.Position();
+
+ case SCI_SETEMPTYSELECTION:
+ SetEmptySelection(wParam);
+ break;
+
+ case SCI_SETPRINTMAGNIFICATION:
+ printParameters.magnification = wParam;
+ break;
+
+ case SCI_GETPRINTMAGNIFICATION:
+ return printParameters.magnification;
+
+ case SCI_SETPRINTCOLOURMODE:
+ printParameters.colourMode = wParam;
+ break;
+
+ case SCI_GETPRINTCOLOURMODE:
+ return printParameters.colourMode;
+
+ case SCI_SETPRINTWRAPMODE:
+ printParameters.wrapState = (wParam == SC_WRAP_WORD) ? eWrapWord : eWrapNone;
+ break;
+
+ case SCI_GETPRINTWRAPMODE:
+ return printParameters.wrapState;
+
+ case SCI_GETSTYLEAT:
+ if (static_cast<int>(wParam) >= pdoc->Length())
+ return 0;
+ else
+ return pdoc->StyleAt(wParam);
+
+ case SCI_REDO:
+ Redo();
+ break;
+
+ case SCI_SELECTALL:
+ SelectAll();
+ break;
+
+ case SCI_SETSAVEPOINT:
+ pdoc->SetSavePoint();
+ break;
+
+ case SCI_GETSTYLEDTEXT: {
+ if (lParam == 0)
+ return 0;
+ Sci_TextRange *tr = reinterpret_cast<Sci_TextRange *>(lParam);
+ int iPlace = 0;
+ for (int iChar = tr->chrg.cpMin; iChar < tr->chrg.cpMax; iChar++) {
+ tr->lpstrText[iPlace++] = pdoc->CharAt(iChar);
+ tr->lpstrText[iPlace++] = pdoc->StyleAt(iChar);
+ }
+ tr->lpstrText[iPlace] = '\0';
+ tr->lpstrText[iPlace + 1] = '\0';
+ return iPlace;
+ }
+
+ case SCI_CANREDO:
+ return (pdoc->CanRedo() && !pdoc->IsReadOnly()) ? 1 : 0;
+
+ case SCI_MARKERLINEFROMHANDLE:
+ return pdoc->LineFromHandle(wParam);
+
+ case SCI_MARKERDELETEHANDLE:
+ pdoc->DeleteMarkFromHandle(wParam);
+ break;
+
+ case SCI_GETVIEWWS:
+ return vs.viewWhitespace;
+
+ case SCI_SETVIEWWS:
+ vs.viewWhitespace = static_cast<WhiteSpaceVisibility>(wParam);
+ Redraw();
+ break;
+
+ case SCI_GETWHITESPACESIZE:
+ return vs.whitespaceSize;
+
+ case SCI_SETWHITESPACESIZE:
+ vs.whitespaceSize = static_cast<int>(wParam);
+ Redraw();
+ break;
+
+ case SCI_POSITIONFROMPOINT:
+ return PositionFromLocation(Point(wParam - vs.ExternalMarginWidth(), lParam),
+ false, false);
+
+ case SCI_POSITIONFROMPOINTCLOSE:
+ return PositionFromLocation(Point(wParam - vs.ExternalMarginWidth(), lParam),
+ true, false);
+
+ case SCI_CHARPOSITIONFROMPOINT:
+ return PositionFromLocation(Point(wParam - vs.ExternalMarginWidth(), lParam),
+ false, true);
+
+ case SCI_CHARPOSITIONFROMPOINTCLOSE:
+ return PositionFromLocation(Point(wParam - vs.ExternalMarginWidth(), lParam),
+ true, true);
+
+ case SCI_GOTOLINE:
+ GoToLine(wParam);
+ break;
+
+ case SCI_GOTOPOS:
+ SetEmptySelection(wParam);
+ EnsureCaretVisible();
+ break;
+
+ case SCI_GETCURLINE: {
+ int lineCurrentPos = pdoc->LineFromPosition(sel.MainCaret());
+ int lineStart = pdoc->LineStart(lineCurrentPos);
+ unsigned int lineEnd = pdoc->LineStart(lineCurrentPos + 1);
+ if (lParam == 0) {
+ return 1 + lineEnd - lineStart;
+ }
+ PLATFORM_ASSERT(wParam > 0);
+ char *ptr = CharPtrFromSPtr(lParam);
+ unsigned int iPlace = 0;
+ for (unsigned int iChar = lineStart; iChar < lineEnd && iPlace < wParam - 1; iChar++) {
+ ptr[iPlace++] = pdoc->CharAt(iChar);
+ }
+ ptr[iPlace] = '\0';
+ return sel.MainCaret() - lineStart;
+ }
+
+ case SCI_GETENDSTYLED:
+ return pdoc->GetEndStyled();
+
+ case SCI_GETEOLMODE:
+ return pdoc->eolMode;
+
+ case SCI_SETEOLMODE:
+ pdoc->eolMode = wParam;
+ break;
+
+ case SCI_SETLINEENDTYPESALLOWED:
+ if (pdoc->SetLineEndTypesAllowed(wParam)) {
+ cs.Clear();
+ cs.InsertLines(0, pdoc->LinesTotal() - 1);
+ SetAnnotationHeights(0, pdoc->LinesTotal());
+ InvalidateStyleRedraw();
+ }
+ break;
+
+ case SCI_GETLINEENDTYPESALLOWED:
+ return pdoc->GetLineEndTypesAllowed();
+
+ case SCI_GETLINEENDTYPESACTIVE:
+ return pdoc->GetLineEndTypesActive();
+
+ case SCI_STARTSTYLING:
+ pdoc->StartStyling(wParam, static_cast<char>(lParam));
+ break;
+
+ case SCI_SETSTYLING:
+ pdoc->SetStyleFor(wParam, static_cast<char>(lParam));
+ break;
+
+ case SCI_SETSTYLINGEX: // Specify a complete styling buffer
+ if (lParam == 0)
+ return 0;
+ pdoc->SetStyles(wParam, CharPtrFromSPtr(lParam));
+ break;
+
+ case SCI_SETBUFFEREDDRAW:
+ bufferedDraw = wParam != 0;
+ break;
+
+ case SCI_GETBUFFEREDDRAW:
+ return bufferedDraw;
+
+ case SCI_GETTWOPHASEDRAW:
+ return twoPhaseDraw;
+
+ case SCI_SETTWOPHASEDRAW:
+ twoPhaseDraw = wParam != 0;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_SETFONTQUALITY:
+ vs.extraFontFlag &= ~SC_EFF_QUALITY_MASK;
+ vs.extraFontFlag |= (wParam & SC_EFF_QUALITY_MASK);
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETFONTQUALITY:
+ return (vs.extraFontFlag & SC_EFF_QUALITY_MASK);
+
+ case SCI_SETTABWIDTH:
+ if (wParam > 0) {
+ pdoc->tabInChars = wParam;
+ if (pdoc->indentInChars == 0)
+ pdoc->actualIndentInChars = pdoc->tabInChars;
+ }
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETTABWIDTH:
+ return pdoc->tabInChars;
+
+ case SCI_SETINDENT:
+ pdoc->indentInChars = wParam;
+ if (pdoc->indentInChars != 0)
+ pdoc->actualIndentInChars = pdoc->indentInChars;
+ else
+ pdoc->actualIndentInChars = pdoc->tabInChars;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETINDENT:
+ return pdoc->indentInChars;
+
+ case SCI_SETUSETABS:
+ pdoc->useTabs = wParam != 0;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETUSETABS:
+ return pdoc->useTabs;
+
+ case SCI_SETLINEINDENTATION:
+ pdoc->SetLineIndentation(wParam, lParam);
+ break;
+
+ case SCI_GETLINEINDENTATION:
+ return pdoc->GetLineIndentation(wParam);
+
+ case SCI_GETLINEINDENTPOSITION:
+ return pdoc->GetLineIndentPosition(wParam);
+
+ case SCI_SETTABINDENTS:
+ pdoc->tabIndents = wParam != 0;
+ break;
+
+ case SCI_GETTABINDENTS:
+ return pdoc->tabIndents;
+
+ case SCI_SETBACKSPACEUNINDENTS:
+ pdoc->backspaceUnindents = wParam != 0;
+ break;
+
+ case SCI_GETBACKSPACEUNINDENTS:
+ return pdoc->backspaceUnindents;
+
+ case SCI_SETMOUSEDWELLTIME:
+ dwellDelay = wParam;
+ ticksToDwell = dwellDelay;
+ break;
+
+ case SCI_GETMOUSEDWELLTIME:
+ return dwellDelay;
+
+ case SCI_WORDSTARTPOSITION:
+ return pdoc->ExtendWordSelect(wParam, -1, lParam != 0);
+
+ case SCI_WORDENDPOSITION:
+ return pdoc->ExtendWordSelect(wParam, 1, lParam != 0);
+
+ case SCI_SETWRAPMODE:
+ if (vs.SetWrapState(wParam)) {
+ xOffset = 0;
+ ContainerNeedsUpdate(SC_UPDATE_H_SCROLL);
+ InvalidateStyleRedraw();
+ ReconfigureScrollBars();
+ }
+ break;
+
+ case SCI_GETWRAPMODE:
+ return vs.wrapState;
+
+ case SCI_SETWRAPVISUALFLAGS:
+ if (vs.SetWrapVisualFlags(wParam)) {
+ InvalidateStyleRedraw();
+ ReconfigureScrollBars();
+ }
+ break;
+
+ case SCI_GETWRAPVISUALFLAGS:
+ return vs.wrapVisualFlags;
+
+ case SCI_SETWRAPVISUALFLAGSLOCATION:
+ if (vs.SetWrapVisualFlagsLocation(wParam)) {
+ InvalidateStyleRedraw();
+ }
+ break;
+
+ case SCI_GETWRAPVISUALFLAGSLOCATION:
+ return vs.wrapVisualFlagsLocation;
+
+ case SCI_SETWRAPSTARTINDENT:
+ if (vs.SetWrapVisualStartIndent(wParam)) {
+ InvalidateStyleRedraw();
+ ReconfigureScrollBars();
+ }
+ break;
+
+ case SCI_GETWRAPSTARTINDENT:
+ return vs.wrapVisualStartIndent;
+
+ case SCI_SETWRAPINDENTMODE:
+ if (vs.SetWrapIndentMode(wParam)) {
+ InvalidateStyleRedraw();
+ ReconfigureScrollBars();
+ }
+ break;
+
+ case SCI_GETWRAPINDENTMODE:
+ return vs.wrapIndentMode;
+
+ case SCI_SETLAYOUTCACHE:
+ llc.SetLevel(wParam);
+ break;
+
+ case SCI_GETLAYOUTCACHE:
+ return llc.GetLevel();
+
+ case SCI_SETPOSITIONCACHE:
+ posCache.SetSize(wParam);
+ break;
+
+ case SCI_GETPOSITIONCACHE:
+ return posCache.GetSize();
+
+ case SCI_SETSCROLLWIDTH:
+ PLATFORM_ASSERT(wParam > 0);
+ if ((wParam > 0) && (wParam != static_cast<unsigned int >(scrollWidth))) {
+ lineWidthMaxSeen = 0;
+ scrollWidth = wParam;
+ SetScrollBars();
+ }
+ break;
+
+ case SCI_GETSCROLLWIDTH:
+ return scrollWidth;
+
+ case SCI_SETSCROLLWIDTHTRACKING:
+ trackLineWidth = wParam != 0;
+ break;
+
+ case SCI_GETSCROLLWIDTHTRACKING:
+ return trackLineWidth;
+
+ case SCI_LINESJOIN:
+ LinesJoin();
+ break;
+
+ case SCI_LINESSPLIT:
+ LinesSplit(wParam);
+ break;
+
+ case SCI_TEXTWIDTH:
+ PLATFORM_ASSERT(wParam < vs.styles.size());
+ PLATFORM_ASSERT(lParam);
+ return TextWidth(wParam, CharPtrFromSPtr(lParam));
+
+ case SCI_TEXTHEIGHT:
+ return vs.lineHeight;
+
+ case SCI_SETENDATLASTLINE:
+ PLATFORM_ASSERT((wParam == 0) || (wParam == 1));
+ if (endAtLastLine != (wParam != 0)) {
+ endAtLastLine = wParam != 0;
+ SetScrollBars();
+ }
+ break;
+
+ case SCI_GETENDATLASTLINE:
+ return endAtLastLine;
+
+ case SCI_SETCARETSTICKY:
+ PLATFORM_ASSERT(wParam <= SC_CARETSTICKY_WHITESPACE);
+ if (wParam <= SC_CARETSTICKY_WHITESPACE) {
+ caretSticky = wParam;
+ }
+ break;
+
+ case SCI_GETCARETSTICKY:
+ return caretSticky;
+
+ case SCI_TOGGLECARETSTICKY:
+ caretSticky = !caretSticky;
+ break;
+
+ case SCI_GETCOLUMN:
+ return pdoc->GetColumn(wParam);
+
+ case SCI_FINDCOLUMN:
+ return pdoc->FindColumn(wParam, lParam);
+
+ case SCI_SETHSCROLLBAR :
+ if (horizontalScrollBarVisible != (wParam != 0)) {
+ horizontalScrollBarVisible = wParam != 0;
+ SetScrollBars();
+ ReconfigureScrollBars();
+ }
+ break;
+
+ case SCI_GETHSCROLLBAR:
+ return horizontalScrollBarVisible;
+
+ case SCI_SETVSCROLLBAR:
+ if (verticalScrollBarVisible != (wParam != 0)) {
+ verticalScrollBarVisible = wParam != 0;
+ SetScrollBars();
+ ReconfigureScrollBars();
+ if (verticalScrollBarVisible)
+ SetVerticalScrollPos();
+ }
+ break;
+
+ case SCI_GETVSCROLLBAR:
+ return verticalScrollBarVisible;
+
+ case SCI_SETINDENTATIONGUIDES:
+ vs.viewIndentationGuides = IndentView(wParam);
+ Redraw();
+ break;
+
+ case SCI_GETINDENTATIONGUIDES:
+ return vs.viewIndentationGuides;
+
+ case SCI_SETHIGHLIGHTGUIDE:
+ if ((highlightGuideColumn != static_cast<int>(wParam)) || (wParam > 0)) {
+ highlightGuideColumn = wParam;
+ Redraw();
+ }
+ break;
+
+ case SCI_GETHIGHLIGHTGUIDE:
+ return highlightGuideColumn;
+
+ case SCI_GETLINEENDPOSITION:
+ return pdoc->LineEnd(wParam);
+
+ case SCI_SETCODEPAGE:
+ if (ValidCodePage(wParam)) {
+ if (pdoc->SetDBCSCodePage(wParam)) {
+ cs.Clear();
+ cs.InsertLines(0, pdoc->LinesTotal() - 1);
+ SetAnnotationHeights(0, pdoc->LinesTotal());
+ InvalidateStyleRedraw();
+ SetRepresentations();
+ }
+ }
+ break;
+
+ case SCI_GETCODEPAGE:
+ return pdoc->dbcsCodePage;
+
+#ifdef INCLUDE_DEPRECATED_FEATURES
+ case SCI_SETUSEPALETTE:
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETUSEPALETTE:
+ return 0;
+#endif
+
+ // Marker definition and setting
+ case SCI_MARKERDEFINE:
+ if (wParam <= MARKER_MAX) {
+ vs.markers[wParam].markType = lParam;
+ vs.CalcLargestMarkerHeight();
+ }
+ InvalidateStyleData();
+ RedrawSelMargin();
+ break;
+
+ case SCI_MARKERSYMBOLDEFINED:
+ if (wParam <= MARKER_MAX)
+ return vs.markers[wParam].markType;
+ else
+ return 0;
+
+ case SCI_MARKERSETFORE:
+ if (wParam <= MARKER_MAX)
+ vs.markers[wParam].fore = ColourDesired(lParam);
+ InvalidateStyleData();
+ RedrawSelMargin();
+ break;
+ case SCI_MARKERSETBACKSELECTED:
+ if (wParam <= MARKER_MAX)
+ vs.markers[wParam].backSelected = ColourDesired(lParam);
+ InvalidateStyleData();
+ RedrawSelMargin();
+ break;
+ case SCI_MARKERENABLEHIGHLIGHT:
+ highlightDelimiter.isEnabled = wParam == 1;
+ RedrawSelMargin();
+ break;
+ case SCI_MARKERSETBACK:
+ if (wParam <= MARKER_MAX)
+ vs.markers[wParam].back = ColourDesired(lParam);
+ InvalidateStyleData();
+ RedrawSelMargin();
+ break;
+ case SCI_MARKERSETALPHA:
+ if (wParam <= MARKER_MAX)
+ vs.markers[wParam].alpha = lParam;
+ InvalidateStyleRedraw();
+ break;
+ case SCI_MARKERADD: {
+ int markerID = pdoc->AddMark(wParam, lParam);
+ return markerID;
+ }
+ case SCI_MARKERADDSET:
+ if (lParam != 0)
+ pdoc->AddMarkSet(wParam, lParam);
+ break;
+
+ case SCI_MARKERDELETE:
+ pdoc->DeleteMark(wParam, lParam);
+ break;
+
+ case SCI_MARKERDELETEALL:
+ pdoc->DeleteAllMarks(static_cast<int>(wParam));
+ break;
+
+ case SCI_MARKERGET:
+ return pdoc->GetMark(wParam);
+
+ case SCI_MARKERNEXT:
+ return pdoc->MarkerNext(wParam, lParam);
+
+ case SCI_MARKERPREVIOUS: {
+ for (int iLine = wParam; iLine >= 0; iLine--) {
+ if ((pdoc->GetMark(iLine) & lParam) != 0)
+ return iLine;
+ }
+ }
+ return -1;
+
+ case SCI_MARKERDEFINEPIXMAP:
+ if (wParam <= MARKER_MAX) {
+ vs.markers[wParam].SetXPM(CharPtrFromSPtr(lParam));
+ vs.CalcLargestMarkerHeight();
+ };
+ InvalidateStyleData();
+ RedrawSelMargin();
+ break;
+
+ case SCI_RGBAIMAGESETWIDTH:
+ sizeRGBAImage.x = wParam;
+ break;
+
+ case SCI_RGBAIMAGESETHEIGHT:
+ sizeRGBAImage.y = wParam;
+ break;
+
+ case SCI_RGBAIMAGESETSCALE:
+ scaleRGBAImage = wParam;
+ break;
+
+ case SCI_MARKERDEFINERGBAIMAGE:
+ if (wParam <= MARKER_MAX) {
+ vs.markers[wParam].SetRGBAImage(sizeRGBAImage, scaleRGBAImage / 100.0, reinterpret_cast<unsigned char *>(lParam));
+ vs.CalcLargestMarkerHeight();
+ };
+ InvalidateStyleData();
+ RedrawSelMargin();
+ break;
+
+ case SCI_SETMARGINTYPEN:
+ if (ValidMargin(wParam)) {
+ vs.ms[wParam].style = lParam;
+ InvalidateStyleRedraw();
+ }
+ break;
+
+ case SCI_GETMARGINTYPEN:
+ if (ValidMargin(wParam))
+ return vs.ms[wParam].style;
+ else
+ return 0;
+
+ case SCI_SETMARGINWIDTHN:
+ if (ValidMargin(wParam)) {
+ // Short-circuit if the width is unchanged, to avoid unnecessary redraw.
+ if (vs.ms[wParam].width != lParam) {
+ lastXChosen += lParam - vs.ms[wParam].width;
+ vs.ms[wParam].width = lParam;
+ InvalidateStyleRedraw();
+ }
+ }
+ break;
+
+ case SCI_GETMARGINWIDTHN:
+ if (ValidMargin(wParam))
+ return vs.ms[wParam].width;
+ else
+ return 0;
+
+ case SCI_SETMARGINMASKN:
+ if (ValidMargin(wParam)) {
+ vs.ms[wParam].mask = lParam;
+ InvalidateStyleRedraw();
+ }
+ break;
+
+ case SCI_GETMARGINMASKN:
+ if (ValidMargin(wParam))
+ return vs.ms[wParam].mask;
+ else
+ return 0;
+
+ case SCI_SETMARGINSENSITIVEN:
+ if (ValidMargin(wParam)) {
+ vs.ms[wParam].sensitive = lParam != 0;
+ InvalidateStyleRedraw();
+ }
+ break;
+
+ case SCI_GETMARGINSENSITIVEN:
+ if (ValidMargin(wParam))
+ return vs.ms[wParam].sensitive ? 1 : 0;
+ else
+ return 0;
+
+ case SCI_SETMARGINCURSORN:
+ if (ValidMargin(wParam))
+ vs.ms[wParam].cursor = lParam;
+ break;
+
+ case SCI_GETMARGINCURSORN:
+ if (ValidMargin(wParam))
+ return vs.ms[wParam].cursor;
+ else
+ return 0;
+
+ case SCI_STYLECLEARALL:
+ vs.ClearStyles();
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_STYLESETFORE:
+ case SCI_STYLESETBACK:
+ case SCI_STYLESETBOLD:
+ case SCI_STYLESETWEIGHT:
+ case SCI_STYLESETITALIC:
+ case SCI_STYLESETEOLFILLED:
+ case SCI_STYLESETSIZE:
+ case SCI_STYLESETSIZEFRACTIONAL:
+ case SCI_STYLESETFONT:
+ case SCI_STYLESETUNDERLINE:
+ case SCI_STYLESETCASE:
+ case SCI_STYLESETCHARACTERSET:
+ case SCI_STYLESETVISIBLE:
+ case SCI_STYLESETCHANGEABLE:
+ case SCI_STYLESETHOTSPOT:
+ StyleSetMessage(iMessage, wParam, lParam);
+ break;
+
+ case SCI_STYLEGETFORE:
+ case SCI_STYLEGETBACK:
+ case SCI_STYLEGETBOLD:
+ case SCI_STYLEGETWEIGHT:
+ case SCI_STYLEGETITALIC:
+ case SCI_STYLEGETEOLFILLED:
+ case SCI_STYLEGETSIZE:
+ case SCI_STYLEGETSIZEFRACTIONAL:
+ case SCI_STYLEGETFONT:
+ case SCI_STYLEGETUNDERLINE:
+ case SCI_STYLEGETCASE:
+ case SCI_STYLEGETCHARACTERSET:
+ case SCI_STYLEGETVISIBLE:
+ case SCI_STYLEGETCHANGEABLE:
+ case SCI_STYLEGETHOTSPOT:
+ return StyleGetMessage(iMessage, wParam, lParam);
+
+ case SCI_STYLERESETDEFAULT:
+ vs.ResetDefaultStyle();
+ InvalidateStyleRedraw();
+ break;
+ case SCI_SETSTYLEBITS:
+ vs.EnsureStyle((1 << wParam) - 1);
+ pdoc->SetStylingBits(wParam);
+ break;
+
+ case SCI_GETSTYLEBITS:
+ return pdoc->stylingBits;
+
+ case SCI_SETLINESTATE:
+ return pdoc->SetLineState(wParam, lParam);
+
+ case SCI_GETLINESTATE:
+ return pdoc->GetLineState(wParam);
+
+ case SCI_GETMAXLINESTATE:
+ return pdoc->GetMaxLineState();
+
+ case SCI_GETCARETLINEVISIBLE:
+ return vs.showCaretLineBackground;
+ case SCI_SETCARETLINEVISIBLE:
+ vs.showCaretLineBackground = wParam != 0;
+ InvalidateStyleRedraw();
+ break;
+ case SCI_GETCARETLINEVISIBLEALWAYS:
+ return vs.alwaysShowCaretLineBackground;
+ case SCI_SETCARETLINEVISIBLEALWAYS:
+ vs.alwaysShowCaretLineBackground = wParam != 0;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETCARETLINEBACK:
+ return vs.caretLineBackground.AsLong();
+ case SCI_SETCARETLINEBACK:
+ vs.caretLineBackground = wParam;
+ InvalidateStyleRedraw();
+ break;
+ case SCI_GETCARETLINEBACKALPHA:
+ return vs.caretLineAlpha;
+ case SCI_SETCARETLINEBACKALPHA:
+ vs.caretLineAlpha = wParam;
+ InvalidateStyleRedraw();
+ break;
+
+ // Folding messages
+
+ case SCI_VISIBLEFROMDOCLINE:
+ return cs.DisplayFromDoc(wParam);
+
+ case SCI_DOCLINEFROMVISIBLE:
+ return cs.DocFromDisplay(wParam);
+
+ case SCI_WRAPCOUNT:
+ return WrapCount(wParam);
+
+ case SCI_SETFOLDLEVEL: {
+ int prev = pdoc->SetLevel(wParam, lParam);
+ if (prev != lParam)
+ RedrawSelMargin();
+ return prev;
+ }
+
+ case SCI_GETFOLDLEVEL:
+ return pdoc->GetLevel(wParam);
+
+ case SCI_GETLASTCHILD:
+ return pdoc->GetLastChild(wParam, lParam);
+
+ case SCI_GETFOLDPARENT:
+ return pdoc->GetFoldParent(wParam);
+
+ case SCI_SHOWLINES:
+ cs.SetVisible(wParam, lParam, true);
+ SetScrollBars();
+ Redraw();
+ break;
+
+ case SCI_HIDELINES:
+ if (wParam > 0)
+ cs.SetVisible(wParam, lParam, false);
+ SetScrollBars();
+ Redraw();
+ break;
+
+ case SCI_GETLINEVISIBLE:
+ return cs.GetVisible(wParam);
+
+ case SCI_GETALLLINESVISIBLE:
+ return cs.HiddenLines() ? 0 : 1;
+
+ case SCI_SETFOLDEXPANDED:
+ SetFoldExpanded(wParam, lParam != 0);
+ break;
+
+ case SCI_GETFOLDEXPANDED:
+ return cs.GetExpanded(wParam);
+
+ case SCI_SETAUTOMATICFOLD:
+ foldAutomatic = wParam;
+ break;
+
+ case SCI_GETAUTOMATICFOLD:
+ return foldAutomatic;
+
+ case SCI_SETFOLDFLAGS:
+ foldFlags = wParam;
+ Redraw();
+ break;
+
+ case SCI_TOGGLEFOLD:
+ FoldLine(wParam, SC_FOLDACTION_TOGGLE);
+ break;
+
+ case SCI_FOLDLINE:
+ FoldLine(wParam, lParam);
+ break;
+
+ case SCI_FOLDCHILDREN:
+ FoldExpand(wParam, lParam, pdoc->GetLevel(wParam));
+ break;
+
+ case SCI_FOLDALL:
+ FoldAll(wParam);
+ break;
+
+ case SCI_EXPANDCHILDREN:
+ FoldExpand(wParam, SC_FOLDACTION_EXPAND, lParam);
+ break;
+
+ case SCI_CONTRACTEDFOLDNEXT:
+ return ContractedFoldNext(wParam);
+
+ case SCI_ENSUREVISIBLE:
+ EnsureLineVisible(wParam, false);
+ break;
+
+ case SCI_ENSUREVISIBLEENFORCEPOLICY:
+ EnsureLineVisible(wParam, true);
+ break;
+
+ case SCI_SCROLLRANGE:
+ ScrollRange(SelectionRange(lParam, wParam));
+ break;
+
+ case SCI_SEARCHANCHOR:
+ SearchAnchor();
+ break;
+
+ case SCI_SEARCHNEXT:
+ case SCI_SEARCHPREV:
+ return SearchText(iMessage, wParam, lParam);
+
+ case SCI_SETXCARETPOLICY:
+ caretXPolicy = wParam;
+ caretXSlop = lParam;
+ break;
+
+ case SCI_SETYCARETPOLICY:
+ caretYPolicy = wParam;
+ caretYSlop = lParam;
+ break;
+
+ case SCI_SETVISIBLEPOLICY:
+ visiblePolicy = wParam;
+ visibleSlop = lParam;
+ break;
+
+ case SCI_LINESONSCREEN:
+ return LinesOnScreen();
+
+ case SCI_SETSELFORE:
+ vs.selColours.fore = ColourOptional(wParam, lParam);
+ vs.selAdditionalForeground = ColourDesired(lParam);
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_SETSELBACK:
+ vs.selColours.back = ColourOptional(wParam, lParam);
+ vs.selAdditionalBackground = ColourDesired(lParam);
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_SETSELALPHA:
+ vs.selAlpha = wParam;
+ vs.selAdditionalAlpha = wParam;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETSELALPHA:
+ return vs.selAlpha;
+
+ case SCI_GETSELEOLFILLED:
+ return vs.selEOLFilled;
+
+ case SCI_SETSELEOLFILLED:
+ vs.selEOLFilled = wParam != 0;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_SETWHITESPACEFORE:
+ vs.whitespaceColours.fore = ColourOptional(wParam, lParam);
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_SETWHITESPACEBACK:
+ vs.whitespaceColours.back = ColourOptional(wParam, lParam);
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_SETCARETFORE:
+ vs.caretcolour = ColourDesired(wParam);
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETCARETFORE:
+ return vs.caretcolour.AsLong();
+
+ case SCI_SETCARETSTYLE:
+ if (wParam <= CARETSTYLE_BLOCK)
+ vs.caretStyle = wParam;
+ else
+ /* Default to the line caret */
+ vs.caretStyle = CARETSTYLE_LINE;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETCARETSTYLE:
+ return vs.caretStyle;
+
+ case SCI_SETCARETWIDTH:
+ if (static_cast<int>(wParam) <= 0)
+ vs.caretWidth = 0;
+ else if (wParam >= 3)
+ vs.caretWidth = 3;
+ else
+ vs.caretWidth = wParam;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETCARETWIDTH:
+ return vs.caretWidth;
+
+ case SCI_ASSIGNCMDKEY:
+ kmap.AssignCmdKey(Platform::LowShortFromLong(wParam),
+ Platform::HighShortFromLong(wParam), lParam);
+ break;
+
+ case SCI_CLEARCMDKEY:
+ kmap.AssignCmdKey(Platform::LowShortFromLong(wParam),
+ Platform::HighShortFromLong(wParam), SCI_NULL);
+ break;
+
+ case SCI_CLEARALLCMDKEYS:
+ kmap.Clear();
+ break;
+
+ case SCI_INDICSETSTYLE:
+ if (wParam <= INDIC_MAX) {
+ vs.indicators[wParam].style = lParam;
+ InvalidateStyleRedraw();
+ }
+ break;
+
+ case SCI_INDICGETSTYLE:
+ return (wParam <= INDIC_MAX) ? vs.indicators[wParam].style : 0;
+
+ case SCI_INDICSETFORE:
+ if (wParam <= INDIC_MAX) {
+ vs.indicators[wParam].fore = ColourDesired(lParam);
+ InvalidateStyleRedraw();
+ }
+ break;
+
+ case SCI_INDICGETFORE:
+ return (wParam <= INDIC_MAX) ? vs.indicators[wParam].fore.AsLong() : 0;
+
+ case SCI_INDICSETUNDER:
+ if (wParam <= INDIC_MAX) {
+ vs.indicators[wParam].under = lParam != 0;
+ InvalidateStyleRedraw();
+ }
+ break;
+
+ case SCI_INDICGETUNDER:
+ return (wParam <= INDIC_MAX) ? vs.indicators[wParam].under : 0;
+
+ case SCI_INDICSETALPHA:
+ if (wParam <= INDIC_MAX && lParam >=0 && lParam <= 255) {
+ vs.indicators[wParam].fillAlpha = lParam;
+ InvalidateStyleRedraw();
+ }
+ break;
+
+ case SCI_INDICGETALPHA:
+ return (wParam <= INDIC_MAX) ? vs.indicators[wParam].fillAlpha : 0;
+
+ case SCI_INDICSETOUTLINEALPHA:
+ if (wParam <= INDIC_MAX && lParam >=0 && lParam <= 255) {
+ vs.indicators[wParam].outlineAlpha = lParam;
+ InvalidateStyleRedraw();
+ }
+ break;
+
+ case SCI_INDICGETOUTLINEALPHA:
+ return (wParam <= INDIC_MAX) ? vs.indicators[wParam].outlineAlpha : 0;
+
+ case SCI_SETINDICATORCURRENT:
+ pdoc->decorations.SetCurrentIndicator(wParam);
+ break;
+ case SCI_GETINDICATORCURRENT:
+ return pdoc->decorations.GetCurrentIndicator();
+ case SCI_SETINDICATORVALUE:
+ pdoc->decorations.SetCurrentValue(wParam);
+ break;
+ case SCI_GETINDICATORVALUE:
+ return pdoc->decorations.GetCurrentValue();
+
+ case SCI_INDICATORFILLRANGE:
+ pdoc->DecorationFillRange(wParam, pdoc->decorations.GetCurrentValue(), lParam);
+ break;
+
+ case SCI_INDICATORCLEARRANGE:
+ pdoc->DecorationFillRange(wParam, 0, lParam);
+ break;
+
+ case SCI_INDICATORALLONFOR:
+ return pdoc->decorations.AllOnFor(wParam);
+
+ case SCI_INDICATORVALUEAT:
+ return pdoc->decorations.ValueAt(wParam, lParam);
+
+ case SCI_INDICATORSTART:
+ return pdoc->decorations.Start(wParam, lParam);
+
+ case SCI_INDICATOREND:
+ return pdoc->decorations.End(wParam, lParam);
+
+ case SCI_LINEDOWN:
+ case SCI_LINEDOWNEXTEND:
+ case SCI_PARADOWN:
+ case SCI_PARADOWNEXTEND:
+ case SCI_LINEUP:
+ case SCI_LINEUPEXTEND:
+ case SCI_PARAUP:
+ case SCI_PARAUPEXTEND:
+ case SCI_CHARLEFT:
+ case SCI_CHARLEFTEXTEND:
+ case SCI_CHARRIGHT:
+ case SCI_CHARRIGHTEXTEND:
+ case SCI_WORDLEFT:
+ case SCI_WORDLEFTEXTEND:
+ case SCI_WORDRIGHT:
+ case SCI_WORDRIGHTEXTEND:
+ case SCI_WORDLEFTEND:
+ case SCI_WORDLEFTENDEXTEND:
+ case SCI_WORDRIGHTEND:
+ case SCI_WORDRIGHTENDEXTEND:
+ case SCI_HOME:
+ case SCI_HOMEEXTEND:
+ case SCI_LINEEND:
+ case SCI_LINEENDEXTEND:
+ case SCI_HOMEWRAP:
+ case SCI_HOMEWRAPEXTEND:
+ case SCI_LINEENDWRAP:
+ case SCI_LINEENDWRAPEXTEND:
+ case SCI_DOCUMENTSTART:
+ case SCI_DOCUMENTSTARTEXTEND:
+ case SCI_DOCUMENTEND:
+ case SCI_DOCUMENTENDEXTEND:
+ case SCI_SCROLLTOSTART:
+ case SCI_SCROLLTOEND:
+
+ case SCI_STUTTEREDPAGEUP:
+ case SCI_STUTTEREDPAGEUPEXTEND:
+ case SCI_STUTTEREDPAGEDOWN:
+ case SCI_STUTTEREDPAGEDOWNEXTEND:
+
+ case SCI_PAGEUP:
+ case SCI_PAGEUPEXTEND:
+ case SCI_PAGEDOWN:
+ case SCI_PAGEDOWNEXTEND:
+ case SCI_EDITTOGGLEOVERTYPE:
+ case SCI_CANCEL:
+ case SCI_DELETEBACK:
+ case SCI_TAB:
+ case SCI_BACKTAB:
+ case SCI_NEWLINE:
+ case SCI_FORMFEED:
+ case SCI_VCHOME:
+ case SCI_VCHOMEEXTEND:
+ case SCI_VCHOMEWRAP:
+ case SCI_VCHOMEWRAPEXTEND:
+ case SCI_VCHOMEDISPLAY:
+ case SCI_VCHOMEDISPLAYEXTEND:
+ case SCI_ZOOMIN:
+ case SCI_ZOOMOUT:
+ case SCI_DELWORDLEFT:
+ case SCI_DELWORDRIGHT:
+ case SCI_DELWORDRIGHTEND:
+ case SCI_DELLINELEFT:
+ case SCI_DELLINERIGHT:
+ case SCI_LINECOPY:
+ case SCI_LINECUT:
+ case SCI_LINEDELETE:
+ case SCI_LINETRANSPOSE:
+ case SCI_LINEDUPLICATE:
+ case SCI_LOWERCASE:
+ case SCI_UPPERCASE:
+ case SCI_LINESCROLLDOWN:
+ case SCI_LINESCROLLUP:
+ case SCI_WORDPARTLEFT:
+ case SCI_WORDPARTLEFTEXTEND:
+ case SCI_WORDPARTRIGHT:
+ case SCI_WORDPARTRIGHTEXTEND:
+ case SCI_DELETEBACKNOTLINE:
+ case SCI_HOMEDISPLAY:
+ case SCI_HOMEDISPLAYEXTEND:
+ case SCI_LINEENDDISPLAY:
+ case SCI_LINEENDDISPLAYEXTEND:
+ case SCI_LINEDOWNRECTEXTEND:
+ case SCI_LINEUPRECTEXTEND:
+ case SCI_CHARLEFTRECTEXTEND:
+ case SCI_CHARRIGHTRECTEXTEND:
+ case SCI_HOMERECTEXTEND:
+ case SCI_VCHOMERECTEXTEND:
+ case SCI_LINEENDRECTEXTEND:
+ case SCI_PAGEUPRECTEXTEND:
+ case SCI_PAGEDOWNRECTEXTEND:
+ case SCI_SELECTIONDUPLICATE:
+ return KeyCommand(iMessage);
+
+ case SCI_BRACEHIGHLIGHT:
+ SetBraceHighlight(static_cast<int>(wParam), lParam, STYLE_BRACELIGHT);
+ break;
+
+ case SCI_BRACEHIGHLIGHTINDICATOR:
+ if (lParam >= 0 && lParam <= INDIC_MAX) {
+ vs.braceHighlightIndicatorSet = wParam != 0;
+ vs.braceHighlightIndicator = lParam;
+ }
+ break;
+
+ case SCI_BRACEBADLIGHT:
+ SetBraceHighlight(static_cast<int>(wParam), -1, STYLE_BRACEBAD);
+ break;
+
+ case SCI_BRACEBADLIGHTINDICATOR:
+ if (lParam >= 0 && lParam <= INDIC_MAX) {
+ vs.braceBadLightIndicatorSet = wParam != 0;
+ vs.braceBadLightIndicator = lParam;
+ }
+ break;
+
+ case SCI_BRACEMATCH:
+ // wParam is position of char to find brace for,
+ // lParam is maximum amount of text to restyle to find it
+ return pdoc->BraceMatch(wParam, lParam);
+
+ case SCI_GETVIEWEOL:
+ return vs.viewEOL;
+
+ case SCI_SETVIEWEOL:
+ vs.viewEOL = wParam != 0;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_SETZOOM:
+ vs.zoomLevel = wParam;
+ InvalidateStyleRedraw();
+ NotifyZoom();
+ break;
+
+ case SCI_GETZOOM:
+ return vs.zoomLevel;
+
+ case SCI_GETEDGECOLUMN:
+ return vs.theEdge;
+
+ case SCI_SETEDGECOLUMN:
+ vs.theEdge = wParam;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETEDGEMODE:
+ return vs.edgeState;
+
+ case SCI_SETEDGEMODE:
+ vs.edgeState = wParam;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETEDGECOLOUR:
+ return vs.edgecolour.AsLong();
+
+ case SCI_SETEDGECOLOUR:
+ vs.edgecolour = ColourDesired(wParam);
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETDOCPOINTER:
+ return reinterpret_cast<sptr_t>(pdoc);
+
+ case SCI_SETDOCPOINTER:
+ CancelModes();
+ SetDocPointer(reinterpret_cast<Document *>(lParam));
+ return 0;
+
+ case SCI_CREATEDOCUMENT: {
+ Document *doc = new Document();
+ doc->AddRef();
+ return reinterpret_cast<sptr_t>(doc);
+ }
+
+ case SCI_ADDREFDOCUMENT:
+ (reinterpret_cast<Document *>(lParam))->AddRef();
+ break;
+
+ case SCI_RELEASEDOCUMENT:
+ (reinterpret_cast<Document *>(lParam))->Release();
+ break;
+
+ case SCI_CREATELOADER: {
+ Document *doc = new Document();
+ doc->AddRef();
+ doc->Allocate(wParam);
+ doc->SetUndoCollection(false);
+ return reinterpret_cast<sptr_t>(static_cast<ILoader *>(doc));
+ }
+
+ case SCI_SETMODEVENTMASK:
+ modEventMask = wParam;
+ return 0;
+
+ case SCI_GETMODEVENTMASK:
+ return modEventMask;
+
+ case SCI_CONVERTEOLS:
+ pdoc->ConvertLineEnds(wParam);
+ SetSelection(sel.MainCaret(), sel.MainAnchor()); // Ensure selection inside document
+ return 0;
+
+ case SCI_SETLENGTHFORENCODE:
+ lengthForEncode = wParam;
+ return 0;
+
+ case SCI_SELECTIONISRECTANGLE:
+ return sel.selType == Selection::selRectangle ? 1 : 0;
+
+ case SCI_SETSELECTIONMODE: {
+ switch (wParam) {
+ case SC_SEL_STREAM:
+ sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::selStream));
+ sel.selType = Selection::selStream;
+ break;
+ case SC_SEL_RECTANGLE:
+ sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::selRectangle));
+ sel.selType = Selection::selRectangle;
+ break;
+ case SC_SEL_LINES:
+ sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::selLines));
+ sel.selType = Selection::selLines;
+ break;
+ case SC_SEL_THIN:
+ sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::selThin));
+ sel.selType = Selection::selThin;
+ break;
+ default:
+ sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::selStream));
+ sel.selType = Selection::selStream;
+ }
+ InvalidateSelection(sel.RangeMain(), true);
+ break;
+ }
+ case SCI_GETSELECTIONMODE:
+ switch (sel.selType) {
+ case Selection::selStream:
+ return SC_SEL_STREAM;
+ case Selection::selRectangle:
+ return SC_SEL_RECTANGLE;
+ case Selection::selLines:
+ return SC_SEL_LINES;
+ case Selection::selThin:
+ return SC_SEL_THIN;
+ default: // ?!
+ return SC_SEL_STREAM;
+ }
+ case SCI_GETLINESELSTARTPOSITION:
+ case SCI_GETLINESELENDPOSITION: {
+ SelectionSegment segmentLine(SelectionPosition(pdoc->LineStart(wParam)),
+ SelectionPosition(pdoc->LineEnd(wParam)));
+ for (size_t r=0; r<sel.Count(); r++) {
+ SelectionSegment portion = sel.Range(r).Intersect(segmentLine);
+ if (portion.start.IsValid()) {
+ return (iMessage == SCI_GETLINESELSTARTPOSITION) ? portion.start.Position() : portion.end.Position();
+ }
+ }
+ return INVALID_POSITION;
+ }
+
+ case SCI_SETOVERTYPE:
+ inOverstrike = wParam != 0;
+ break;
+
+ case SCI_GETOVERTYPE:
+ return inOverstrike ? 1 : 0;
+
+ case SCI_SETFOCUS:
+ SetFocusState(wParam != 0);
+ break;
+
+ case SCI_GETFOCUS:
+ return hasFocus;
+
+ case SCI_SETSTATUS:
+ errorStatus = wParam;
+ break;
+
+ case SCI_GETSTATUS:
+ return errorStatus;
+
+ case SCI_SETMOUSEDOWNCAPTURES:
+ mouseDownCaptures = wParam != 0;
+ break;
+
+ case SCI_GETMOUSEDOWNCAPTURES:
+ return mouseDownCaptures;
+
+ case SCI_SETCURSOR:
+ cursorMode = wParam;
+ DisplayCursor(Window::cursorText);
+ break;
+
+ case SCI_GETCURSOR:
+ return cursorMode;
+
+ case SCI_SETCONTROLCHARSYMBOL:
+ vs.controlCharSymbol = wParam;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETCONTROLCHARSYMBOL:
+ return vs.controlCharSymbol;
+
+ case SCI_SETREPRESENTATION:
+ reprs.SetRepresentation(reinterpret_cast<const char *>(wParam), CharPtrFromSPtr(lParam));
+ break;
+
+ case SCI_GETREPRESENTATION: {
+ Representation *repr = reprs.RepresentationFromCharacter(
+ reinterpret_cast<const char *>(wParam), UTF8MaxBytes);
+ if (repr) {
+ if (lParam != 0)
+ strcpy(CharPtrFromSPtr(lParam), repr->stringRep.c_str());
+ return repr->stringRep.size();
+ }
+ return 0;
+ }
+
+ case SCI_CLEARREPRESENTATION:
+ reprs.ClearRepresentation(reinterpret_cast<const char *>(wParam));
+ break;
+
+ case SCI_STARTRECORD:
+ recordingMacro = true;
+ return 0;
+
+ case SCI_STOPRECORD:
+ recordingMacro = false;
+ return 0;
+
+ case SCI_MOVECARETINSIDEVIEW:
+ MoveCaretInsideView();
+ break;
+
+ case SCI_SETFOLDMARGINCOLOUR:
+ vs.foldmarginColour = ColourOptional(wParam, lParam);
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_SETFOLDMARGINHICOLOUR:
+ vs.foldmarginHighlightColour = ColourOptional(wParam, lParam);
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_SETHOTSPOTACTIVEFORE:
+ vs.hotspotColours.fore = ColourOptional(wParam, lParam);
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETHOTSPOTACTIVEFORE:
+ return vs.hotspotColours.fore.AsLong();
+
+ case SCI_SETHOTSPOTACTIVEBACK:
+ vs.hotspotColours.back = ColourOptional(wParam, lParam);
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETHOTSPOTACTIVEBACK:
+ return vs.hotspotColours.back.AsLong();
+
+ case SCI_SETHOTSPOTACTIVEUNDERLINE:
+ vs.hotspotUnderline = wParam != 0;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETHOTSPOTACTIVEUNDERLINE:
+ return vs.hotspotUnderline ? 1 : 0;
+
+ case SCI_SETHOTSPOTSINGLELINE:
+ vs.hotspotSingleLine = wParam != 0;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETHOTSPOTSINGLELINE:
+ return vs.hotspotSingleLine ? 1 : 0;
+
+ case SCI_SETPASTECONVERTENDINGS:
+ convertPastes = wParam != 0;
+ break;
+
+ case SCI_GETPASTECONVERTENDINGS:
+ return convertPastes ? 1 : 0;
+
+ case SCI_GETCHARACTERPOINTER:
+ return reinterpret_cast<sptr_t>(pdoc->BufferPointer());
+
+ case SCI_GETRANGEPOINTER:
+ return reinterpret_cast<sptr_t>(pdoc->RangePointer(wParam, lParam));
+
+ case SCI_GETGAPPOSITION:
+ return pdoc->GapPosition();
+
+ case SCI_SETEXTRAASCENT:
+ vs.extraAscent = wParam;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETEXTRAASCENT:
+ return vs.extraAscent;
+
+ case SCI_SETEXTRADESCENT:
+ vs.extraDescent = wParam;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETEXTRADESCENT:
+ return vs.extraDescent;
+
+ case SCI_MARGINSETSTYLEOFFSET:
+ vs.marginStyleOffset = wParam;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_MARGINGETSTYLEOFFSET:
+ return vs.marginStyleOffset;
+
+ case SCI_SETMARGINOPTIONS:
+ marginOptions = wParam;
+ break;
+
+ case SCI_GETMARGINOPTIONS:
+ return marginOptions;
+
+ case SCI_MARGINSETTEXT:
+ pdoc->MarginSetText(wParam, CharPtrFromSPtr(lParam));
+ break;
+
+ case SCI_MARGINGETTEXT: {
+ const StyledText st = pdoc->MarginStyledText(wParam);
+ if (lParam) {
+ if (st.text)
+ memcpy(CharPtrFromSPtr(lParam), st.text, st.length);
+ else
+ strcpy(CharPtrFromSPtr(lParam), "");
+ }
+ return st.length;
+ }
+
+ case SCI_MARGINSETSTYLE:
+ pdoc->MarginSetStyle(wParam, lParam);
+ break;
+
+ case SCI_MARGINGETSTYLE: {
+ const StyledText st = pdoc->MarginStyledText(wParam);
+ return st.style;
+ }
+
+ case SCI_MARGINSETSTYLES:
+ pdoc->MarginSetStyles(wParam, reinterpret_cast<const unsigned char *>(lParam));
+ break;
+
+ case SCI_MARGINGETSTYLES: {
+ const StyledText st = pdoc->MarginStyledText(wParam);
+ if (lParam) {
+ if (st.styles)
+ memcpy(CharPtrFromSPtr(lParam), st.styles, st.length);
+ else
+ strcpy(CharPtrFromSPtr(lParam), "");
+ }
+ return st.styles ? st.length : 0;
+ }
+
+ case SCI_MARGINTEXTCLEARALL:
+ pdoc->MarginClearAll();
+ break;
+
+ case SCI_ANNOTATIONSETTEXT:
+ pdoc->AnnotationSetText(wParam, CharPtrFromSPtr(lParam));
+ break;
+
+ case SCI_ANNOTATIONGETTEXT: {
+ const StyledText st = pdoc->AnnotationStyledText(wParam);
+ if (lParam) {
+ if (st.text)
+ memcpy(CharPtrFromSPtr(lParam), st.text, st.length);
+ else
+ strcpy(CharPtrFromSPtr(lParam), "");
+ }
+ return st.length;
+ }
+
+ case SCI_ANNOTATIONGETSTYLE: {
+ const StyledText st = pdoc->AnnotationStyledText(wParam);
+ return st.style;
+ }
+
+ case SCI_ANNOTATIONSETSTYLE:
+ pdoc->AnnotationSetStyle(wParam, lParam);
+ break;
+
+ case SCI_ANNOTATIONSETSTYLES:
+ pdoc->AnnotationSetStyles(wParam, reinterpret_cast<const unsigned char *>(lParam));
+ break;
+
+ case SCI_ANNOTATIONGETSTYLES: {
+ const StyledText st = pdoc->AnnotationStyledText(wParam);
+ if (lParam) {
+ if (st.styles)
+ memcpy(CharPtrFromSPtr(lParam), st.styles, st.length);
+ else
+ strcpy(CharPtrFromSPtr(lParam), "");
+ }
+ return st.styles ? st.length : 0;
+ }
+
+ case SCI_ANNOTATIONGETLINES:
+ return pdoc->AnnotationLines(wParam);
+
+ case SCI_ANNOTATIONCLEARALL:
+ pdoc->AnnotationClearAll();
+ break;
+
+ case SCI_ANNOTATIONSETVISIBLE:
+ SetAnnotationVisible(wParam);
+ break;
+
+ case SCI_ANNOTATIONGETVISIBLE:
+ return vs.annotationVisible;
+
+ case SCI_ANNOTATIONSETSTYLEOFFSET:
+ vs.annotationStyleOffset = wParam;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_ANNOTATIONGETSTYLEOFFSET:
+ return vs.annotationStyleOffset;
+
+ case SCI_RELEASEALLEXTENDEDSTYLES:
+ vs.ReleaseAllExtendedStyles();
+ break;
+
+ case SCI_ALLOCATEEXTENDEDSTYLES:
+ return vs.AllocateExtendedStyles(wParam);
+
+ case SCI_ADDUNDOACTION:
+ pdoc->AddUndoAction(wParam, lParam & UNDO_MAY_COALESCE);
+ break;
+
+ case SCI_SETMOUSESELECTIONRECTANGULARSWITCH:
+ mouseSelectionRectangularSwitch = wParam != 0;
+ break;
+
+ case SCI_GETMOUSESELECTIONRECTANGULARSWITCH:
+ return mouseSelectionRectangularSwitch;
+
+ case SCI_SETMULTIPLESELECTION:
+ multipleSelection = wParam != 0;
+ InvalidateCaret();
+ break;
+
+ case SCI_GETMULTIPLESELECTION:
+ return multipleSelection;
+
+ case SCI_SETADDITIONALSELECTIONTYPING:
+ additionalSelectionTyping = wParam != 0;
+ InvalidateCaret();
+ break;
+
+ case SCI_GETADDITIONALSELECTIONTYPING:
+ return additionalSelectionTyping;
+
+ case SCI_SETMULTIPASTE:
+ multiPasteMode = wParam;
+ break;
+
+ case SCI_GETMULTIPASTE:
+ return multiPasteMode;
+
+ case SCI_SETADDITIONALCARETSBLINK:
+ additionalCaretsBlink = wParam != 0;
+ InvalidateCaret();
+ break;
+
+ case SCI_GETADDITIONALCARETSBLINK:
+ return additionalCaretsBlink;
+
+ case SCI_SETADDITIONALCARETSVISIBLE:
+ additionalCaretsVisible = wParam != 0;
+ InvalidateCaret();
+ break;
+
+ case SCI_GETADDITIONALCARETSVISIBLE:
+ return additionalCaretsVisible;
+
+ case SCI_GETSELECTIONS:
+ return sel.Count();
+
+ case SCI_GETSELECTIONEMPTY:
+ return sel.Empty();
+
+ case SCI_CLEARSELECTIONS:
+ sel.Clear();
+ Redraw();
+ break;
+
+ case SCI_SETSELECTION:
+ sel.SetSelection(SelectionRange(wParam, lParam));
+ Redraw();
+ break;
+
+ case SCI_ADDSELECTION:
+ sel.AddSelection(SelectionRange(wParam, lParam));
+ Redraw();
+ break;
+
+ case SCI_SETMAINSELECTION:
+ sel.SetMain(wParam);
+ Redraw();
+ break;
+
+ case SCI_GETMAINSELECTION:
+ return sel.Main();
+
+ case SCI_SETSELECTIONNCARET:
+ sel.Range(wParam).caret.SetPosition(lParam);
+ Redraw();
+ break;
+
+ case SCI_GETSELECTIONNCARET:
+ return sel.Range(wParam).caret.Position();
+
+ case SCI_SETSELECTIONNANCHOR:
+ sel.Range(wParam).anchor.SetPosition(lParam);
+ Redraw();
+ break;
+ case SCI_GETSELECTIONNANCHOR:
+ return sel.Range(wParam).anchor.Position();
+
+ case SCI_SETSELECTIONNCARETVIRTUALSPACE:
+ sel.Range(wParam).caret.SetVirtualSpace(lParam);
+ Redraw();
+ break;
+
+ case SCI_GETSELECTIONNCARETVIRTUALSPACE:
+ return sel.Range(wParam).caret.VirtualSpace();
+
+ case SCI_SETSELECTIONNANCHORVIRTUALSPACE:
+ sel.Range(wParam).anchor.SetVirtualSpace(lParam);
+ Redraw();
+ break;
+
+ case SCI_GETSELECTIONNANCHORVIRTUALSPACE:
+ return sel.Range(wParam).anchor.VirtualSpace();
+
+ case SCI_SETSELECTIONNSTART:
+ sel.Range(wParam).anchor.SetPosition(lParam);
+ Redraw();
+ break;
+
+ case SCI_GETSELECTIONNSTART:
+ return sel.Range(wParam).Start().Position();
+
+ case SCI_SETSELECTIONNEND:
+ sel.Range(wParam).caret.SetPosition(lParam);
+ Redraw();
+ break;
+
+ case SCI_GETSELECTIONNEND:
+ return sel.Range(wParam).End().Position();
+
+ case SCI_SETRECTANGULARSELECTIONCARET:
+ if (!sel.IsRectangular())
+ sel.Clear();
+ sel.selType = Selection::selRectangle;
+ sel.Rectangular().caret.SetPosition(wParam);
+ SetRectangularRange();
+ Redraw();
+ break;
+
+ case SCI_GETRECTANGULARSELECTIONCARET:
+ return sel.Rectangular().caret.Position();
+
+ case SCI_SETRECTANGULARSELECTIONANCHOR:
+ if (!sel.IsRectangular())
+ sel.Clear();
+ sel.selType = Selection::selRectangle;
+ sel.Rectangular().anchor.SetPosition(wParam);
+ SetRectangularRange();
+ Redraw();
+ break;
+
+ case SCI_GETRECTANGULARSELECTIONANCHOR:
+ return sel.Rectangular().anchor.Position();
+
+ case SCI_SETRECTANGULARSELECTIONCARETVIRTUALSPACE:
+ if (!sel.IsRectangular())
+ sel.Clear();
+ sel.selType = Selection::selRectangle;
+ sel.Rectangular().caret.SetVirtualSpace(wParam);
+ SetRectangularRange();
+ Redraw();
+ break;
+
+ case SCI_GETRECTANGULARSELECTIONCARETVIRTUALSPACE:
+ return sel.Rectangular().caret.VirtualSpace();
+
+ case SCI_SETRECTANGULARSELECTIONANCHORVIRTUALSPACE:
+ if (!sel.IsRectangular())
+ sel.Clear();
+ sel.selType = Selection::selRectangle;
+ sel.Rectangular().anchor.SetVirtualSpace(wParam);
+ SetRectangularRange();
+ Redraw();
+ break;
+
+ case SCI_GETRECTANGULARSELECTIONANCHORVIRTUALSPACE:
+ return sel.Rectangular().anchor.VirtualSpace();
+
+ case SCI_SETVIRTUALSPACEOPTIONS:
+ virtualSpaceOptions = wParam;
+ break;
+
+ case SCI_GETVIRTUALSPACEOPTIONS:
+ return virtualSpaceOptions;
+
+ case SCI_SETADDITIONALSELFORE:
+ vs.selAdditionalForeground = ColourDesired(wParam);
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_SETADDITIONALSELBACK:
+ vs.selAdditionalBackground = ColourDesired(wParam);
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_SETADDITIONALSELALPHA:
+ vs.selAdditionalAlpha = wParam;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETADDITIONALSELALPHA:
+ return vs.selAdditionalAlpha;
+
+ case SCI_SETADDITIONALCARETFORE:
+ vs.additionalCaretColour = ColourDesired(wParam);
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETADDITIONALCARETFORE:
+ return vs.additionalCaretColour.AsLong();
+
+ case SCI_ROTATESELECTION:
+ sel.RotateMain();
+ InvalidateSelection(sel.RangeMain(), true);
+ break;
+
+ case SCI_SWAPMAINANCHORCARET:
+ InvalidateSelection(sel.RangeMain());
+ sel.RangeMain() = SelectionRange(sel.RangeMain().anchor, sel.RangeMain().caret);
+ break;
+
+ case SCI_CHANGELEXERSTATE:
+ pdoc->ChangeLexerState(wParam, lParam);
+ break;
+
+ case SCI_SETIDENTIFIER:
+ SetCtrlID(wParam);
+ break;
+
+ case SCI_GETIDENTIFIER:
+ return GetCtrlID();
+
+ case SCI_SETTECHNOLOGY:
+ // No action by default
+ break;
+
+ case SCI_GETTECHNOLOGY:
+ return technology;
+
+ case SCI_COUNTCHARACTERS:
+ return pdoc->CountCharacters(wParam, lParam);
+
+ default:
+ return DefWndProc(iMessage, wParam, lParam);
+ }
+ //Platform::DebugPrintf("end wnd proc\n");
+ return 0l;
+}
diff --git a/3rdparty/bgfx/3rdparty/stb/stb_image.c b/3rdparty/bgfx/3rdparty/stb/stb_image.c
index e9b2a1d0dbb..bc305501477 100644
--- a/3rdparty/bgfx/3rdparty/stb/stb_image.c
+++ b/3rdparty/bgfx/3rdparty/stb/stb_image.c
@@ -1,3 +1,11 @@
+#ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wshadow"
+#elif defined(_MSC_VER)
+# pragma warning(disable:4312) // warning C4312: 'type cast': conversion from '' to '' of greater size
+# pragma warning(disable:4456) // warning C4456: declaration of 'k' hides previous local declaration
+# pragma warning(disable:4457) // warning C4457: declaration of 'y' hides function parameter
+#endif
+
/* stb_image - v2.06 - public domain image loader - http://nothings.org/stb_image.h
no warranty implied; use at your own risk
diff --git a/3rdparty/bgfx/3rdparty/stb/stb_truetype.h b/3rdparty/bgfx/3rdparty/stb/stb_truetype.h
index d71eac7b745..98f1319e844 100644
--- a/3rdparty/bgfx/3rdparty/stb/stb_truetype.h
+++ b/3rdparty/bgfx/3rdparty/stb/stb_truetype.h
@@ -1,5 +1,7 @@
#ifdef __GNUC__
# pragma GCC diagnostic ignored "-Wshadow"
+#elif defined(_MSC_VER)
+# pragma warning(disable:4456) // warning C4456: declaration of 'k' hides previous local declaration
#endif
// stb_truetype.h - v1.07 - public domain
diff --git a/3rdparty/bgfx/README.md b/3rdparty/bgfx/README.md
index 3ac227c147c..3b412508723 100644
--- a/3rdparty/bgfx/README.md
+++ b/3rdparty/bgfx/README.md
@@ -28,10 +28,11 @@ Supported platforms:
* Android (14+, ARM, x86, MIPS)
* asm.js/Emscripten (1.25.0)
* FreeBSD
- * iOS
+ * iOS (iPhone, iPad, AppleTV)
* Linux ![](https://tc27.draster.com/app/rest/builds/buildType:(id:Bgfx_Linux)/statusIcon)
+ * MIPS Creator CI20
* Native Client (PPAPI 37+, ARM, x86, x64, PNaCl)
- * OSX (10.9)
+ * OSX (10.9+)
* RaspberryPi
* Windows (XP, Vista, 7, 8, 10) ![](https://tc27.draster.com/app/rest/builds/buildType:(id:Bgfx_Windows)/statusIcon)
* WinRT (WinPhone 8.0+)
diff --git a/3rdparty/bgfx/examples/00-helloworld/helloworld.cpp b/3rdparty/bgfx/examples/00-helloworld/helloworld.cpp
index 03d64e0bb0f..b1f762ea76f 100644
--- a/3rdparty/bgfx/examples/00-helloworld/helloworld.cpp
+++ b/3rdparty/bgfx/examples/00-helloworld/helloworld.cpp
@@ -4,7 +4,7 @@
*/
#include "common.h"
-#include <bgfx.h>
+#include <bgfx/bgfx.h>
#include <bx/uint32_t.h>
#include "logo.h"
diff --git a/3rdparty/bgfx/examples/02-metaballs/metaballs.cpp b/3rdparty/bgfx/examples/02-metaballs/metaballs.cpp
index b7dc4654d92..6593f3d33c1 100644
--- a/3rdparty/bgfx/examples/02-metaballs/metaballs.cpp
+++ b/3rdparty/bgfx/examples/02-metaballs/metaballs.cpp
@@ -4,7 +4,7 @@
*/
#include "common.h"
-#include <bgfx.h>
+#include <bgfx/bgfx.h>
// embedded shaders
#include "vs_metaballs.bin.h"
@@ -504,6 +504,11 @@ class Metaballs : public entry::AppI
fs_metaballs = bgfx::makeRef(fs_metaballs_dx11, sizeof(fs_metaballs_dx11) );
break;
+ case bgfx::RendererType::Metal:
+ vs_metaballs = bgfx::makeRef(vs_metaballs_mtl, sizeof(vs_metaballs_mtl) );
+ fs_metaballs = bgfx::makeRef(fs_metaballs_mtl, sizeof(fs_metaballs_mtl) );
+ break;
+
default:
vs_metaballs = bgfx::makeRef(vs_metaballs_glsl, sizeof(vs_metaballs_glsl) );
fs_metaballs = bgfx::makeRef(fs_metaballs_glsl, sizeof(fs_metaballs_glsl) );
diff --git a/3rdparty/bgfx/examples/08-update/update.cpp b/3rdparty/bgfx/examples/08-update/update.cpp
index 8ac79e8d268..51bd8c0213d 100644
--- a/3rdparty/bgfx/examples/08-update/update.cpp
+++ b/3rdparty/bgfx/examples/08-update/update.cpp
@@ -141,7 +141,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
loadTexture("texture_compression_bc1.dds", BGFX_TEXTURE_U_CLAMP|BGFX_TEXTURE_V_CLAMP),
loadTexture("texture_compression_bc2.dds", BGFX_TEXTURE_U_CLAMP),
loadTexture("texture_compression_bc3.dds", BGFX_TEXTURE_V_CLAMP),
- loadTexture("texture_compression_etc1.ktx", BGFX_TEXTURE_U_BORDER|BGFX_TEXTURE_V_BORDER),
+ loadTexture("texture_compression_etc1.ktx", BGFX_TEXTURE_U_BORDER|BGFX_TEXTURE_V_BORDER|BGFX_TEXTURE_BORDER_COLOR(1) ),
loadTexture("texture_compression_etc2.ktx"),
loadTexture("texture_compression_ptc12.pvr"),
loadTexture("texture_compression_ptc14.pvr"),
@@ -197,20 +197,22 @@ int _main_(int /*_argc*/, char** /*_argv*/)
// Create static index buffer.
bgfx::IndexBufferHandle ibh = bgfx::createIndexBuffer(bgfx::makeRef(s_cubeIndices, sizeof(s_cubeIndices) ) );
+ // Create programs.
+ bgfx::ProgramHandle program = loadProgram("vs_update", "fs_update");
+ bgfx::ProgramHandle programCmp = loadProgram("vs_update", "fs_update_cmp");
+ bgfx::ProgramHandle program3d = BGFX_INVALID_HANDLE;
+ if (texture3DSupported)
+ {
+ program3d = loadProgram("vs_update", "fs_update_3d");
+ }
+
// Create texture sampler uniforms.
bgfx::UniformHandle s_texCube = bgfx::createUniform("s_texCube", bgfx::UniformType::Int1);
bgfx::UniformHandle s_texColor = bgfx::createUniform("s_texColor", bgfx::UniformType::Int1);
+ // Create time uniform.
bgfx::UniformHandle u_time = bgfx::createUniform("u_time", bgfx::UniformType::Vec4);
- bgfx::ProgramHandle program = loadProgram("vs_update", "fs_update");
- bgfx::ProgramHandle programCmp = loadProgram("vs_update", "fs_update_cmp");
- bgfx::ProgramHandle program3d = BGFX_INVALID_HANDLE;
- if (texture3DSupported)
- {
- program3d = loadProgram("vs_update", "fs_update_3d");
- }
-
const uint32_t textureSide = 2048;
bgfx::TextureHandle textureCube = bgfx::createTextureCube(textureSide, 1
@@ -243,6 +245,9 @@ int _main_(int /*_argc*/, char** /*_argv*/)
while (!entry::processEvents(width, height, debug, reset) )
{
+ float borderColor[4] = { float(rand()%255)/255.0f, float(rand()%255)/255.0f, float(rand()%255)/255.0f, float(rand()%255)/255.0f };
+ bgfx::setPaletteColor(1, borderColor);
+
// Set view 0 and 1 viewport.
bgfx::setViewRect(0, 0, 0, width, height);
bgfx::setViewRect(1, 0, 0, width, height);
diff --git a/3rdparty/bgfx/examples/10-font/font.cpp b/3rdparty/bgfx/examples/10-font/font.cpp
index 7b81663539f..660ff2998af 100644
--- a/3rdparty/bgfx/examples/10-font/font.cpp
+++ b/3rdparty/bgfx/examples/10-font/font.cpp
@@ -5,7 +5,7 @@
#include "common.h"
-#include <bgfx.h>
+#include <bgfx/bgfx.h>
#include <bx/timer.h>
#include <bx/string.h>
#include <bx/fpumath.h>
diff --git a/3rdparty/bgfx/examples/11-fontsdf/fontsdf.cpp b/3rdparty/bgfx/examples/11-fontsdf/fontsdf.cpp
index f74c3885867..d54d4756cd8 100644
--- a/3rdparty/bgfx/examples/11-fontsdf/fontsdf.cpp
+++ b/3rdparty/bgfx/examples/11-fontsdf/fontsdf.cpp
@@ -6,7 +6,7 @@
#include "common.h"
#include "bgfx_utils.h"
-#include <bgfx.h>
+#include <bgfx/bgfx.h>
#include <bx/timer.h>
#include <bx/fpumath.h>
diff --git a/3rdparty/bgfx/examples/13-stencil/stencil.cpp b/3rdparty/bgfx/examples/13-stencil/stencil.cpp
index 2551306e7a1..7a1e90d2834 100644
--- a/3rdparty/bgfx/examples/13-stencil/stencil.cpp
+++ b/3rdparty/bgfx/examples/13-stencil/stencil.cpp
@@ -9,7 +9,7 @@
#include "common.h"
#include "bgfx_utils.h"
-#include <bgfx.h>
+#include <bgfx/bgfx.h>
#include <bx/timer.h>
#include <bx/readerwriter.h>
#include <bx/fpumath.h>
diff --git a/3rdparty/bgfx/examples/14-shadowvolumes/shadowvolumes.cpp b/3rdparty/bgfx/examples/14-shadowvolumes/shadowvolumes.cpp
index 1ab279cc561..17a19ab566c 100644
--- a/3rdparty/bgfx/examples/14-shadowvolumes/shadowvolumes.cpp
+++ b/3rdparty/bgfx/examples/14-shadowvolumes/shadowvolumes.cpp
@@ -19,7 +19,7 @@ using namespace std::tr1;
#include "common.h"
#include "bgfx_utils.h"
-#include <bgfx.h>
+#include <bgfx/bgfx.h>
#include <bx/timer.h>
#include <bx/readerwriter.h>
#include <bx/allocator.h>
diff --git a/3rdparty/bgfx/examples/15-shadowmaps-simple/shadowmaps_simple.cpp b/3rdparty/bgfx/examples/15-shadowmaps-simple/shadowmaps_simple.cpp
index c361c860115..513a37f2579 100644
--- a/3rdparty/bgfx/examples/15-shadowmaps-simple/shadowmaps_simple.cpp
+++ b/3rdparty/bgfx/examples/15-shadowmaps-simple/shadowmaps_simple.cpp
@@ -9,7 +9,7 @@
#include "common.h"
-#include <bgfx.h>
+#include <bgfx/bgfx.h>
#include <bx/timer.h>
#include <bx/readerwriter.h>
#include <bx/fpumath.h>
@@ -311,7 +311,6 @@ int _main_(int /*_argc*/, char** /*_argv*/)
// Floor.
bx::mtxMul(lightMtx, mtxFloor, mtxShadow);
- bgfx::setUniform(u_lightMtx, lightMtx);
uint32_t cached = bgfx::setTransform(mtxFloor);
for (uint32_t pass = 0; pass < 2; ++pass)
{
diff --git a/3rdparty/bgfx/examples/16-shadowmaps/shadowmaps.cpp b/3rdparty/bgfx/examples/16-shadowmaps/shadowmaps.cpp
index ad0dbc26d36..34ce52c36d2 100644
--- a/3rdparty/bgfx/examples/16-shadowmaps/shadowmaps.cpp
+++ b/3rdparty/bgfx/examples/16-shadowmaps/shadowmaps.cpp
@@ -10,7 +10,7 @@
#include "common.h"
#include "bgfx_utils.h"
-#include <bgfx.h>
+#include <bgfx/bgfx.h>
#include <bx/timer.h>
#include <bx/readerwriter.h>
#include <bx/fpumath.h>
diff --git a/3rdparty/bgfx/examples/17-drawstress/drawstress.cpp b/3rdparty/bgfx/examples/17-drawstress/drawstress.cpp
index de08f68b39f..1f40768b370 100644
--- a/3rdparty/bgfx/examples/17-drawstress/drawstress.cpp
+++ b/3rdparty/bgfx/examples/17-drawstress/drawstress.cpp
@@ -3,7 +3,7 @@
* License: http://www.opensource.org/licenses/BSD-2-Clause
*/
-#include <bgfx.h>
+#include <bgfx/bgfx.h>
#include <bx/uint32_t.h>
#include "common.h"
@@ -127,6 +127,11 @@ class DrawStress : public entry::AppI
fs_drawstress = bgfx::makeRef(fs_drawstress_dx11, sizeof(fs_drawstress_dx11) );
break;
+ case bgfx::RendererType::Metal:
+ vs_drawstress = bgfx::makeRef(vs_drawstress_mtl, sizeof(vs_drawstress_mtl) );
+ fs_drawstress = bgfx::makeRef(fs_drawstress_mtl, sizeof(fs_drawstress_mtl) );
+ break;
+
default:
vs_drawstress = bgfx::makeRef(vs_drawstress_glsl, sizeof(vs_drawstress_glsl) );
fs_drawstress = bgfx::makeRef(fs_drawstress_glsl, sizeof(fs_drawstress_glsl) );
diff --git a/3rdparty/bgfx/examples/19-oit/oit.cpp b/3rdparty/bgfx/examples/19-oit/oit.cpp
index f673a9abeb0..7457364e86e 100644
--- a/3rdparty/bgfx/examples/19-oit/oit.cpp
+++ b/3rdparty/bgfx/examples/19-oit/oit.cpp
@@ -311,11 +311,11 @@ int _main_(int /*_argc*/, char** /*_argv*/)
bgfx::setViewTransform(0, view, proj);
- // Set clear color palette for index 0
- bgfx::setClearColor(0, 0.0f, 0.0f, 0.0f, 0.0f);
+ // Set palette color for index 0
+ bgfx::setPaletteColor(0, 0.0f, 0.0f, 0.0f, 0.0f);
- // Set clear color palette for index 1
- bgfx::setClearColor(1, 1.0f, 1.0f, 1.0f, 1.0f);
+ // Set palette color for index 1
+ bgfx::setPaletteColor(1, 1.0f, 1.0f, 1.0f, 1.0f);
bgfx::setViewClear(0
, BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH
diff --git a/3rdparty/bgfx/examples/20-nanovg/nanovg.cpp b/3rdparty/bgfx/examples/20-nanovg/nanovg.cpp
index c505b8425dc..2f4060a40b8 100644
--- a/3rdparty/bgfx/examples/20-nanovg/nanovg.cpp
+++ b/3rdparty/bgfx/examples/20-nanovg/nanovg.cpp
@@ -26,7 +26,7 @@
#include <stdio.h>
#include <math.h>
-#include <bgfx.h>
+#include <bgfx/bgfx.h>
#include <bx/string.h>
#include <bx/timer.h>
#include "entry/entry.h"
diff --git a/3rdparty/bgfx/examples/21-deferred/deferred.cpp b/3rdparty/bgfx/examples/21-deferred/deferred.cpp
index 7aae64fe64b..019b8920518 100644
--- a/3rdparty/bgfx/examples/21-deferred/deferred.cpp
+++ b/3rdparty/bgfx/examples/21-deferred/deferred.cpp
@@ -18,11 +18,6 @@
static float s_texelHalf = 0.0f;
static bool s_originBottomLeft = false;
-inline void mtxProj(float* _result, float _fovy, float _aspect, float _near, float _far)
-{
- bx::mtxProj(_result, _fovy, _aspect, _near, _far, s_originBottomLeft);
-}
-
struct PosNormalTangentTexcoordVertex
{
float m_x;
@@ -233,11 +228,11 @@ class Deferred : public entry::AppI
// Enable m_debug text.
bgfx::setDebug(m_debug);
- // Set clear color palette for index 0
- bgfx::setClearColor(0, UINT32_C(0x00000000) );
+ // Set palette color for index 0
+ bgfx::setPaletteColor(0, UINT32_C(0x00000000) );
- // Set clear color palette for index 1
- bgfx::setClearColor(1, UINT32_C(0x303030ff) );
+ // Set palette color for index 1
+ bgfx::setPaletteColor(1, UINT32_C(0x303030ff) );
// Set geometry pass view clear state.
bgfx::setViewClear(RENDER_PASS_GEOMETRY_ID
@@ -504,7 +499,7 @@ class Deferred : public entry::AppI
bgfx::setViewFrameBuffer(RENDER_PASS_LIGHT_ID, m_lightBuffer);
float proj[16];
- mtxProj(proj, 60.0f, float(m_width)/float(m_height), 0.1f, 100.0f);
+ bx::mtxProj(proj, 60.0f, float(m_width)/float(m_height), 0.1f, 100.0f, s_originBottomLeft);
bgfx::setViewFrameBuffer(RENDER_PASS_GEOMETRY_ID, m_gbuffer);
bgfx::setViewTransform(RENDER_PASS_GEOMETRY_ID, view, proj);
diff --git a/3rdparty/bgfx/examples/23-vectordisplay/vectordisplay.cpp b/3rdparty/bgfx/examples/23-vectordisplay/vectordisplay.cpp
index 46179aeb4c4..4285502394d 100644
--- a/3rdparty/bgfx/examples/23-vectordisplay/vectordisplay.cpp
+++ b/3rdparty/bgfx/examples/23-vectordisplay/vectordisplay.cpp
@@ -210,8 +210,6 @@ void VectorDisplay::endFrame()
if (m_brightness > 0)
{
- bgfx::setUniform(u_params, params);
-
bgfx::setTexture(0, s_texColor, m_sceneFrameBuffer);
int npasses = (int)(m_brightness * 4);
@@ -264,6 +262,8 @@ void VectorDisplay::endFrame()
}
}
+ bgfx::discard();
+
//now do last pass, combination of blur and normal buffer to screen
bgfx::setViewTransform(viewCounter, NULL, proj);
bgfx::setViewRect(viewCounter, 0, 0, m_screenWidth, m_screenHeight);
diff --git a/3rdparty/bgfx/examples/23-vectordisplay/vectordisplay.h b/3rdparty/bgfx/examples/23-vectordisplay/vectordisplay.h
index 88a71b83a85..0b8c78a8efb 100644
--- a/3rdparty/bgfx/examples/23-vectordisplay/vectordisplay.h
+++ b/3rdparty/bgfx/examples/23-vectordisplay/vectordisplay.h
@@ -12,7 +12,7 @@
#ifndef __VECTORDISPLAY_H__
#define __VECTORDISPLAY_H__
-#include "bgfx.h"
+#include <bgfx/bgfx.h>
#include <tinystl/allocator.h>
#include <tinystl/vector.h>
diff --git a/3rdparty/bgfx/examples/24-nbody/nbody.cpp b/3rdparty/bgfx/examples/24-nbody/nbody.cpp
index da7e7a44d29..854a55a7aea 100644
--- a/3rdparty/bgfx/examples/24-nbody/nbody.cpp
+++ b/3rdparty/bgfx/examples/24-nbody/nbody.cpp
@@ -7,7 +7,7 @@
#include "bgfx_utils.h"
#include "imgui/imgui.h"
#include "camera.h"
-#include <bgfx.h>
+#include <bgfx/bgfx.h>
struct u_paramsDataStruct
{
diff --git a/3rdparty/bgfx/examples/25-c99/helloworld.c b/3rdparty/bgfx/examples/25-c99/helloworld.c
index b2e809c6d7c..a362736b435 100644
--- a/3rdparty/bgfx/examples/25-c99/helloworld.c
+++ b/3rdparty/bgfx/examples/25-c99/helloworld.c
@@ -3,7 +3,7 @@
* License: http://www.opensource.org/licenses/BSD-2-Clause
*/
-#include <bgfx.c99.h>
+#include <bgfx/c99/bgfx.h>
#include "../00-helloworld/logo.h"
extern bool entry_process_events(uint32_t* _width, uint32_t* _height, uint32_t* _debug, uint32_t* _reset);
diff --git a/3rdparty/bgfx/examples/common/bgfx_utils.cpp b/3rdparty/bgfx/examples/common/bgfx_utils.cpp
index ad1ca9fc4cb..386062c065d 100644
--- a/3rdparty/bgfx/examples/common/bgfx_utils.cpp
+++ b/3rdparty/bgfx/examples/common/bgfx_utils.cpp
@@ -12,7 +12,7 @@
#include <tinystl/string.h>
namespace stl = tinystl;
-#include <bgfx.h>
+#include <bgfx/bgfx.h>
#include <bx/readerwriter.h>
#include <bx/fpumath.h>
#include <bx/string.h>
diff --git a/3rdparty/bgfx/examples/common/bgfx_utils.h b/3rdparty/bgfx/examples/common/bgfx_utils.h
index 6b7d1f05da7..2938abff1b9 100644
--- a/3rdparty/bgfx/examples/common/bgfx_utils.h
+++ b/3rdparty/bgfx/examples/common/bgfx_utils.h
@@ -6,7 +6,7 @@
#ifndef BGFX_UTILS_H_HEADER_GUARD
#define BGFX_UTILS_H_HEADER_GUARD
-#include <bgfx.h>
+#include <bgfx/bgfx.h>
void* load(const char* _filePath, uint32_t* _size = NULL);
void unload(void* _ptr);
diff --git a/3rdparty/bgfx/examples/common/cube_atlas.cpp b/3rdparty/bgfx/examples/common/cube_atlas.cpp
index c0303d0baf9..1d762b6544d 100644
--- a/3rdparty/bgfx/examples/common/cube_atlas.cpp
+++ b/3rdparty/bgfx/examples/common/cube_atlas.cpp
@@ -4,7 +4,7 @@
*/
#include "common.h"
-#include <bgfx.h>
+#include <bgfx/bgfx.h>
#include <limits.h> // INT_MAX
#include <memory.h> // memset
diff --git a/3rdparty/bgfx/examples/common/cube_atlas.h b/3rdparty/bgfx/examples/common/cube_atlas.h
index 903221e7aed..5efde04858d 100644
--- a/3rdparty/bgfx/examples/common/cube_atlas.h
+++ b/3rdparty/bgfx/examples/common/cube_atlas.h
@@ -15,7 +15,7 @@
/// algorithm based on C++ sources provided by Jukka Jylänki at:
/// http://clb.demon.fi/files/RectangleBinPack/
-#include <bgfx.h>
+#include <bgfx/bgfx.h>
struct AtlasRegion
{
diff --git a/3rdparty/bgfx/examples/common/entry/entry.cpp b/3rdparty/bgfx/examples/common/entry/entry.cpp
index fa83cce89ba..61dbe0b3c9c 100644
--- a/3rdparty/bgfx/examples/common/entry/entry.cpp
+++ b/3rdparty/bgfx/examples/common/entry/entry.cpp
@@ -3,7 +3,7 @@
* License: http://www.opensource.org/licenses/BSD-2-Clause
*/
-#include <bgfx.h>
+#include <bgfx/bgfx.h>
#include <bx/string.h>
#include <bx/readerwriter.h>
diff --git a/3rdparty/bgfx/examples/common/entry/entry_android.cpp b/3rdparty/bgfx/examples/common/entry/entry_android.cpp
index f16b1e5dac6..aef9fee938a 100644
--- a/3rdparty/bgfx/examples/common/entry/entry_android.cpp
+++ b/3rdparty/bgfx/examples/common/entry/entry_android.cpp
@@ -7,7 +7,7 @@
#if ENTRY_CONFIG_USE_NATIVE && BX_PLATFORM_ANDROID
-#include <bgfxplatform.h>
+#include <bgfx/bgfxplatform.h>
#include <stdio.h>
#include <bx/thread.h>
diff --git a/3rdparty/bgfx/examples/common/entry/entry_glfw.cpp b/3rdparty/bgfx/examples/common/entry/entry_glfw.cpp
index 42a7bc6f047..615d828cea9 100644
--- a/3rdparty/bgfx/examples/common/entry/entry_glfw.cpp
+++ b/3rdparty/bgfx/examples/common/entry/entry_glfw.cpp
@@ -9,7 +9,7 @@
#define GLFW_DLL
#include <GLFW/glfw3.h>
-#include <bgfxplatform.h>
+#include <bgfx/bgfxplatform.h>
#include "dbg.h"
// This is just trivial implementation of GLFW3 integration.
diff --git a/3rdparty/bgfx/examples/common/entry/entry_ios.mm b/3rdparty/bgfx/examples/common/entry/entry_ios.mm
index d2392d898f4..1a10d26f765 100644
--- a/3rdparty/bgfx/examples/common/entry/entry_ios.mm
+++ b/3rdparty/bgfx/examples/common/entry/entry_ios.mm
@@ -17,7 +17,7 @@
//# define HAS_METAL_SDK
#endif
-#include <bgfxplatform.h>
+#include <bgfx/bgfxplatform.h>
#include <bx/uint32_t.h>
#include <bx/thread.h>
diff --git a/3rdparty/bgfx/examples/common/entry/entry_nacl.cpp b/3rdparty/bgfx/examples/common/entry/entry_nacl.cpp
index 8d6fac7baff..bc476290db0 100644
--- a/3rdparty/bgfx/examples/common/entry/entry_nacl.cpp
+++ b/3rdparty/bgfx/examples/common/entry/entry_nacl.cpp
@@ -7,7 +7,7 @@
#if ENTRY_CONFIG_USE_NATIVE && BX_PLATFORM_NACL
-#include <bgfxplatform.h>
+#include <bgfx/bgfxplatform.h>
#include <stdio.h>
#include <string.h>
@@ -29,7 +29,7 @@
#include <ppapi/c/ppp_instance.h>
#include <ppapi/gles2/gl2ext_ppapi.h>
-#include <bgfxplatform.h>
+#include <bgfx/bgfxplatform.h>
#include <bx/thread.h>
#include "entry.h"
diff --git a/3rdparty/bgfx/examples/common/entry/entry_osx.mm b/3rdparty/bgfx/examples/common/entry/entry_osx.mm
index c0cec19d9c7..5b59fe06c84 100644
--- a/3rdparty/bgfx/examples/common/entry/entry_osx.mm
+++ b/3rdparty/bgfx/examples/common/entry/entry_osx.mm
@@ -9,7 +9,7 @@
#import <Cocoa/Cocoa.h>
-#include <bgfxplatform.h>
+#include <bgfx/bgfxplatform.h>
#include <bx/uint32_t.h>
#include <bx/thread.h>
diff --git a/3rdparty/bgfx/examples/common/entry/entry_sdl.cpp b/3rdparty/bgfx/examples/common/entry/entry_sdl.cpp
index b9094e8c3c3..a9faec69e47 100644
--- a/3rdparty/bgfx/examples/common/entry/entry_sdl.cpp
+++ b/3rdparty/bgfx/examples/common/entry/entry_sdl.cpp
@@ -13,7 +13,7 @@
#include <SDL2/SDL.h>
#include <SDL2/SDL_syswm.h>
-#include <bgfxplatform.h>
+#include <bgfx/bgfxplatform.h>
#include <stdio.h>
#include <bx/thread.h>
diff --git a/3rdparty/bgfx/examples/common/entry/entry_windows.cpp b/3rdparty/bgfx/examples/common/entry/entry_windows.cpp
index a6a5ff2c973..c61450c9ab9 100644
--- a/3rdparty/bgfx/examples/common/entry/entry_windows.cpp
+++ b/3rdparty/bgfx/examples/common/entry/entry_windows.cpp
@@ -7,12 +7,13 @@
#if ENTRY_CONFIG_USE_NATIVE && BX_PLATFORM_WINDOWS
-#include <bgfxplatform.h>
+#include <bgfx/bgfxplatform.h>
#include <bx/uint32_t.h>
#include <bx/thread.h>
#include <bx/mutex.h>
#include <bx/handlealloc.h>
+#include <bx/timer.h>
#include <tinystl/allocator.h>
#include <tinystl/string.h>
@@ -116,6 +117,17 @@ namespace entry
void update(EventQueue& _eventQueue)
{
+ int64_t now = bx::getHPCounter();
+ static int64_t next = now;
+
+ if (now < next)
+ {
+ return;
+ }
+
+ const int64_t timerFreq = bx::getHPFrequency();
+ next = now + timerFreq/60;
+
if (NULL == m_xinputdll)
{
return;
@@ -518,7 +530,7 @@ namespace entry
, msg->m_y
, msg->m_width
, msg->m_height
- , m_hwnd[0]
+ , NULL
, NULL
, (HINSTANCE)GetModuleHandle(NULL)
, 0
@@ -902,33 +914,6 @@ namespace entry
top = newrect.top +(newrect.bottom-newrect.top-height)/2;
}
- HWND parent = GetWindow(_hwnd, GW_OWNER);
- if (NULL != parent)
- {
- if (_windowFrame)
- {
- SetWindowPos(parent
- , HWND_TOP
- , -32000
- , -32000
- , 0
- , 0
- , SWP_SHOWWINDOW
- );
- }
- else
- {
- SetWindowPos(parent
- , HWND_TOP
- , newrect.left
- , newrect.top
- , newrect.right-newrect.left
- , newrect.bottom-newrect.top
- , SWP_SHOWWINDOW
- );
- }
- }
-
SetWindowPos(_hwnd
, HWND_TOP
, left
diff --git a/3rdparty/bgfx/examples/common/entry/entry_winrt.cpp b/3rdparty/bgfx/examples/common/entry/entry_winrt.cpp
index 44fb92a4ee0..042c032d609 100644
--- a/3rdparty/bgfx/examples/common/entry/entry_winrt.cpp
+++ b/3rdparty/bgfx/examples/common/entry/entry_winrt.cpp
@@ -7,7 +7,7 @@
#if BX_PLATFORM_WINRT
-#include <bgfxplatform.h>
+#include <bgfx/bgfxplatform.h>
#include <bx/thread.h>
using namespace Windows::ApplicationModel;
diff --git a/3rdparty/bgfx/examples/common/entry/entry_x11.cpp b/3rdparty/bgfx/examples/common/entry/entry_x11.cpp
index e02548841ae..16b7af4ffa1 100644
--- a/3rdparty/bgfx/examples/common/entry/entry_x11.cpp
+++ b/3rdparty/bgfx/examples/common/entry/entry_x11.cpp
@@ -11,7 +11,7 @@
#define XK_LATIN1
#include <X11/keysymdef.h>
#include <X11/Xlib.h> // will include X11 which #defines None... Don't mess with order of includes.
-#include <bgfxplatform.h>
+#include <bgfx/bgfxplatform.h>
#undef None
#include <bx/thread.h>
@@ -299,11 +299,10 @@ namespace entry
m_visual = DefaultVisual(m_display, screen);
m_root = RootWindow(m_display, screen);
- XSetWindowAttributes windowAttrs;
- memset(&windowAttrs, 0, sizeof(windowAttrs) );
- windowAttrs.background_pixmap = 0;
- windowAttrs.border_pixel = 0;
- windowAttrs.event_mask = 0
+ memset(&m_windowAttrs, 0, sizeof(m_windowAttrs) );
+ m_windowAttrs.background_pixmap = 0;
+ m_windowAttrs.border_pixel = 0;
+ m_windowAttrs.event_mask = 0
| ButtonPressMask
| ButtonReleaseMask
| ExposureMask
@@ -322,7 +321,7 @@ namespace entry
, InputOutput
, m_visual
, CWBorderPixel|CWEventMask
- , &windowAttrs
+ , &m_windowAttrs
);
// Clear window to black.
@@ -338,6 +337,20 @@ namespace entry
XMapWindow(m_display, m_window[0]);
XStoreName(m_display, m_window[0], "BGFX");
+ XIM im;
+ im = XOpenIM(m_display, NULL, NULL, NULL);
+
+ XIC ic;
+ ic = XCreateIC(im
+ , XNInputStyle
+ , 0
+ | XIMPreeditNothing
+ | XIMStatusNothing
+ , XNClientWindow
+ , m_window[0]
+ , NULL
+ );
+
//
bgfx::x11SetDisplayWindow(m_display, m_window[0]);
@@ -449,10 +462,30 @@ namespace entry
default:
{
+ WindowHandle handle = findHandle(xkey.window);
+ if (KeyPress == event.type)
+ {
+ Status status = 0;
+ uint8_t utf8[4];
+ int len = Xutf8LookupString(ic, &xkey, (char*)utf8, sizeof(utf8), &keysym, &status);
+ switch (status)
+ {
+ case XLookupChars:
+ case XLookupBoth:
+ if (0 != len)
+ {
+ m_eventQueue.postCharEvent(handle, len, utf8);
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
Key::Enum key = fromXk(keysym);
if (Key::None != key)
{
- WindowHandle handle = findHandle(xkey.window);
m_eventQueue.postKeyEvent(handle, key, m_modifiers, KeyPress == event.type);
}
}
@@ -479,6 +512,9 @@ namespace entry
s_joystick.shutdown();
+ XDestroyIC(ic);
+ XCloseIM(im);
+
XUnmapWindow(m_display, m_window[0]);
XDestroyWindow(m_display, m_window[0]);
@@ -493,21 +529,6 @@ namespace entry
void createWindow(WindowHandle _handle, Msg* msg)
{
- XSetWindowAttributes windowAttrs;
- memset(&windowAttrs, 0, sizeof(windowAttrs) );
- windowAttrs.background_pixmap = 0;
- windowAttrs.border_pixel = 0;
- windowAttrs.event_mask = 0
- | ButtonPressMask
- | ButtonReleaseMask
- | ExposureMask
- | KeyPressMask
- | KeyReleaseMask
- | PointerMotionMask
- | ResizeRedirectMask
- | StructureNotifyMask
- ;
-
Window window = XCreateWindow(m_display
, m_root
, msg->m_x
@@ -519,7 +540,7 @@ namespace entry
, InputOutput
, m_visual
, CWBorderPixel|CWEventMask
- , &windowAttrs
+ , &m_windowAttrs
);
m_window[_handle.idx] = window;
@@ -583,6 +604,8 @@ namespace entry
Visual* m_visual;
Window m_root;
+ XSetWindowAttributes m_windowAttrs;
+
Display* m_display;
Window m_window[ENTRY_CONFIG_MAX_WINDOWS];
uint32_t m_flags[ENTRY_CONFIG_MAX_WINDOWS];
@@ -648,26 +671,23 @@ namespace entry
void setWindowPos(WindowHandle _handle, int32_t _x, int32_t _y)
{
- BX_UNUSED(_handle, _x, _y);
+ Display* display = s_ctx.m_display;
+ Window window = s_ctx.m_window[_handle.idx];
+ XMoveWindow(display, window, _x, _y);
}
void setWindowSize(WindowHandle _handle, uint32_t _width, uint32_t _height)
{
- BX_UNUSED(_handle);
- XResizeRequestEvent ev;
- ev.type = ResizeRequest;
- ev.serial = 0;
- ev.send_event = true;
- ev.display = s_ctx.m_display;
- ev.window = s_ctx.m_window[0];
- ev.width = (int)_width;
- ev.height = (int)_height;
- XSendEvent(s_ctx.m_display, s_ctx.m_window[0], false, ResizeRedirectMask, (XEvent*)&ev);
+ Display* display = s_ctx.m_display;
+ Window window = s_ctx.m_window[_handle.idx];
+ XResizeWindow(display, window, int32_t(_width), int32_t(_height) );
}
void setWindowTitle(WindowHandle _handle, const char* _title)
{
- XStoreName(s_ctx.m_display, s_ctx.m_window[_handle.idx], _title);
+ Display* display = s_ctx.m_display;
+ Window window = s_ctx.m_window[_handle.idx];
+ XStoreName(display, window, _title);
}
void toggleWindowFrame(WindowHandle _handle)
diff --git a/3rdparty/bgfx/examples/common/font/font_manager.cpp b/3rdparty/bgfx/examples/common/font/font_manager.cpp
index 8532a534e03..053f7c95f93 100644
--- a/3rdparty/bgfx/examples/common/font/font_manager.cpp
+++ b/3rdparty/bgfx/examples/common/font/font_manager.cpp
@@ -25,7 +25,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
#include "../common.h"
-#include <bgfx.h>
+#include <bgfx/bgfx.h>
#include <math.h>
#if USE_EDTAA3
diff --git a/3rdparty/bgfx/examples/common/font/font_manager.h b/3rdparty/bgfx/examples/common/font/font_manager.h
index 73d47120333..978440a8f73 100644
--- a/3rdparty/bgfx/examples/common/font/font_manager.h
+++ b/3rdparty/bgfx/examples/common/font/font_manager.h
@@ -7,7 +7,7 @@
#define FONT_MANAGER_H_HEADER_GUARD
#include <bx/handlealloc.h>
-#include <bgfx.h>
+#include <bgfx/bgfx.h>
class Atlas;
diff --git a/3rdparty/bgfx/examples/common/font/text_buffer_manager.cpp b/3rdparty/bgfx/examples/common/font/text_buffer_manager.cpp
index d42e0cb8d40..540a0ea3869 100644
--- a/3rdparty/bgfx/examples/common/font/text_buffer_manager.cpp
+++ b/3rdparty/bgfx/examples/common/font/text_buffer_manager.cpp
@@ -5,7 +5,7 @@
#include "../common.h"
-#include <bgfx.h>
+#include <bgfx/bgfx.h>
#include <stddef.h> // offsetof
#include <memory.h> // memcpy
#include <wchar.h> // wcslen
@@ -329,6 +329,15 @@ void TextBuffer::clearTextBuffer()
void TextBuffer::appendGlyph(FontHandle _handle, CodePoint _codePoint)
{
+ if (_codePoint == L'\t')
+ {
+ for (uint32_t ii = 0; ii < 4; ++ii)
+ {
+ appendGlyph(_handle, L' ');
+ }
+ return;
+ }
+
const GlyphInfo* glyph = m_fontManager->getGlyphInfo(_handle, _codePoint);
BX_WARN(NULL != glyph, "Glyph not found (font handle %d, code point %d)", _handle.idx, _codePoint);
if (NULL == glyph)
@@ -336,27 +345,27 @@ void TextBuffer::appendGlyph(FontHandle _handle, CodePoint _codePoint)
return;
}
- const FontInfo& font = m_fontManager->getFontInfo(_handle);
-
if( m_vertexCount/4 >= MAX_BUFFERED_CHARACTERS)
{
return;
}
+ const FontInfo& font = m_fontManager->getFontInfo(_handle);
+
if (_codePoint == L'\n')
{
m_penX = m_originX;
m_penY += m_lineGap + m_lineAscender -m_lineDescender;
m_lineGap = font.lineGap;
- m_lineDescender = font.descender;
- m_lineAscender = font.ascender;
+ m_lineDescender = font.descender;
+ m_lineAscender = font.ascender;
m_lineStartIndex = m_vertexCount;
return;
}
//is there a change of font size that require the text on the left to be centered again ?
if (font.ascender > m_lineAscender
- || (font.descender < m_lineDescender) )
+ || (font.descender < m_lineDescender) )
{
if (font.descender < m_lineDescender)
{
@@ -377,7 +386,7 @@ void TextBuffer::appendGlyph(FontHandle _handle, CodePoint _codePoint)
const Atlas* atlas = m_fontManager->getAtlas();
if (m_styleFlags & STYLE_BACKGROUND
- && m_backgroundColor & 0xFF000000)
+ && m_backgroundColor & 0xff000000)
{
float x0 = (m_penX - kerning);
float y0 = (m_penY);
@@ -592,7 +601,7 @@ TextBufferManager::TextBufferManager(FontManager* _fontManager)
vs_font_distance_field_subpixel = bgfx::makeRef(vs_font_distance_field_subpixel_mtl, sizeof(vs_font_distance_field_subpixel_mtl) );
fs_font_distance_field_subpixel = bgfx::makeRef(fs_font_distance_field_subpixel_mtl, sizeof(fs_font_distance_field_subpixel_mtl) );
break;
-
+
default:
vs_font_basic = bgfx::makeRef(vs_font_basic_glsl, sizeof(vs_font_basic_glsl) );
fs_font_basic = bgfx::makeRef(fs_font_basic_glsl, sizeof(fs_font_basic_glsl) );
diff --git a/3rdparty/bgfx/examples/common/imgui/imgui.cpp b/3rdparty/bgfx/examples/common/imgui/imgui.cpp
index 1ff8e090818..073191fde57 100644
--- a/3rdparty/bgfx/examples/common/imgui/imgui.cpp
+++ b/3rdparty/bgfx/examples/common/imgui/imgui.cpp
@@ -466,7 +466,7 @@ struct Imgui
_size = sizeof(s_droidSansTtf);
}
- IMGUI_create(_data, _size, _fontSize, _allocator);
+ IMGUI_create(_data, _size, _fontSize, m_allocator);
m_nvg = nvgCreate(1, m_view);
nvgCreateFontMem(m_nvg, "default", (unsigned char*)_data, INT32_MAX, 0);
@@ -3080,8 +3080,8 @@ struct Imgui
bool visible(int32_t _elemY, int32_t _elemHeight, int32_t _scissorY, int32_t _scissorHeight)
{
- return _elemY > _scissorY
- && (_elemY+_elemHeight) < (_scissorY+_scissorHeight);
+ return (_elemY+_elemHeight) > _scissorY
+ && (_elemY) < (_scissorY+_scissorHeight);
}
inline Area& getCurrentArea()
diff --git a/3rdparty/bgfx/examples/common/imgui/imgui.h b/3rdparty/bgfx/examples/common/imgui/imgui.h
index acd6e6daf98..e85b9d3a16a 100644
--- a/3rdparty/bgfx/examples/common/imgui/imgui.h
+++ b/3rdparty/bgfx/examples/common/imgui/imgui.h
@@ -26,8 +26,9 @@
#ifndef IMGUI_H_HEADER_GUARD
#define IMGUI_H_HEADER_GUARD
-#include <bgfx.h>
+#include <bgfx/bgfx.h>
#include <ocornut-imgui/imgui.h>
+#include <ocornut-imgui/imgui_wm.h>
#define IMGUI_MBUT_LEFT 0x01
#define IMGUI_MBUT_RIGHT 0x02
@@ -207,20 +208,65 @@ bool imguiMouseOverArea();
namespace ImGui
{
+#define IMGUI_FLAGS_NONE UINT16_C(0x0000)
+#define IMGUI_FLAGS_ALPHA_BLEND UINT16_C(0x0001)
+
+ // Helper function for passing bgfx::TextureHandle to ImGui::Image.
+ inline void Image(bgfx::TextureHandle _handle
+ , uint16_t _flags
+ , const ImVec2& _size
+ , const ImVec2& _uv0 = ImVec2(0.0f, 0.0f)
+ , const ImVec2& _uv1 = ImVec2(1.0f, 1.0f)
+ , const ImVec4& _tintCol = ImVec4(1.0f, 1.0f, 1.0f, 1.0f)
+ , const ImVec4& _borderCol = ImVec4(0.0f, 0.0f, 0.0f, 0.0f)
+ )
+ {
+ union { struct { uint16_t flags; bgfx::TextureHandle handle; } s; ImTextureID ptr; } texture;
+ texture.s.flags = _flags;
+ texture.s.handle = _handle;
+ Image(texture.ptr, _size, _uv0, _uv1, _tintCol, _borderCol);
+ }
+
// Helper function for passing bgfx::TextureHandle to ImGui::Image.
- inline void Image(bgfx::TextureHandle _handle, const ImVec2& _size, const ImVec2& _uv0 = ImVec2(0, 0), const ImVec2& _uv1 = ImVec2(1, 1), const ImVec4& _tint_col = ImVec4(1, 1, 1, 1), const ImVec4& _border_col = ImVec4(0, 0, 0, 0) )
+ inline void Image(bgfx::TextureHandle _handle
+ , const ImVec2& _size
+ , const ImVec2& _uv0 = ImVec2(0.0f, 0.0f)
+ , const ImVec2& _uv1 = ImVec2(1.0f, 1.0f)
+ , const ImVec4& _tintCol = ImVec4(1.0f, 1.0f, 1.0f, 1.0f)
+ , const ImVec4& _borderCol = ImVec4(0.0f, 0.0f, 0.0f, 0.0f)
+ )
+ {
+ Image(_handle, IMGUI_FLAGS_ALPHA_BLEND, _size, _uv0, _uv1, _tintCol, _borderCol);
+ }
+
+ // Helper function for passing bgfx::TextureHandle to ImGui::ImageButton.
+ inline bool ImageButton(bgfx::TextureHandle _handle
+ , uint16_t _flags
+ , const ImVec2& _size
+ , const ImVec2& _uv0 = ImVec2(0.0f, 0.0f)
+ , const ImVec2& _uv1 = ImVec2(1.0f, 1.0f)
+ , int _framePadding = -1
+ , const ImVec4& _bgCol = ImVec4(0.0f, 0.0f, 0.0f, 0.0f)
+ , const ImVec4& _tintCol = ImVec4(1.0f, 1.0f, 1.0f, 1.0f)
+ )
{
- union { bgfx::TextureHandle handle; ImTextureID ptr; } texture;
- texture.handle = _handle;
- Image(texture.ptr, _size, _uv0, _uv1, _tint_col, _border_col);
+ union { struct { uint16_t flags; bgfx::TextureHandle handle; } s; ImTextureID ptr; } texture;
+ texture.s.flags = _flags;
+ texture.s.handle = _handle;
+ return ImageButton(texture.ptr, _size, _uv0, _uv1, _framePadding, _bgCol, _tintCol);
}
// Helper function for passing bgfx::TextureHandle to ImGui::ImageButton.
- inline bool ImageButton(bgfx::TextureHandle _handle, const ImVec2& _size, const ImVec2& _uv0 = ImVec2(0,0), const ImVec2& _uv1 = ImVec2(1,1), int _frame_padding = -1, const ImVec4& _bg_col = ImVec4(0,0,0,0), const ImVec4& _tint_col = ImVec4(1,1,1,1))
+ inline bool ImageButton(bgfx::TextureHandle _handle
+ , const ImVec2& _size
+ , const ImVec2& _uv0 = ImVec2(0.0f, 0.0f)
+ , const ImVec2& _uv1 = ImVec2(1.0f, 1.0f)
+ , int _framePadding = -1
+ , const ImVec4& _bgCol = ImVec4(0.0f, 0.0f, 0.0f, 0.0f)
+ , const ImVec4& _tintCol = ImVec4(1.0f, 1.0f, 1.0f, 1.0f)
+ )
{
- union { bgfx::TextureHandle handle; ImTextureID ptr; } texture;
- texture.handle = _handle;
- return ImageButton(texture.ptr, _size, _uv0, _uv1, _frame_padding, _bg_col, _tint_col);
+ return ImageButton(_handle, IMGUI_FLAGS_ALPHA_BLEND, _size, _uv0, _uv1, _framePadding, _bgCol, _tintCol);
}
} // namespace ImGui
diff --git a/3rdparty/bgfx/examples/common/imgui/ocornut_imgui.cpp b/3rdparty/bgfx/examples/common/imgui/ocornut_imgui.cpp
index aff41ac376a..8efddcc65f8 100644
--- a/3rdparty/bgfx/examples/common/imgui/ocornut_imgui.cpp
+++ b/3rdparty/bgfx/examples/common/imgui/ocornut_imgui.cpp
@@ -3,15 +3,24 @@
* License: http://www.opensource.org/licenses/BSD-2-Clause
*/
-#include <bgfx.h>
+#include <bgfx/bgfx.h>
#include <bx/allocator.h>
#include <bx/fpumath.h>
#include <bx/timer.h>
#include <ocornut-imgui/imgui.h>
+#include <ocornut-imgui/imgui_wm.h>
#include "imgui.h"
#include "ocornut_imgui.h"
#include <stb/stb_image.c>
+#ifndef USE_ENTRY
+# define USE_ENTRY defined(SCI_NAMESPACE)
+#endif // USE_ENTRY
+
+#if USE_ENTRY
+# include "../entry/entry.h"
+#endif // USE_ENTRY
+
#if defined(SCI_NAMESPACE)
# include "../entry/input.h"
# include "scintilla.h"
@@ -20,86 +29,334 @@
#include "vs_ocornut_imgui.bin.h"
#include "fs_ocornut_imgui.bin.h"
+void viewCallback(const ImDrawList* _parentList, const ImDrawCmd* _cmd);
+
+class PlatformWindow : public ImGuiWM::PlatformWindow
+{
+ typedef ImGuiWM::PlatformWindow Super;
+
+public:
+ PlatformWindow(bool _mainWindow, bool _isDragWindow)
+ : ImGuiWM::PlatformWindow(_mainWindow, _isDragWindow)
+ , m_pos(0.0f, 0.0f)
+ , m_size(0.0f, 0.0f)
+ , m_drag(false)
+ {
+#if USE_ENTRY
+ if (!_mainWindow
+ && !_isDragWindow)
+ {
+ m_window = entry::createWindow(0, 0, 640, 380);
+ extern void pwToWindow(entry::WindowHandle _handle, PlatformWindow* _pw);
+ pwToWindow(m_window, this);
+ }
+ else
+ {
+ m_window.idx = 0;
+ }
+#endif // USE_ENTRY
+ }
+
+ virtual ~PlatformWindow() BX_OVERRIDE
+ {
+ }
+
+ virtual bool Init(ImGuiWM::PlatformWindow* /*_parent*/) BX_OVERRIDE
+ {
+ return true;
+ }
+
+ virtual const ImVec2& GetPosition() const BX_OVERRIDE
+ {
+ return m_pos;
+ }
+
+ virtual const ImVec2& GetSize() const BX_OVERRIDE
+ {
+ return m_size;
+ }
+
+ virtual void Show() BX_OVERRIDE
+ {
+ }
+
+ virtual void Hide() BX_OVERRIDE
+ {
+ }
+
+ virtual void SetSize(const ImVec2& _size) BX_OVERRIDE
+ {
+#if USE_ENTRY
+ if (0 != m_window.idx
+ && m_size.x != _size.x
+ && m_size.y != _size.y)
+ {
+ entry::setWindowSize(m_window, int32_t(_size.x), int32_t(_size.y) );
+ }
+#endif // USE_ENTRY
+
+ m_size = _size;
+ }
+
+ virtual void SetPosition(const ImVec2& _pos) BX_OVERRIDE
+ {
+
+#if USE_ENTRY
+ if (0 != m_window.idx
+ && m_pos.x != _pos.x
+ && m_pos.y != _pos.y)
+ {
+ entry::setWindowPos(m_window, int32_t(_pos.x), int32_t(_pos.y) );
+ }
+#endif // USE_ENTRY
+
+ m_pos = _pos;
+ }
+
+ virtual void SetTitle(const char* _title) BX_OVERRIDE
+ {
+#if USE_ENTRY
+ entry::setWindowTitle(m_window, _title);
+#else
+ BX_UNUSED(_title);
+#endif // USE_ENTRY
+ }
+
+ virtual void PreUpdate() BX_OVERRIDE
+ {
+ }
+
+ virtual void PaintBegin()
+ {
+#if USE_ENTRY
+ if (!m_bIsDragWindow)
+ {
+ ImDrawList* drawList = ImGui::GetWindowDrawList();
+ union { entry::WindowHandle handle; void* ptr; } cast = { m_window };
+ drawList->AddCallback(viewCallback, cast.ptr);
+ drawList->PushClipRect(ImVec4(0.0f, 0.0f, m_size.x, m_size.y) );
+ }
+#endif // USE_ENTRY
+ }
+
+ virtual void Paint() BX_OVERRIDE
+ {
+ if (!m_bIsDragWindow)
+ {
+ Super::Paint();
+ }
+ }
+
+ virtual void PaintEnd()
+ {
+#if USE_ENTRY
+ if (!m_bIsDragWindow)
+ {
+ ImDrawList* drawList = ImGui::GetWindowDrawList();
+ drawList->PopClipRect();
+ drawList->AddCallback(viewCallback, NULL);
+ }
+#endif // USE_ENTRY
+ }
+
+ virtual void Destroy() BX_OVERRIDE
+ {
+ }
+
+ virtual void StartDrag() BX_OVERRIDE
+ {
+ m_drag = true;
+ }
+
+ virtual void StopDrag() BX_OVERRIDE
+ {
+ m_drag = false;
+ }
+
+ virtual bool IsDraging() BX_OVERRIDE
+ {
+ return m_drag;
+ }
+
+private:
+ ImVec2 m_pos;
+ ImVec2 m_size;
+ bool m_drag;
+
+#if USE_ENTRY
+ entry::WindowHandle m_window;
+#endif // USE_ENTRY
+};
+
+class WindowManager : public ImGuiWM::WindowManager
+{
+ typedef ImGuiWM::WindowManager Super;
+
+public:
+ WindowManager()
+ {
+ }
+
+ virtual ~WindowManager() BX_OVERRIDE
+ {
+ }
+
+protected:
+ virtual ImGuiWM::PlatformWindow* CreatePlatformWindow(bool _main, ImGuiWM::PlatformWindow* _parent, bool _isDragWindow) BX_OVERRIDE
+ {
+#if USE_ENTRY
+#else
+ if (!_main
+ && !_isDragWindow)
+ {
+ return NULL;
+ }
+#endif // USE_ENTRY
+
+ PlatformWindow* window = new (ImGui::MemAlloc(sizeof(PlatformWindow) ) ) PlatformWindow(_main, _isDragWindow);
+ window->Init(_parent);
+ return static_cast<ImGuiWM::PlatformWindow*>(window);
+ }
+
+ virtual void LogFormatted(const char* _str) BX_OVERRIDE
+ {
+ BX_TRACE("%s", _str); BX_UNUSED(_str);
+ }
+
+ virtual void InternalRun() BX_OVERRIDE
+ {
+ PreUpdate();
+ Update();
+ }
+};
+
struct OcornutImguiContext
{
static void* memAlloc(size_t _size);
static void memFree(void* _ptr);
- static void renderDrawLists(ImDrawData* draw_data);
+ static void renderDrawLists(ImDrawData* _drawData);
- void render(ImDrawData* draw_data)
+ void render(ImDrawData* _drawData)
{
- const float width = ImGui::GetIO().DisplaySize.x;
- const float height = ImGui::GetIO().DisplaySize.y;
+ const ImGuiIO& io = ImGui::GetIO();
+ const float width = io.DisplaySize.x;
+ const float height = io.DisplaySize.y;
- float ortho[16];
- bx::mtxOrtho(ortho, 0.0f, width, height, 0.0f, -1.0f, 1.0f);
+ {
+ float ortho[16];
+ bx::mtxOrtho(ortho, 0.0f, width, height, 0.0f, -1.0f, 1.0f);
+ bgfx::setViewTransform(m_viewId, NULL, ortho);
+ }
- bgfx::setViewTransform(m_viewId, NULL, ortho);
+#if USE_ENTRY
+ for (uint32_t ii = 1; ii < BX_COUNTOF(m_window); ++ii)
+ {
+ Window& window = m_window[ii];
+ if (bgfx::isValid(window.m_fbh) )
+ {
+ const uint8_t viewId = window.m_viewId;
+ bgfx::setViewClear(viewId
+ , BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH
+ , 0x303030ff + rand()
+ , 1.0f
+ , 0
+ );
+ bgfx::setViewFrameBuffer(viewId, window.m_fbh);
+ bgfx::setViewRect(viewId
+ , 0
+ , 0
+ , window.m_state.m_width
+ , window.m_state.m_height
+ );
+ float ortho[16];
+ bx::mtxOrtho(ortho
+ , 0.0f
+ , float(window.m_state.m_width)
+ , float(window.m_state.m_height)
+ , 0.0f
+ , -1.0f
+ , 1.0f
+ );
+ bgfx::setViewTransform(viewId
+ , NULL
+ , ortho
+ );
+ }
+ }
+#endif // USE_ENTRY
// Render command lists
- for (int32_t ii = 0; ii < draw_data->CmdListsCount; ++ii)
+ for (int32_t ii = 0, num = _drawData->CmdListsCount; ii < num; ++ii)
{
bgfx::TransientVertexBuffer tvb;
bgfx::TransientIndexBuffer tib;
- const ImDrawList* cmd_list = draw_data->CmdLists[ii];
- uint32_t vtx_size = (uint32_t)cmd_list->VtxBuffer.size();
- uint32_t idx_size = (uint32_t)cmd_list->IdxBuffer.size();
+ const ImDrawList* drawList = _drawData->CmdLists[ii];
+ uint32_t numVertices = (uint32_t)drawList->VtxBuffer.size();
+ uint32_t numIndices = (uint32_t)drawList->IdxBuffer.size();
- if (!bgfx::checkAvailTransientVertexBuffer(vtx_size, m_decl) || !bgfx::checkAvailTransientIndexBuffer(idx_size) )
+ if (!bgfx::checkAvailTransientVertexBuffer(numVertices, m_decl)
+ || !bgfx::checkAvailTransientIndexBuffer(numIndices) )
{
// not enough space in transient buffer just quit drawing the rest...
break;
}
- bgfx::allocTransientVertexBuffer(&tvb, vtx_size, m_decl);
- bgfx::allocTransientIndexBuffer(&tib, idx_size);
+ bgfx::allocTransientVertexBuffer(&tvb, numVertices, m_decl);
+ bgfx::allocTransientIndexBuffer(&tib, numIndices);
ImDrawVert* verts = (ImDrawVert*)tvb.data;
- memcpy(verts, cmd_list->VtxBuffer.begin(), vtx_size * sizeof(ImDrawVert) );
+ memcpy(verts, drawList->VtxBuffer.begin(), numVertices * sizeof(ImDrawVert) );
ImDrawIdx* indices = (ImDrawIdx*)tib.data;
- memcpy(indices, cmd_list->IdxBuffer.begin(), idx_size * sizeof(ImDrawIdx) );
+ memcpy(indices, drawList->IdxBuffer.begin(), numIndices * sizeof(ImDrawIdx) );
- uint32_t elem_offset = 0;
- const ImDrawCmd* pcmd_begin = cmd_list->CmdBuffer.begin();
- const ImDrawCmd* pcmd_end = cmd_list->CmdBuffer.end();
- for (const ImDrawCmd* pcmd = pcmd_begin; pcmd != pcmd_end; pcmd++)
+ uint32_t offset = 0;
+ for (const ImDrawCmd* cmd = drawList->CmdBuffer.begin(), *cmdEnd = drawList->CmdBuffer.end(); cmd != cmdEnd; ++cmd)
{
- if (pcmd->UserCallback)
+ if (cmd->UserCallback)
{
- pcmd->UserCallback(cmd_list, pcmd);
- elem_offset += pcmd->ElemCount;
- continue;
+ cmd->UserCallback(drawList, cmd);
}
- if (0 == pcmd->ElemCount)
+ else if (0 != cmd->ElemCount)
{
- continue;
+ uint64_t state = 0
+ | BGFX_STATE_RGB_WRITE
+ | BGFX_STATE_ALPHA_WRITE
+ | BGFX_STATE_MSAA
+ ;
+
+ bgfx::TextureHandle th = m_texture;
+
+ if (NULL != cmd->TextureId)
+ {
+ union { ImTextureID ptr; struct { uint16_t flags; bgfx::TextureHandle handle; } s; } texture = { cmd->TextureId };
+ state |= 0 != (IMGUI_FLAGS_ALPHA_BLEND & texture.s.flags)
+ ? BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA)
+ : BGFX_STATE_NONE
+ ;
+ th = texture.s.handle;
+ }
+ else
+ {
+ state |= BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA);
+ }
+
+ const uint16_t xx = uint16_t(bx::fmax(cmd->ClipRect.x, 0.0f) );
+ const uint16_t yy = uint16_t(bx::fmax(cmd->ClipRect.y, 0.0f) );
+ bgfx::setScissor(xx, yy
+ , uint16_t(bx::fmin(cmd->ClipRect.z, 65535.0f)-xx)
+ , uint16_t(bx::fmin(cmd->ClipRect.w, 65535.0f)-yy)
+ );
+
+ bgfx::setState(state);
+ bgfx::setTexture(0, s_tex, th);
+ bgfx::setVertexBuffer(&tvb, 0, numVertices);
+ bgfx::setIndexBuffer(&tib, offset, cmd->ElemCount);
+ bgfx::submit(m_viewId, m_program);
}
- bgfx::setState(0
- | BGFX_STATE_RGB_WRITE
- | BGFX_STATE_ALPHA_WRITE
- | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA)
- | BGFX_STATE_MSAA
- );
- bgfx::setScissor(uint16_t(bx::fmax(pcmd->ClipRect.x, 0.0f) )
- , uint16_t(bx::fmax(pcmd->ClipRect.y, 0.0f) )
- , uint16_t(bx::fmin(pcmd->ClipRect.z, 65535.0f)-bx::fmax(pcmd->ClipRect.x, 0.0f) )
- , uint16_t(bx::fmin(pcmd->ClipRect.w, 65535.0f)-bx::fmax(pcmd->ClipRect.y, 0.0f) )
- );
- union { void* ptr; bgfx::TextureHandle handle; } texture = { pcmd->TextureId };
-
- bgfx::setTexture(0, s_tex, 0 != texture.handle.idx
- ? texture.handle
- : m_texture
- );
-
- bgfx::setVertexBuffer(&tvb, 0, vtx_size);
- bgfx::setIndexBuffer(&tib, elem_offset, pcmd->ElemCount);
- bgfx::submit(m_viewId, m_program);
-
- elem_offset += pcmd->ElemCount;
+ offset += cmd->ElemCount;
}
}
}
@@ -176,9 +433,9 @@ struct OcornutImguiContext
m_decl
.begin()
- .add(bgfx::Attrib::Position, 2, bgfx::AttribType::Float)
+ .add(bgfx::Attrib::Position, 2, bgfx::AttribType::Float)
.add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float)
- .add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true)
+ .add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true)
.end();
s_tex = bgfx::createUniform("s_tex", bgfx::UniformType::Int1);
@@ -202,10 +459,61 @@ struct OcornutImguiContext
ImGuiStyle& style = ImGui::GetStyle();
style.FrameRounding = 4.0f;
+
+ m_wm = BX_NEW(m_allocator, WindowManager);
+ m_wm->Init();
+
+#if 0
+ {
+ class Window : public ImGuiWM::Window
+ {
+ public:
+ Window(const char* _title)
+ : ImGuiWM::Window()
+ {
+ SetTitle(_title);
+ }
+
+ virtual void OnGui() BX_OVERRIDE
+ {
+ }
+ };
+
+ class WindowX : public ImGuiWM::Window
+ {
+ public:
+ WindowX(const char* _title)
+ : ImGuiWM::Window()
+ {
+ SetTitle(_title);
+ }
+
+ virtual void OnGui() BX_OVERRIDE
+ {
+#if defined(SCI_NAMESPACE) && 0
+ bool opened = true;
+ ImGuiScintilla("Scintilla Editor", &opened, ImVec2(640.0f, 480.0f) );
+#endif // 0
+ }
+ };
+
+ Window* w0 = new Window("test");
+ WindowX* w1 = new WindowX("abcd");
+ Window* w2 = new Window("xyzw");
+ Window* w3 = new Window("0123");
+
+ m_wm->Dock(w0);
+ m_wm->DockWith(w1, w0, ImGuiWM::E_DOCK_ORIENTATION_RIGHT);
+ m_wm->DockWith(w2, w1, ImGuiWM::E_DOCK_ORIENTATION_BOTTOM);
+ m_wm->DockWith(w3, w0, ImGuiWM::E_DOCK_ORIENTATION_BOTTOM);
+ }
+#endif // 0
}
void destroy()
{
+ m_wm->Exit();
+ BX_DELETE(m_allocator, m_wm);
ImGui::Shutdown();
bgfx::destroyUniform(s_tex);
@@ -217,7 +525,9 @@ struct OcornutImguiContext
void beginFrame(int32_t _mx, int32_t _my, uint8_t _button, int32_t _scroll, int _width, int _height, char _inputChar, uint8_t _viewId)
{
- m_viewId = _viewId;
+ m_viewId = _viewId;
+ m_defaultViewId = _viewId;
+
ImGuiIO& io = ImGui::GetIO();
if (_inputChar < 0x7f)
{
@@ -261,15 +571,11 @@ struct OcornutImguiContext
bool opened = true;
ShowExampleAppCustomNodeGraph(&opened);
#endif // 0
-
-#if defined(SCI_NAMESPACE) && 0
- bool opened = true;
- ImGuiScintilla("Scintilla Editor", &opened, ImVec2(640.0f, 480.0f) );
-#endif // 0
}
void endFrame()
{
+ m_wm->Run();
ImGui::Render();
}
@@ -278,13 +584,84 @@ struct OcornutImguiContext
bgfx::ProgramHandle m_program;
bgfx::TextureHandle m_texture;
bgfx::UniformHandle s_tex;
+ WindowManager* m_wm;
int64_t m_last;
int32_t m_lastScroll;
uint8_t m_viewId;
+ uint8_t m_defaultViewId;
+
+#if USE_ENTRY
+ struct Window
+ {
+ Window()
+ {
+ m_fbh.idx = bgfx::invalidHandle;
+ }
+
+ entry::WindowState m_state;
+ PlatformWindow* m_pw;
+ bgfx::FrameBufferHandle m_fbh;
+ uint8_t m_viewId;
+ };
+
+ Window m_window[16];
+#endif // USE_ENTRY
};
static OcornutImguiContext s_ctx;
+#if USE_ENTRY
+
+void viewCallback(const ImDrawList* /*_parentList*/, const ImDrawCmd* _cmd)
+{
+ union { void* ptr; entry::WindowHandle handle; } cast = { _cmd->UserCallbackData };
+
+ if (0 != cast.handle.idx)
+ {
+ s_ctx.m_viewId = s_ctx.m_window[cast.handle.idx].m_viewId;
+ }
+ else
+ {
+ s_ctx.m_viewId = s_ctx.m_defaultViewId;
+ }
+}
+
+void pwToWindow(entry::WindowHandle _handle, PlatformWindow* _pw)
+{
+ s_ctx.m_window[_handle.idx].m_pw = _pw;
+}
+
+void imguiUpdateWindow(const entry::WindowState& _state)
+{
+ OcornutImguiContext::Window& window = s_ctx.m_window[_state.m_handle.idx];
+
+ if (window.m_state.m_nwh != _state.m_nwh
+ || (window.m_state.m_width != _state.m_width
+ || window.m_state.m_height != _state.m_height) )
+ {
+ // When window changes size or native window handle changed
+ // frame buffer must be recreated.
+ if (bgfx::isValid(window.m_fbh) )
+ {
+ bgfx::destroyFrameBuffer(window.m_fbh);
+ window.m_fbh.idx = bgfx::invalidHandle;
+ }
+
+ if (NULL != _state.m_nwh)
+ {
+ window.m_fbh = bgfx::createFrameBuffer(_state.m_nwh, _state.m_width, _state.m_height);
+ window.m_viewId = 200 + _state.m_handle.idx;
+ }
+ else
+ {
+ window.m_viewId = s_ctx.m_defaultViewId;
+ }
+ }
+
+ memcpy(&window.m_state, &_state, sizeof(entry::WindowState) );
+}
+#endif // USE_ENTRY
+
void* OcornutImguiContext::memAlloc(size_t _size)
{
return BX_ALLOC(s_ctx.m_allocator, _size);
diff --git a/3rdparty/bgfx/examples/common/imgui/scintilla.cpp b/3rdparty/bgfx/examples/common/imgui/scintilla.cpp
index d88a75efa2d..f9f0d06ea22 100644
--- a/3rdparty/bgfx/examples/common/imgui/scintilla.cpp
+++ b/3rdparty/bgfx/examples/common/imgui/scintilla.cpp
@@ -1105,7 +1105,7 @@ ScintillaEditor* ImGuiScintilla(const char* _name, bool* _opened, const ImVec2&
{
ScintillaEditor* sci = NULL;
- if (ImGui::Begin(_name, _opened, _size) )
+// if (ImGui::Begin(_name, _opened, _size) )
{
ImGuiStorage* storage = ImGui::GetStateStorage();
@@ -1121,7 +1121,7 @@ ScintillaEditor* ImGuiScintilla(const char* _name, bool* _opened, const ImVec2&
sci->draw();
}
- ImGui::End();
+// ImGui::End();
return sci;
}
diff --git a/3rdparty/bgfx/examples/common/nanovg/nanovg_bgfx.cpp b/3rdparty/bgfx/examples/common/nanovg/nanovg_bgfx.cpp
index 817457dbc14..263c1b31b94 100644
--- a/3rdparty/bgfx/examples/common/nanovg/nanovg_bgfx.cpp
+++ b/3rdparty/bgfx/examples/common/nanovg/nanovg_bgfx.cpp
@@ -28,7 +28,7 @@
#include <math.h>
#include "nanovg.h"
-#include <bgfx.h>
+#include <bgfx/bgfx.h>
#include <bx/bx.h>
@@ -667,7 +667,6 @@ namespace
);
bgfx::setVertexBuffer(&gl->tvb, paths[i].strokeOffset, paths[i].strokeCount);
bgfx::setTexture(0, gl->s_tex, gl->th);
- bgfx::setTexture(0, gl->s_tex, gl->th);
bgfx::submit(gl->viewid, gl->prog);
}
}
diff --git a/3rdparty/bgfx/examples/makefile b/3rdparty/bgfx/examples/makefile
index ebebb525fb0..56ad944b750 100644
--- a/3rdparty/bgfx/examples/makefile
+++ b/3rdparty/bgfx/examples/makefile
@@ -30,3 +30,23 @@ rebuild:
@make -s --no-print-directory rebuild -C common/font
@make -s --no-print-directory rebuild -C common/imgui
@make -s --no-print-directory rebuild -C common/nanovg
+
+metal:
+ @make -s --no-print-directory TARGET=5 -C 01-cubes
+ @make -s --no-print-directory TARGET=5 -C 03-raymarch
+ @make -s --no-print-directory TARGET=5 -C 04-mesh
+ @make -s --no-print-directory TARGET=5 -C 05-instancing
+ @make -s --no-print-directory TARGET=5 -C 06-bump
+ @make -s --no-print-directory TARGET=5 -C 07-callback
+ @make -s --no-print-directory TARGET=5 -C 08-update
+ @make -s --no-print-directory TARGET=5 -C 09-hdr
+ @make -s --no-print-directory TARGET=5 -C 12-lod
+ @make -s --no-print-directory TARGET=5 -C 13-stencil
+ @make -s --no-print-directory TARGET=5 -C 14-shadowvolumes
+ @make -s --no-print-directory TARGET=5 -C 15-shadowmaps-simple
+ @make -s --no-print-directory TARGET=5 -C 16-shadowmaps
+ @make -s --no-print-directory TARGET=5 -C 18-ibl
+ @make -s --no-print-directory TARGET=5 -C 19-oit
+ @make -s --no-print-directory TARGET=5 -C 21-deferred
+ @make -s --no-print-directory TARGET=5 -C 23-vectordisplay
+ @make -s --no-print-directory TARGET=5 -C 24-nbody
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_bump.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_bump.bin
new file mode 100644
index 00000000000..d9c2da922fc
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_bump.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_callback.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_callback.bin
new file mode 100644
index 00000000000..9ac95509870
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_callback.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_cubes.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_cubes.bin
new file mode 100644
index 00000000000..fb726f353c0
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_cubes.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_deferred_combine.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_deferred_combine.bin
new file mode 100644
index 00000000000..fa8ca277c11
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_deferred_combine.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_deferred_debug.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_deferred_debug.bin
new file mode 100644
index 00000000000..e48079000cc
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_deferred_debug.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_deferred_debug_line.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_deferred_debug_line.bin
new file mode 100644
index 00000000000..fb726f353c0
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_deferred_debug_line.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_deferred_geom.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_deferred_geom.bin
new file mode 100644
index 00000000000..8a18929a80c
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_deferred_geom.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_deferred_light.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_deferred_light.bin
new file mode 100644
index 00000000000..89bc35bc2a3
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_deferred_light.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_hdr_blur.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_hdr_blur.bin
new file mode 100644
index 00000000000..14475c3ade0
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_hdr_blur.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_hdr_bright.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_hdr_bright.bin
new file mode 100644
index 00000000000..6ec541f32ad
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_hdr_bright.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_hdr_lum.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_hdr_lum.bin
new file mode 100644
index 00000000000..76ff3900cd3
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_hdr_lum.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_hdr_lumavg.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_hdr_lumavg.bin
new file mode 100644
index 00000000000..f4d3784e6da
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_hdr_lumavg.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_hdr_mesh.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_hdr_mesh.bin
new file mode 100644
index 00000000000..f650d6686b2
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_hdr_mesh.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_hdr_skybox.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_hdr_skybox.bin
new file mode 100644
index 00000000000..d113a607c3e
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_hdr_skybox.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_hdr_tonemap.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_hdr_tonemap.bin
new file mode 100644
index 00000000000..bb42a0bdae8
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_hdr_tonemap.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_ibl_mesh.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_ibl_mesh.bin
new file mode 100644
index 00000000000..3ee33011539
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_ibl_mesh.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_ibl_skybox.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_ibl_skybox.bin
new file mode 100644
index 00000000000..f36f1f5ebba
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_ibl_skybox.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_instancing.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_instancing.bin
new file mode 100644
index 00000000000..fb726f353c0
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_instancing.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_mesh.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_mesh.bin
new file mode 100644
index 00000000000..f99861205a3
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_mesh.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_oit.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_oit.bin
new file mode 100644
index 00000000000..6d6012f5eb3
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_oit.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_oit_wb.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_oit_wb.bin
new file mode 100644
index 00000000000..2dae0e8f200
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_oit_wb.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_oit_wb_blit.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_oit_wb_blit.bin
new file mode 100644
index 00000000000..ef295e63d22
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_oit_wb_blit.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_oit_wb_separate.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_oit_wb_separate.bin
new file mode 100644
index 00000000000..2ef7b1b065c
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_oit_wb_separate.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_oit_wb_separate_blit.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_oit_wb_separate_blit.bin
new file mode 100644
index 00000000000..3772fd2de80
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_oit_wb_separate_blit.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_particle.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_particle.bin
new file mode 100644
index 00000000000..39d113334d6
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_particle.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_raymarching.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_raymarching.bin
new file mode 100644
index 00000000000..1a3de3d0ab9
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_raymarching.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_black.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_black.bin
new file mode 100644
index 00000000000..5281abc6100
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_black.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_esm.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_esm.bin
new file mode 100644
index 00000000000..5b9813e8595
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_esm.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_esm_csm.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_esm_csm.bin
new file mode 100644
index 00000000000..c5a8b4b215c
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_esm_csm.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_esm_linear.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_esm_linear.bin
new file mode 100644
index 00000000000..c4d87c03987
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_esm_linear.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_esm_linear_csm.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_esm_linear_csm.bin
new file mode 100644
index 00000000000..2eeed8cde91
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_esm_linear_csm.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_esm_linear_omni.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_esm_linear_omni.bin
new file mode 100644
index 00000000000..4ce8af71a63
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_esm_linear_omni.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_esm_omni.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_esm_omni.bin
new file mode 100644
index 00000000000..ca3449ca4d2
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_esm_omni.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_hard.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_hard.bin
new file mode 100644
index 00000000000..d8fe2fc1ae9
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_hard.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_hard_csm.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_hard_csm.bin
new file mode 100644
index 00000000000..5089c8f1d23
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_hard_csm.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_hard_linear.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_hard_linear.bin
new file mode 100644
index 00000000000..1884107d6bc
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_hard_linear.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_hard_linear_csm.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_hard_linear_csm.bin
new file mode 100644
index 00000000000..2fa958d85bd
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_hard_linear_csm.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_hard_linear_omni.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_hard_linear_omni.bin
new file mode 100644
index 00000000000..6e7bffc7959
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_hard_linear_omni.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_hard_omni.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_hard_omni.bin
new file mode 100644
index 00000000000..af048da8a6f
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_hard_omni.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_pcf.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_pcf.bin
new file mode 100644
index 00000000000..467c47d243e
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_pcf.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_pcf_csm.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_pcf_csm.bin
new file mode 100644
index 00000000000..6faad277fd6
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_pcf_csm.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_pcf_linear.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_pcf_linear.bin
new file mode 100644
index 00000000000..3e0fbb37abc
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_pcf_linear.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_pcf_linear_csm.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_pcf_linear_csm.bin
new file mode 100644
index 00000000000..31dd9f7c420
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_pcf_linear_csm.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_pcf_linear_omni.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_pcf_linear_omni.bin
new file mode 100644
index 00000000000..3a5f285cf37
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_pcf_linear_omni.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_pcf_omni.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_pcf_omni.bin
new file mode 100644
index 00000000000..e7c3ad1fa1a
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_pcf_omni.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_vsm.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_vsm.bin
new file mode 100644
index 00000000000..a76c572dc2a
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_vsm.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_vsm_csm.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_vsm_csm.bin
new file mode 100644
index 00000000000..8915dd6c718
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_vsm_csm.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_vsm_linear.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_vsm_linear.bin
new file mode 100644
index 00000000000..79ddb6551c8
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_vsm_linear.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_vsm_linear_csm.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_vsm_linear_csm.bin
new file mode 100644
index 00000000000..392fceccbd3
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_vsm_linear_csm.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_vsm_linear_omni.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_vsm_linear_omni.bin
new file mode 100644
index 00000000000..b377bf7db6a
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_vsm_linear_omni.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_vsm_omni.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_vsm_omni.bin
new file mode 100644
index 00000000000..953b60d9b18
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_lightning_vsm_omni.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_texture.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_texture.bin
new file mode 100644
index 00000000000..ae7007c7af8
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_color_texture.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_hblur.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_hblur.bin
new file mode 100644
index 00000000000..b5fe202adc9
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_hblur.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_hblur_vsm.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_hblur_vsm.bin
new file mode 100644
index 00000000000..f42eef2fcc8
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_hblur_vsm.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_packdepth.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_packdepth.bin
new file mode 100644
index 00000000000..ccec78ba002
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_packdepth.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_packdepth_linear.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_packdepth_linear.bin
new file mode 100644
index 00000000000..67b12c79dcc
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_packdepth_linear.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_packdepth_vsm.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_packdepth_vsm.bin
new file mode 100644
index 00000000000..7480677534d
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_packdepth_vsm.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_packdepth_vsm_linear.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_packdepth_vsm_linear.bin
new file mode 100644
index 00000000000..8b2ee2abbd3
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_packdepth_vsm_linear.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_texture.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_texture.bin
new file mode 100644
index 00000000000..436d6d4471f
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_texture.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_unpackdepth.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_unpackdepth.bin
new file mode 100644
index 00000000000..cd9a6e88530
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_unpackdepth.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_unpackdepth_vsm.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_unpackdepth_vsm.bin
new file mode 100644
index 00000000000..94abea67646
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_unpackdepth_vsm.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_vblur.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_vblur.bin
new file mode 100644
index 00000000000..b5fe202adc9
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_vblur.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_vblur_vsm.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_vblur_vsm.bin
new file mode 100644
index 00000000000..f42eef2fcc8
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowmaps_vblur_vsm.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_color_lightning.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_color_lightning.bin
new file mode 100644
index 00000000000..5f7d4490bb7
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_color_lightning.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_color_texture.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_color_texture.bin
new file mode 100644
index 00000000000..52de7234847
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_color_texture.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svbackblank.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svbackblank.bin
new file mode 100644
index 00000000000..187800af846
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svbackblank.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svbackcolor.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svbackcolor.bin
new file mode 100644
index 00000000000..ec4fa7bfff5
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svbackcolor.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svbacktex1.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svbacktex1.bin
new file mode 100644
index 00000000000..51d0af3c132
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svbacktex1.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svbacktex2.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svbacktex2.bin
new file mode 100644
index 00000000000..65eefb71cd1
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svbacktex2.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svfrontblank.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svfrontblank.bin
new file mode 100644
index 00000000000..747c3963734
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svfrontblank.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svfrontcolor.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svfrontcolor.bin
new file mode 100644
index 00000000000..ec4fa7bfff5
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svfrontcolor.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svfronttex1.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svfronttex1.bin
new file mode 100644
index 00000000000..1ee26821e14
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svfronttex1.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svfronttex2.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svfronttex2.bin
new file mode 100644
index 00000000000..d638ce4dbb2
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svfronttex2.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svside.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svside.bin
new file mode 100644
index 00000000000..e67e7c2306e
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svside.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svsideblank.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svsideblank.bin
new file mode 100644
index 00000000000..aaf666c25d8
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svsideblank.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svsidecolor.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svsidecolor.bin
new file mode 100644
index 00000000000..bdfa2f42428
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svsidecolor.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svsidetex.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svsidetex.bin
new file mode 100644
index 00000000000..843ccfa6f0e
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_svsidetex.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_texture.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_texture.bin
new file mode 100644
index 00000000000..e48079000cc
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_texture.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_texture_lightning.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_texture_lightning.bin
new file mode 100644
index 00000000000..7e7bbab26e3
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_shadowvolume_texture_lightning.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_sms_mesh.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_sms_mesh.bin
new file mode 100644
index 00000000000..5c173c76aac
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_sms_mesh.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_sms_mesh_pd.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_sms_mesh_pd.bin
new file mode 100644
index 00000000000..26a2cc3de69
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_sms_mesh_pd.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_sms_shadow.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_sms_shadow.bin
new file mode 100644
index 00000000000..5281abc6100
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_sms_shadow.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_sms_shadow_pd.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_sms_shadow_pd.bin
new file mode 100644
index 00000000000..ccec78ba002
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_sms_shadow_pd.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_stencil_color_black.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_stencil_color_black.bin
new file mode 100644
index 00000000000..5281abc6100
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_stencil_color_black.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_stencil_color_lightning.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_stencil_color_lightning.bin
new file mode 100644
index 00000000000..ec312f8a3d8
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_stencil_color_lightning.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_stencil_color_texture.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_stencil_color_texture.bin
new file mode 100644
index 00000000000..52de7234847
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_stencil_color_texture.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_stencil_texture.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_stencil_texture.bin
new file mode 100644
index 00000000000..e48079000cc
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_stencil_texture.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_stencil_texture_lightning.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_stencil_texture_lightning.bin
new file mode 100644
index 00000000000..b0f45e5b5b6
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_stencil_texture_lightning.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_tree.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_tree.bin
new file mode 100644
index 00000000000..c36a93d60b5
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_tree.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_update.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_update.bin
new file mode 100644
index 00000000000..6deeecafcd6
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_update.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_update_3d.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_update_3d.bin
new file mode 100644
index 00000000000..aa8f3cb2e9a
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_update_3d.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_update_cmp.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_update_cmp.bin
new file mode 100644
index 00000000000..0e9089a14d1
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_update_cmp.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_vectordisplay_blit.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_vectordisplay_blit.bin
new file mode 100644
index 00000000000..e1c858e537a
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_vectordisplay_blit.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_vectordisplay_blur.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_vectordisplay_blur.bin
new file mode 100644
index 00000000000..2b71fdb79b3
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_vectordisplay_blur.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/fs_vectordisplay_fb.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_vectordisplay_fb.bin
new file mode 100644
index 00000000000..ab9efb8dd6e
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/fs_vectordisplay_fb.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_bump.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_bump.bin
new file mode 100644
index 00000000000..7998ca70fb0
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_bump.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_bump_instanced.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_bump_instanced.bin
new file mode 100644
index 00000000000..7ed86a0fd2b
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_bump_instanced.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_callback.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_callback.bin
new file mode 100644
index 00000000000..f7f3092c847
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_callback.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_cubes.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_cubes.bin
new file mode 100644
index 00000000000..66262f6bc11
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_cubes.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_deferred_combine.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_deferred_combine.bin
new file mode 100644
index 00000000000..10fb2d926e2
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_deferred_combine.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_deferred_debug.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_deferred_debug.bin
new file mode 100644
index 00000000000..10fb2d926e2
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_deferred_debug.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_deferred_debug_line.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_deferred_debug_line.bin
new file mode 100644
index 00000000000..66262f6bc11
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_deferred_debug_line.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_deferred_geom.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_deferred_geom.bin
new file mode 100644
index 00000000000..7998ca70fb0
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_deferred_geom.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_deferred_light.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_deferred_light.bin
new file mode 100644
index 00000000000..10fb2d926e2
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_deferred_light.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_hdr_blur.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_hdr_blur.bin
new file mode 100644
index 00000000000..62e916b1c78
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_hdr_blur.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_hdr_bright.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_hdr_bright.bin
new file mode 100644
index 00000000000..10fb2d926e2
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_hdr_bright.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_hdr_lum.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_hdr_lum.bin
new file mode 100644
index 00000000000..10fb2d926e2
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_hdr_lum.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_hdr_lumavg.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_hdr_lumavg.bin
new file mode 100644
index 00000000000..10fb2d926e2
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_hdr_lumavg.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_hdr_mesh.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_hdr_mesh.bin
new file mode 100644
index 00000000000..172750107c5
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_hdr_mesh.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_hdr_skybox.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_hdr_skybox.bin
new file mode 100644
index 00000000000..10fb2d926e2
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_hdr_skybox.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_hdr_tonemap.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_hdr_tonemap.bin
new file mode 100644
index 00000000000..6fb9ab855e1
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_hdr_tonemap.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_ibl_mesh.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_ibl_mesh.bin
new file mode 100644
index 00000000000..c29d5680e10
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_ibl_mesh.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_ibl_skybox.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_ibl_skybox.bin
new file mode 100644
index 00000000000..ada939a9055
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_ibl_skybox.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_instancing.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_instancing.bin
new file mode 100644
index 00000000000..3201b941d1e
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_instancing.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_mesh.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_mesh.bin
new file mode 100644
index 00000000000..53f57d4439a
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_mesh.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_oit.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_oit.bin
new file mode 100644
index 00000000000..7dfd658840c
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_oit.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_oit_blit.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_oit_blit.bin
new file mode 100644
index 00000000000..10fb2d926e2
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_oit_blit.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_particle.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_particle.bin
new file mode 100644
index 00000000000..be331f304db
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_particle.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_raymarching.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_raymarching.bin
new file mode 100644
index 00000000000..38f1edfabd4
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_raymarching.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_color.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_color.bin
new file mode 100644
index 00000000000..cf6de8b45c3
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_color.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_color_lightning.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_color_lightning.bin
new file mode 100644
index 00000000000..9dcdb61b4ee
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_color_lightning.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_color_lightning_csm.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_color_lightning_csm.bin
new file mode 100644
index 00000000000..a143cfc02b8
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_color_lightning_csm.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_color_lightning_linear.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_color_lightning_linear.bin
new file mode 100644
index 00000000000..02994d2b8b6
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_color_lightning_linear.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_color_lightning_linear_csm.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_color_lightning_linear_csm.bin
new file mode 100644
index 00000000000..8b833673081
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_color_lightning_linear_csm.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_color_lightning_linear_omni.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_color_lightning_linear_omni.bin
new file mode 100644
index 00000000000..54785f92d0e
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_color_lightning_linear_omni.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_color_lightning_omni.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_color_lightning_omni.bin
new file mode 100644
index 00000000000..ac6332a27f3
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_color_lightning_omni.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_color_texture.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_color_texture.bin
new file mode 100644
index 00000000000..10fb2d926e2
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_color_texture.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_depth.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_depth.bin
new file mode 100644
index 00000000000..cf6de8b45c3
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_depth.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_hblur.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_hblur.bin
new file mode 100644
index 00000000000..49949ec67e8
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_hblur.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_packdepth.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_packdepth.bin
new file mode 100644
index 00000000000..1c1ec34d8c7
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_packdepth.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_packdepth_linear.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_packdepth_linear.bin
new file mode 100644
index 00000000000..a5471e7cb39
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_packdepth_linear.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_texture.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_texture.bin
new file mode 100644
index 00000000000..10fb2d926e2
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_texture.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_texture_lightning.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_texture_lightning.bin
new file mode 100644
index 00000000000..2e7362934bb
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_texture_lightning.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_unpackdepth.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_unpackdepth.bin
new file mode 100644
index 00000000000..10fb2d926e2
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_unpackdepth.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_vblur.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_vblur.bin
new file mode 100644
index 00000000000..123787fa57a
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowmaps_vblur.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowvolume_color_lightning.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowvolume_color_lightning.bin
new file mode 100644
index 00000000000..2e782b0cb4c
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowvolume_color_lightning.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowvolume_color_texture.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowvolume_color_texture.bin
new file mode 100644
index 00000000000..10fb2d926e2
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowvolume_color_texture.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowvolume_svback.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowvolume_svback.bin
new file mode 100644
index 00000000000..442d4977a71
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowvolume_svback.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowvolume_svfront.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowvolume_svfront.bin
new file mode 100644
index 00000000000..cf6de8b45c3
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowvolume_svfront.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowvolume_svside.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowvolume_svside.bin
new file mode 100644
index 00000000000..3b893600359
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowvolume_svside.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowvolume_texture.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowvolume_texture.bin
new file mode 100644
index 00000000000..10fb2d926e2
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowvolume_texture.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowvolume_texture_lightning.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowvolume_texture_lightning.bin
new file mode 100644
index 00000000000..2e7362934bb
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_shadowvolume_texture_lightning.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_sms_mesh.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_sms_mesh.bin
new file mode 100644
index 00000000000..51bac010fba
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_sms_mesh.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_sms_shadow.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_sms_shadow.bin
new file mode 100644
index 00000000000..cf6de8b45c3
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_sms_shadow.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_sms_shadow_pd.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_sms_shadow_pd.bin
new file mode 100644
index 00000000000..1c1ec34d8c7
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_sms_shadow_pd.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_stencil_color.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_stencil_color.bin
new file mode 100644
index 00000000000..cf6de8b45c3
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_stencil_color.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_stencil_color_lightning.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_stencil_color_lightning.bin
new file mode 100644
index 00000000000..2e782b0cb4c
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_stencil_color_lightning.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_stencil_color_texture.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_stencil_color_texture.bin
new file mode 100644
index 00000000000..10fb2d926e2
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_stencil_color_texture.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_stencil_texture.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_stencil_texture.bin
new file mode 100644
index 00000000000..10fb2d926e2
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_stencil_texture.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_stencil_texture_lightning.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_stencil_texture_lightning.bin
new file mode 100644
index 00000000000..2e7362934bb
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_stencil_texture_lightning.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_tree.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_tree.bin
new file mode 100644
index 00000000000..851e55ebc2e
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_tree.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_update.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_update.bin
new file mode 100644
index 00000000000..37e19eade16
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_update.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/shaders/metal/vs_vectordisplay_fb.bin b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_vectordisplay_fb.bin
new file mode 100644
index 00000000000..38f1edfabd4
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/shaders/metal/vs_vectordisplay_fb.bin
Binary files differ
diff --git a/3rdparty/bgfx/examples/runtime/tvos-info.plist b/3rdparty/bgfx/examples/runtime/tvos-info.plist
new file mode 100644
index 00000000000..4aa5d31f9ca
--- /dev/null
+++ b/3rdparty/bgfx/examples/runtime/tvos-info.plist
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>en</string>
+ <key>CFBundleExecutable</key>
+ <string>$(EXECUTABLE_NAME)</string>
+ <key>CFBundleIdentifier</key>
+ <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>$(PRODUCT_NAME)</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+ <key>LSRequiresIPhoneOS</key>
+ <true/>
+ <key>UIRequiredDeviceCapabilities</key>
+ <array>
+ <string>arm64</string>
+ </array>
+</dict>
+</plist>
diff --git a/3rdparty/bgfx/include/bgfx.h b/3rdparty/bgfx/include/bgfx/bgfx.h
index d84698a9cec..524953228c3 100644
--- a/3rdparty/bgfx/include/bgfx.h
+++ b/3rdparty/bgfx/include/bgfx/bgfx.h
@@ -10,7 +10,7 @@
#include <stdint.h> // uint32_t
#include <stdlib.h> // size_t
-#include "bgfxdefines.h"
+#include <bgfx/bgfxdefines.h>
///
#define BGFX_HANDLE(_name) \
@@ -200,6 +200,7 @@ namespace bgfx
RG32I,
RG32U,
RG32F,
+ RGB9E5F,
BGRA8,
RGBA8,
RGBA8I,
@@ -1503,32 +1504,32 @@ namespace bgfx
///
void destroyUniform(UniformHandle _handle);
- /// Set clear color palette value.
+ /// Set palette color value.
///
/// @param[in] _index Index into palette.
/// @param[in] _rgba Packed 32-bit RGBA value.
///
- /// @attention C99 equivalent is `bgfx_set_clear_color`.
+ /// @attention C99 equivalent is `bgfx_set_palette_color`.
///
- void setClearColor(uint8_t _index, uint32_t _rgba);
+ void setPaletteColor(uint8_t _index, uint32_t _rgba);
- /// Set clear color palette value.
+ /// Set palette color value.
///
/// @param[in] _index Index into palette.
/// @param[in] _r, _g, _b, _a RGBA floating point values.
///
- /// @attention C99 equivalent is `bgfx_set_clear_color`.
+ /// @attention C99 equivalent is `bgfx_set_palette_color`.
///
- void setClearColor(uint8_t _index, float _r, float _g, float _b, float _a);
+ void setPaletteColor(uint8_t _index, float _r, float _g, float _b, float _a);
- /// Set clear color palette value.
+ /// Set palette color value.
///
/// @param[in] _index Index into palette.
/// @param[in] _rgba RGBA floating point value.
///
- /// @attention C99 equivalent is `bgfx_set_clear_color`.
+ /// @attention C99 equivalent is `bgfx_set_palette_color`.
///
- void setClearColor(uint8_t _index, const float _rgba[4]);
+ void setPaletteColor(uint8_t _index, const float _rgba[4]);
/// Set view name.
///
diff --git a/3rdparty/bgfx/include/bgfxdefines.h b/3rdparty/bgfx/include/bgfx/bgfxdefines.h
index 459ce6a3956..b239be1cf88 100644
--- a/3rdparty/bgfx/include/bgfxdefines.h
+++ b/3rdparty/bgfx/include/bgfx/bgfxdefines.h
@@ -13,12 +13,12 @@
#define BGFX_STATE_DEPTH_TEST_LESS UINT64_C(0x0000000000000010) //!< Enable depth test, less.
#define BGFX_STATE_DEPTH_TEST_LEQUAL UINT64_C(0x0000000000000020) //!< Enable depth test, less equal.
-#define BGFX_STATE_DEPTH_TEST_EQUAL UINT64_C(0x0000000000000030) //!<
-#define BGFX_STATE_DEPTH_TEST_GEQUAL UINT64_C(0x0000000000000040) //!<
-#define BGFX_STATE_DEPTH_TEST_GREATER UINT64_C(0x0000000000000050) //!<
-#define BGFX_STATE_DEPTH_TEST_NOTEQUAL UINT64_C(0x0000000000000060) //!<
-#define BGFX_STATE_DEPTH_TEST_NEVER UINT64_C(0x0000000000000070) //!<
-#define BGFX_STATE_DEPTH_TEST_ALWAYS UINT64_C(0x0000000000000080) //!<
+#define BGFX_STATE_DEPTH_TEST_EQUAL UINT64_C(0x0000000000000030) //!< Enable depth test, equal.
+#define BGFX_STATE_DEPTH_TEST_GEQUAL UINT64_C(0x0000000000000040) //!< Enable depth test, greater equal.
+#define BGFX_STATE_DEPTH_TEST_GREATER UINT64_C(0x0000000000000050) //!< Enable depth test, greater.
+#define BGFX_STATE_DEPTH_TEST_NOTEQUAL UINT64_C(0x0000000000000060) //!< Enable depth test, not equal.
+#define BGFX_STATE_DEPTH_TEST_NEVER UINT64_C(0x0000000000000070) //!< Enable depth test, never.
+#define BGFX_STATE_DEPTH_TEST_ALWAYS UINT64_C(0x0000000000000080) //!< Enable depth test, always.
#define BGFX_STATE_DEPTH_TEST_SHIFT 4
#define BGFX_STATE_DEPTH_TEST_MASK UINT64_C(0x00000000000000f0) //!< Depth test state bit mask.
@@ -53,8 +53,9 @@
#define BGFX_STATE_CULL_SHIFT 36 //!< Culling mode bit shift.
#define BGFX_STATE_CULL_MASK UINT64_C(0x0000003000000000) //!< Culling mode bit mask.
-#define BGFX_STATE_ALPHA_REF_SHIFT 40 //!<
-#define BGFX_STATE_ALPHA_REF_MASK UINT64_C(0x0000ff0000000000) //!<
+/// See BGFX_STATE_ALPHA_REF(_ref) helper macro.
+#define BGFX_STATE_ALPHA_REF_SHIFT 40 //!< Alpha reference bit shift.
+#define BGFX_STATE_ALPHA_REF_MASK UINT64_C(0x0000ff0000000000) //!< Alpha reference bit mask.
#define BGFX_STATE_PT_TRISTRIP UINT64_C(0x0001000000000000) //!< Tristrip.
#define BGFX_STATE_PT_LINES UINT64_C(0x0002000000000000) //!< Lines.
@@ -63,17 +64,18 @@
#define BGFX_STATE_PT_SHIFT 48 //!< Primitive type bit shift.
#define BGFX_STATE_PT_MASK UINT64_C(0x0007000000000000) //!< Primitive type bit mask.
-#define BGFX_STATE_POINT_SIZE_SHIFT 52 //!<
-#define BGFX_STATE_POINT_SIZE_MASK UINT64_C(0x0ff0000000000000) //!<
+#define BGFX_STATE_POINT_SIZE_SHIFT 52 //!< Point size bit shift.
+#define BGFX_STATE_POINT_SIZE_MASK UINT64_C(0x0ff0000000000000) //!< Point size bit mask.
/// Enable MSAA write when writing into MSAA frame buffer. This flag is ignored when not writing into
/// MSAA frame buffer.
-#define BGFX_STATE_MSAA UINT64_C(0x1000000000000000) //!<
+#define BGFX_STATE_MSAA UINT64_C(0x1000000000000000) //!< Enable MSAA rasterization.
-#define BGFX_STATE_RESERVED_MASK UINT64_C(0xe000000000000000) //!<
+#define BGFX_STATE_RESERVED_MASK UINT64_C(0xe000000000000000) //!< Internal bits, do not use!
-#define BGFX_STATE_NONE UINT64_C(0x0000000000000000) //!<
-#define BGFX_STATE_MASK UINT64_C(0xffffffffffffffff) //!<
+/// See BGFX_STATE_POINT_SIZE(_size) helper macro.
+#define BGFX_STATE_NONE UINT64_C(0x0000000000000000) //!< No state.
+#define BGFX_STATE_MASK UINT64_C(0xffffffffffffffff) //!< State mask.
/// Default state is write to RGB, alpha, and depth with depth test less enabled, with clockwise
/// culling and MSAA (when writing into MSAA frame buffer, otherwise this flag is ignored).
@@ -248,9 +250,9 @@
#define BGFX_BUFFER_COMPUTE_TYPE_SHIFT 4 //!<
#define BGFX_BUFFER_COMPUTE_TYPE_MASK UINT16_C(0x0030) //!<
-#define BGFX_BUFFER_COMPUTE_READ UINT16_C(0x0100) //!<
-#define BGFX_BUFFER_COMPUTE_WRITE UINT16_C(0x0200) //!<
-#define BGFX_BUFFER_DRAW_INDIRECT UINT16_C(0x0400) //!<
+#define BGFX_BUFFER_COMPUTE_READ UINT16_C(0x0100) //!< Buffer will be read by shader.
+#define BGFX_BUFFER_COMPUTE_WRITE UINT16_C(0x0200) //!< Buffer will be used for writing.
+#define BGFX_BUFFER_DRAW_INDIRECT UINT16_C(0x0400) //!< Buffer will be used for storing draw indirect commands.
#define BGFX_BUFFER_ALLOW_RESIZE UINT16_C(0x0800) //!<
#define BGFX_BUFFER_INDEX32 UINT16_C(0x1000) //!<
@@ -308,8 +310,12 @@
#define BGFX_TEXTURE_COMPARE_MASK UINT32_C(0x000f0000) //!<
#define BGFX_TEXTURE_COMPUTE_WRITE UINT32_C(0x00100000) //!<
#define BGFX_TEXTURE_SRGB UINT32_C(0x00200000) //!<
-#define BGFX_TEXTURE_RESERVED_SHIFT 24 //!<
-#define BGFX_TEXTURE_RESERVED_MASK UINT32_C(0xff000000) //!<
+#define BGFX_TEXTURE_BORDER_COLOR_SHIFT 24 //!<
+#define BGFX_TEXTURE_BORDER_COLOR_MASK UINT32_C(0x0f000000) //!<
+#define BGFX_TEXTURE_RESERVED_SHIFT 28 //!<
+#define BGFX_TEXTURE_RESERVED_MASK UINT32_C(0xf0000000) //!<
+
+#define BGFX_TEXTURE_BORDER_COLOR(_index) ( (_index << BGFX_TEXTURE_BORDER_COLOR_SHIFT) & BGFX_TEXTURE_BORDER_COLOR_MASK)
#define BGFX_TEXTURE_SAMPLER_BITS_MASK (0 \
| BGFX_TEXTURE_U_MASK \
@@ -374,11 +380,11 @@
///
#define BGFX_VIEW_NONE UINT8_C(0x00) //!<
-#define BGFX_VIEW_STEREO UINT8_C(0x01) //!<
+#define BGFX_VIEW_STEREO UINT8_C(0x01) //!< View will be rendered in stereo mode.
///
-#define BGFX_SUBMIT_EYE_LEFT UINT8_C(0x01) //!<
-#define BGFX_SUBMIT_EYE_RIGHT UINT8_C(0x02) //!<
+#define BGFX_SUBMIT_EYE_LEFT UINT8_C(0x01) //!< Submit to left eye.
+#define BGFX_SUBMIT_EYE_RIGHT UINT8_C(0x02) //!< Submit to right eye.
#define BGFX_SUBMIT_EYE_MASK UINT8_C(0x03) //!<
#define BGFX_SUBMIT_EYE_FIRST BGFX_SUBMIT_EYE_LEFT
diff --git a/3rdparty/bgfx/include/bgfxplatform.h b/3rdparty/bgfx/include/bgfx/bgfxplatform.h
index 920904aa9fc..920904aa9fc 100644
--- a/3rdparty/bgfx/include/bgfxplatform.h
+++ b/3rdparty/bgfx/include/bgfx/bgfxplatform.h
diff --git a/3rdparty/bgfx/include/bgfx.c99.h b/3rdparty/bgfx/include/bgfx/c99/bgfx.h
index f2f49ffa543..b7aeecda3e7 100644
--- a/3rdparty/bgfx/include/bgfx.c99.h
+++ b/3rdparty/bgfx/include/bgfx/c99/bgfx.h
@@ -13,7 +13,7 @@
#include <stdint.h> // uint32_t
#include <stdlib.h> // size_t
-#include "bgfxdefines.h"
+#include <bgfx/bgfxdefines.h>
typedef enum bgfx_renderer_type
{
@@ -123,6 +123,7 @@ typedef enum bgfx_texture_format
BGFX_TEXTURE_FORMAT_RG32I,
BGFX_TEXTURE_FORMAT_RG32U,
BGFX_TEXTURE_FORMAT_RG32F,
+ BGFX_TEXTURE_FORMAT_RGB9E5F,
BGFX_TEXTURE_FORMAT_BGRA8,
BGFX_TEXTURE_FORMAT_RGBA8,
BGFX_TEXTURE_FORMAT_RGBA8I,
@@ -638,7 +639,7 @@ BGFX_C_API bgfx_uniform_handle_t bgfx_create_uniform(const char* _name, bgfx_uni
BGFX_C_API void bgfx_destroy_uniform(bgfx_uniform_handle_t _handle);
/**/
-BGFX_C_API void bgfx_set_clear_color(uint8_t _index, const float _rgba[4]);
+BGFX_C_API void bgfx_set_palette_color(uint8_t _index, const float _rgba[4]);
/**/
BGFX_C_API void bgfx_set_view_name(uint8_t _id, const char* _name);
diff --git a/3rdparty/bgfx/include/bgfxplatform.c99.h b/3rdparty/bgfx/include/bgfx/c99/bgfxplatform.h
index 31c65bd6fd0..31c65bd6fd0 100644
--- a/3rdparty/bgfx/include/bgfxplatform.c99.h
+++ b/3rdparty/bgfx/include/bgfx/c99/bgfxplatform.h
diff --git a/3rdparty/bgfx/scripts/bgfx.lua b/3rdparty/bgfx/scripts/bgfx.lua
index 8c196d5b7d6..c9658d35f84 100644
--- a/3rdparty/bgfx/scripts/bgfx.lua
+++ b/3rdparty/bgfx/scripts/bgfx.lua
@@ -69,11 +69,17 @@ function bgfxProject(_name, _kind, _defines)
"GLESv2",
}
- configuration { "winphone8* or winstore8*"}
+ configuration { "winphone8* or winstore8*" }
linkoptions {
"/ignore:4264" -- LNK4264: archiving object file compiled with /ZW into a static library; note that when authoring Windows Runtime types it is not recommended to link with a static library that contains Windows Runtime metadata
}
+ configuration { "*clang*" }
+ buildoptions {
+ "-Wno-microsoft-enum-value", -- enumerator value is not representable in the underlying type 'int'
+ "-Wno-microsoft-const-init", -- default initialization of an object of const type '' without a user-provided default constructor is a Microsoft extension
+ }
+
configuration { "osx" }
links {
"Cocoa.framework",
diff --git a/3rdparty/bgfx/scripts/example-common.lua b/3rdparty/bgfx/scripts/example-common.lua
index 5a5dd7ce0b7..98dad9afc31 100644
--- a/3rdparty/bgfx/scripts/example-common.lua
+++ b/3rdparty/bgfx/scripts/example-common.lua
@@ -61,7 +61,7 @@ project ("example-common")
}
end
- configuration { "osx or ios*" }
+ configuration { "osx or ios* or tvos*" }
files {
path.join(BGFX_DIR, "examples/common/**.mm"),
}
diff --git a/3rdparty/bgfx/scripts/genie.lua b/3rdparty/bgfx/scripts/genie.lua
index 90beb31a456..ce3e8d8e6d2 100644
--- a/3rdparty/bgfx/scripts/genie.lua
+++ b/3rdparty/bgfx/scripts/genie.lua
@@ -305,16 +305,19 @@ function exampleProject(_name)
}
configuration { "osx" }
- links {
- "Cocoa.framework",
- "OpenGL.framework",
+ linkoptions {
+ "-framework Cocoa",
+ "-framework Metal",
+ "-framework QuartzCore",
+ "-framework OpenGL",
}
- configuration { "ios*" }
+ configuration { "ios* or tvos*" }
kind "ConsoleApp"
linkoptions {
"-framework CoreFoundation",
"-framework Foundation",
+ "-framework Metal",
"-framework OpenGLES",
"-framework UIKit",
"-framework QuartzCore",
@@ -326,6 +329,12 @@ function exampleProject(_name)
path.join(BGFX_DIR, "examples/runtime/iOS-Info.plist"),
}
+ configuration { "xcode4", "tvos" }
+ kind "WindowedApp"
+ files {
+ path.join(BGFX_DIR, "examples/runtime/tvOS-Info.plist"),
+ }
+
configuration { "qnx*" }
targetextension ""
links {
diff --git a/3rdparty/bgfx/src/bgfx.cpp b/3rdparty/bgfx/src/bgfx.cpp
index c24d07ccec2..34d56ddbc65 100644
--- a/3rdparty/bgfx/src/bgfx.cpp
+++ b/3rdparty/bgfx/src/bgfx.cpp
@@ -9,7 +9,7 @@ namespace bgfx
{
#define BGFX_MAIN_THREAD_MAGIC UINT32_C(0x78666762)
-#if BGFX_CONFIG_MULTITHREADED && !BX_PLATFORM_OSX && !BX_PLATFORM_IOS
+#if BGFX_CONFIG_MULTITHREADED
# define BGFX_CHECK_MAIN_THREAD() \
BX_CHECK(NULL != s_ctx, "Library is not initialized yet."); \
BX_CHECK(BGFX_MAIN_THREAD_MAGIC == s_threadIndex, "Must be called from main thread.")
@@ -17,7 +17,7 @@ namespace bgfx
#else
# define BGFX_CHECK_MAIN_THREAD()
# define BGFX_CHECK_RENDER_THREAD()
-#endif // BGFX_CONFIG_MULTITHREADED && !BX_PLATFORM_OSX && !BX_PLATFORM_IOS
+#endif // BGFX_CONFIG_MULTITHREADED
#if BGFX_CONFIG_USE_TINYSTL
void* TinyStlAllocator::static_allocate(size_t _bytes)
@@ -42,8 +42,18 @@ namespace bgfx
virtual void traceVargs(const char* _filePath, uint16_t _line, const char* _format, va_list _argList) BX_OVERRIDE
{
- dbgPrintf("%s (%d): ", _filePath, _line);
- dbgPrintfVargs(_format, _argList);
+ char temp[2048];
+ char* out = temp;
+ int32_t len = bx::snprintf(out, sizeof(temp), "%s (%d): ", _filePath, _line);
+ int32_t total = len + bx::vsnprintf(out + len, sizeof(temp)-len, _format, _argList);
+ if ( (int32_t)sizeof(temp) < total)
+ {
+ out = (char*)alloca(total+1);
+ memcpy(out, temp, len);
+ bx::vsnprintf(out + len, total-len, _format, _argList);
+ }
+ out[total] = '\0';
+ bx::debugOutput(out);
}
virtual void fatal(Fatal::Enum _code, const char* _str) BX_OVERRIDE
@@ -200,7 +210,52 @@ namespace bgfx
Caps g_caps;
- static BX_THREAD uint32_t s_threadIndex = 0;
+#if BGFX_CONFIG_MULTITHREADED && !defined(BX_THREAD_LOCAL)
+ class ThreadData
+ {
+ BX_CLASS(ThreadData
+ , NO_COPY
+ , NO_ASSIGNMENT
+ );
+
+ public:
+ ThreadData(uintptr_t _rhs)
+ {
+ union { uintptr_t ui; void* ptr; } cast = { _rhs };
+ m_tls.set(cast.ptr);
+ }
+
+ operator uintptr_t() const
+ {
+ union { uintptr_t ui; void* ptr; } cast;
+ cast.ptr = m_tls.get();
+ return cast.ui;
+ }
+
+ uintptr_t operator=(uintptr_t _rhs)
+ {
+ union { uintptr_t ui; void* ptr; } cast = { _rhs };
+ m_tls.set(cast.ptr);
+ return _rhs;
+ }
+
+ bool operator==(uintptr_t _rhs) const
+ {
+ uintptr_t lhs = *this;
+ return lhs == _rhs;
+ }
+
+ private:
+ bx::TlsData m_tls;
+ };
+
+ static ThreadData s_threadIndex(0);
+#elif !BGFX_CONFIG_MULTITHREADED
+ static uint32_t s_threadIndex(0);
+#else
+ static BX_THREAD_LOCAL uint32_t s_threadIndex(0);
+#endif
+
static Context* s_ctx = NULL;
static bool s_renderFrameCalled = false;
PlatformData g_platformData;
@@ -722,7 +777,7 @@ namespace bgfx
return m_num;
}
- m_constEnd = m_constantBuffer->getPos();
+ m_uniformEnd = m_uniformBuffer->getPos();
m_key.m_program = invalidHandle == _handle.idx
? 0
@@ -739,14 +794,14 @@ namespace bgfx
m_sortValues[m_num] = m_numRenderItems;
++m_num;
- m_draw.m_constBegin = m_constBegin;
- m_draw.m_constEnd = m_constEnd;
+ m_draw.m_constBegin = m_uniformBegin;
+ m_draw.m_constEnd = m_uniformEnd;
m_draw.m_flags |= m_flags;
m_renderItem[m_numRenderItems].draw = m_draw;
++m_numRenderItems;
m_draw.clear();
- m_constBegin = m_constEnd;
+ m_uniformBegin = m_uniformEnd;
m_flags = BGFX_STATE_NONE;
return m_num;
@@ -766,7 +821,7 @@ namespace bgfx
return m_num;
}
- m_constEnd = m_constantBuffer->getPos();
+ m_uniformEnd = m_uniformBuffer->getPos();
m_compute.m_matrix = m_draw.m_matrix;
m_compute.m_num = m_draw.m_num;
@@ -786,13 +841,13 @@ namespace bgfx
m_sortValues[m_num] = m_numRenderItems;
++m_num;
- m_compute.m_constBegin = m_constBegin;
- m_compute.m_constEnd = m_constEnd;
+ m_compute.m_constBegin = m_uniformBegin;
+ m_compute.m_constEnd = m_uniformEnd;
m_renderItem[m_numRenderItems].compute = m_compute;
++m_numRenderItems;
m_compute.clear();
- m_constBegin = m_constEnd;
+ m_uniformBegin = m_uniformEnd;
return m_num;
}
@@ -844,21 +899,21 @@ namespace bgfx
1,
};
- void ConstantBuffer::writeUniform(UniformType::Enum _type, uint16_t _loc, const void* _value, uint16_t _num)
+ void UniformBuffer::writeUniform(UniformType::Enum _type, uint16_t _loc, const void* _value, uint16_t _num)
{
uint32_t opcode = encodeOpcode(_type, _loc, _num, true);
write(opcode);
write(_value, g_uniformTypeSize[_type]*_num);
}
- void ConstantBuffer::writeUniformHandle(UniformType::Enum _type, uint16_t _loc, UniformHandle _handle, uint16_t _num)
+ void UniformBuffer::writeUniformHandle(UniformType::Enum _type, uint16_t _loc, UniformHandle _handle, uint16_t _num)
{
uint32_t opcode = encodeOpcode(_type, _loc, _num, false);
write(opcode);
write(&_handle, sizeof(UniformHandle) );
}
- void ConstantBuffer::writeMarker(const char* _marker)
+ void UniformBuffer::writeMarker(const char* _marker)
{
uint16_t num = (uint16_t)strlen(_marker)+1;
uint32_t opcode = encodeOpcode(bgfx::UniformType::Count, 0, num, true);
@@ -977,7 +1032,6 @@ namespace bgfx
// should not be created.
BX_TRACE("Application called bgfx::renderFrame directly, not creating render thread.");
m_singleThreaded = true
- && !BX_ENABLED(BX_PLATFORM_OSX || BX_PLATFORM_IOS)
&& ~BGFX_MAIN_THREAD_MAGIC == s_threadIndex
;
}
@@ -1243,10 +1297,10 @@ namespace bgfx
memcpy(m_submit->m_view, m_view, sizeof(m_view) );
memcpy(m_submit->m_proj, m_proj, sizeof(m_proj) );
memcpy(m_submit->m_viewFlags, m_viewFlags, sizeof(m_viewFlags) );
- if (m_clearColorDirty > 0)
+ if (m_colorPaletteDirty > 0)
{
- --m_clearColorDirty;
- memcpy(m_submit->m_clearColor, m_clearColor, sizeof(m_clearColor) );
+ --m_colorPaletteDirty;
+ memcpy(m_submit->m_colorPalette, m_clearColor, sizeof(m_clearColor) );
}
m_submit->finish();
@@ -1271,6 +1325,19 @@ namespace bgfx
);
}
+ const char* Context::getName(UniformHandle _handle) const
+ {
+ for (UniformHashMap::const_iterator it = m_uniformHashMap.begin(), itEnd = m_uniformHashMap.end(); it != itEnd; ++it)
+ {
+ if (it->second.idx == _handle.idx)
+ {
+ return it->first.c_str();
+ }
+ }
+
+ return NULL;
+ }
+
bool Context::renderFrame()
{
if (m_rendererInitialized
@@ -1299,12 +1366,12 @@ namespace bgfx
return m_exit;
}
- void rendererUpdateUniforms(RendererContextI* _renderCtx, ConstantBuffer* _constantBuffer, uint32_t _begin, uint32_t _end)
+ void rendererUpdateUniforms(RendererContextI* _renderCtx, UniformBuffer* _uniformBuffer, uint32_t _begin, uint32_t _end)
{
- _constantBuffer->reset(_begin);
- while (_constantBuffer->getPos() < _end)
+ _uniformBuffer->reset(_begin);
+ while (_uniformBuffer->getPos() < _end)
{
- uint32_t opcode = _constantBuffer->read();
+ uint32_t opcode = _uniformBuffer->read();
if (UniformType::End == opcode)
{
@@ -1315,10 +1382,10 @@ namespace bgfx
uint16_t loc;
uint16_t num;
uint16_t copy;
- ConstantBuffer::decodeOpcode(opcode, type, loc, num, copy);
+ UniformBuffer::decodeOpcode(opcode, type, loc, num, copy);
uint32_t size = g_uniformTypeSize[type]*num;
- const char* data = _constantBuffer->read(size);
+ const char* data = _uniformBuffer->read(size);
if (UniformType::Count > type)
{
if (copy)
@@ -1496,11 +1563,7 @@ again:
if (windowsVersionIs(Condition::GreaterEqual, 0x0602) )
{
-#if defined(__MINGW32__)
- first = RendererType::Direct3D11;
-#else
first = RendererType::Direct3D12;
-#endif // __MINGW32__
second = RendererType::Direct3D11;
if (!s_rendererCreator[second].supported)
{
@@ -1568,6 +1631,13 @@ again:
}
else
{
+#if 0
+ if (s_rendererCreator[RendererType::Metal].supported)
+ {
+ _type = RendererType::Metal;
+ }
+ else
+#endif // 0
if (s_rendererCreator[RendererType::OpenGL].supported)
{
_type = RendererType::OpenGL;
@@ -2635,8 +2705,8 @@ again:
if (BackbufferRatio::Count != _ratio)
{
- _width = uint16_t(s_ctx->m_frame->m_resolution.m_width);
- _height = uint16_t(s_ctx->m_frame->m_resolution.m_height);
+ _width = uint16_t(s_ctx->m_resolution.m_width);
+ _height = uint16_t(s_ctx->m_resolution.m_height);
getTextureSizeFromRatio(_ratio, _width, _height);
}
@@ -2852,7 +2922,7 @@ again:
s_ctx->destroyUniform(_handle);
}
- void setClearColor(uint8_t _index, uint32_t _rgba)
+ void setPaletteColor(uint8_t _index, uint32_t _rgba)
{
BGFX_CHECK_MAIN_THREAD();
@@ -2868,20 +2938,20 @@ again:
bb * 1.0f/255.0f,
aa * 1.0f/255.0f,
};
- s_ctx->setClearColor(_index, rgba);
+ s_ctx->setPaletteColor(_index, rgba);
}
- void setClearColor(uint8_t _index, float _r, float _g, float _b, float _a)
+ void setPaletteColor(uint8_t _index, float _r, float _g, float _b, float _a)
{
BGFX_CHECK_MAIN_THREAD();
float rgba[4] = { _r, _g, _b, _a };
- s_ctx->setClearColor(_index, rgba);
+ s_ctx->setPaletteColor(_index, rgba);
}
- void setClearColor(uint8_t _index, const float _rgba[4])
+ void setPaletteColor(uint8_t _index, const float _rgba[4])
{
BGFX_CHECK_MAIN_THREAD();
- s_ctx->setClearColor(_index, _rgba);
+ s_ctx->setPaletteColor(_index, _rgba);
}
bool checkView(uint8_t _id)
@@ -3178,8 +3248,8 @@ again:
}
} // namespace bgfx
-#include <bgfx.c99.h>
-#include <bgfxplatform.c99.h>
+#include <bgfx/c99/bgfx.h>
+#include <bgfx/c99/bgfxplatform.h>
BX_STATIC_ASSERT(bgfx::Fatal::Count == bgfx::Fatal::Enum(BGFX_FATAL_COUNT) );
BX_STATIC_ASSERT(bgfx::RendererType::Count == bgfx::RendererType::Enum(BGFX_RENDERER_TYPE_COUNT) );
@@ -3742,9 +3812,9 @@ BGFX_C_API void bgfx_destroy_uniform(bgfx_uniform_handle_t _handle)
bgfx::destroyUniform(handle.cpp);
}
-BGFX_C_API void bgfx_set_clear_color(uint8_t _index, const float _rgba[4])
+BGFX_C_API void bgfx_set_palette_color(uint8_t _index, const float _rgba[4])
{
- bgfx::setClearColor(_index, _rgba);
+ bgfx::setPaletteColor(_index, _rgba);
}
BGFX_C_API void bgfx_set_view_name(uint8_t _id, const char* _name)
diff --git a/3rdparty/bgfx/src/bgfx_p.h b/3rdparty/bgfx/src/bgfx_p.h
index b98fee1e48a..b7bbcf676b5 100644
--- a/3rdparty/bgfx/src/bgfx_p.h
+++ b/3rdparty/bgfx/src/bgfx_p.h
@@ -19,7 +19,7 @@
# define BX_CONFIG_ALLOCATOR_DEBUG 1
#endif // BGFX_CONFIG_DEBUG
-#include "bgfx.h"
+#include <bgfx/bgfx.h>
#include "config.h"
#include <inttypes.h>
@@ -108,7 +108,7 @@ namespace bgfx
#include <bx/string.h>
#include <bx/os.h>
-#include "bgfxplatform.h"
+#include <bgfx/bgfxplatform.h>
#include "image.h"
#define BGFX_CHUNK_MAGIC_CSH BX_MAKEFOURCC('C', 'S', 'H', 0x2)
@@ -314,6 +314,14 @@ namespace bgfx
return uint32_t( (_stencil >> (32*_0or1) ) );
}
+ inline bool needBorderColor(uint32_t _flags)
+ {
+ return BGFX_TEXTURE_U_BORDER == (_flags & BGFX_TEXTURE_U_BORDER)
+ || BGFX_TEXTURE_V_BORDER == (_flags & BGFX_TEXTURE_V_BORDER)
+ || BGFX_TEXTURE_W_BORDER == (_flags & BGFX_TEXTURE_W_BORDER)
+ ;
+ }
+
void dump(const VertexDecl& _decl);
struct TextVideoMem
@@ -861,20 +869,31 @@ namespace bgfx
#define BGFX_UNIFORM_SAMPLERBIT UINT8_C(0x20)
#define BGFX_UNIFORM_MASK (BGFX_UNIFORM_FRAGMENTBIT|BGFX_UNIFORM_SAMPLERBIT)
- class ConstantBuffer
+ class UniformBuffer
{
public:
- static ConstantBuffer* create(uint32_t _size)
+ static UniformBuffer* create(uint32_t _size = 1<<20)
{
- uint32_t size = BX_ALIGN_16(bx::uint32_max(_size, sizeof(ConstantBuffer) ) );
- void* data = BX_ALLOC(g_allocator, size);
- return ::new(data) ConstantBuffer(_size);
+ uint32_t size = BX_ALIGN_16(bx::uint32_max(_size, sizeof(UniformBuffer) ) );
+ void* data = BX_ALLOC(g_allocator, size);
+ return ::new(data) UniformBuffer(_size);
}
- static void destroy(ConstantBuffer* _constantBuffer)
+ static void destroy(UniformBuffer* _uniformBuffer)
{
- _constantBuffer->~ConstantBuffer();
- BX_FREE(g_allocator, _constantBuffer);
+ _uniformBuffer->~UniformBuffer();
+ BX_FREE(g_allocator, _uniformBuffer);
+ }
+
+ static void update(UniformBuffer*& _uniformBuffer, uint32_t _treshold = 64<<10, uint32_t _grow = 1<<20)
+ {
+ if (_treshold >= _uniformBuffer->m_size - _uniformBuffer->m_pos)
+ {
+ uint32_t size = BX_ALIGN_16(bx::uint32_max(_uniformBuffer->m_size + _grow, sizeof(UniformBuffer) ) );
+ void* data = BX_REALLOC(g_allocator, _uniformBuffer, size);
+ _uniformBuffer = reinterpret_cast<UniformBuffer*>(data);
+ _uniformBuffer->m_size = size;
+ }
}
static uint32_t encodeOpcode(UniformType::Enum _type, uint16_t _loc, uint16_t _num, uint16_t _copy)
@@ -956,14 +975,14 @@ namespace bgfx
void writeMarker(const char* _marker);
private:
- ConstantBuffer(uint32_t _size)
+ UniformBuffer(uint32_t _size)
: m_size(_size-sizeof(m_buffer) )
, m_pos(0)
{
finish();
}
- ~ConstantBuffer()
+ ~UniformBuffer()
{
}
@@ -1208,9 +1227,10 @@ namespace bgfx
BX_ALIGN_DECL_CACHE_LINE(struct) Frame
{
Frame()
- : m_hmdInitialized(false)
+ : m_uniformMax(0)
, m_waitSubmit(0)
, m_waitRender(0)
+ , m_hmdInitialized(false)
{
SortKey term;
term.reset();
@@ -1225,7 +1245,7 @@ namespace bgfx
void create()
{
- m_constantBuffer = ConstantBuffer::create(BGFX_CONFIG_MAX_CONSTANT_BUFFER_SIZE);
+ m_uniformBuffer = UniformBuffer::create();
reset();
start();
m_textVideoMem = BX_NEW(g_allocator, TextVideoMem);
@@ -1233,7 +1253,7 @@ namespace bgfx
void destroy()
{
- ConstantBuffer::destroy(m_constantBuffer);
+ UniformBuffer::destroy(m_uniformBuffer);
BX_DELETE(g_allocator, m_textVideoMem);
}
@@ -1247,8 +1267,8 @@ namespace bgfx
void start()
{
m_flags = BGFX_STATE_NONE;
- m_constBegin = 0;
- m_constEnd = 0;
+ m_uniformBegin = 0;
+ m_uniformEnd = 0;
m_draw.clear();
m_compute.clear();
m_matrixCache.reset();
@@ -1261,7 +1281,7 @@ namespace bgfx
m_vboffset = 0;
m_cmdPre.start();
m_cmdPost.start();
- m_constantBuffer->reset();
+ m_uniformBuffer->reset();
m_discard = false;
}
@@ -1270,7 +1290,8 @@ namespace bgfx
m_cmdPre.finish();
m_cmdPost.finish();
- m_constantBuffer->finish();
+ m_uniformMax = bx::uint32_max(m_uniformMax, m_uniformBuffer->getPos() );
+ m_uniformBuffer->finish();
if (0 < m_numDropped)
{
@@ -1284,7 +1305,7 @@ namespace bgfx
void setMarker(const char* _name)
{
- m_constantBuffer->writeMarker(_name);
+ m_uniformBuffer->writeMarker(_name);
}
void setState(uint64_t _state, uint32_t _rgba)
@@ -1520,7 +1541,8 @@ namespace bgfx
void writeUniform(UniformType::Enum _type, UniformHandle _handle, const void* _value, uint16_t _num)
{
- m_constantBuffer->writeUniform(_type, _handle.idx, _value, _num);
+ UniformBuffer::update(m_uniformBuffer);
+ m_uniformBuffer->writeUniform(_type, _handle.idx, _value, _num);
}
void free(IndexBufferHandle _handle)
@@ -1588,7 +1610,7 @@ namespace bgfx
uint8_t m_viewRemap[BGFX_CONFIG_MAX_VIEWS];
FrameBufferHandle m_fb[BGFX_CONFIG_MAX_VIEWS];
Clear m_clear[BGFX_CONFIG_MAX_VIEWS];
- float m_clearColor[BGFX_CONFIG_MAX_CLEAR_COLOR_PALETTE][4];
+ float m_colorPalette[BGFX_CONFIG_MAX_COLOR_PALETTE][4];
Rect m_rect[BGFX_CONFIG_MAX_VIEWS];
Rect m_scissor[BGFX_CONFIG_MAX_VIEWS];
Matrix4 m_view[BGFX_CONFIG_MAX_VIEWS];
@@ -1601,10 +1623,11 @@ namespace bgfx
RenderDraw m_draw;
RenderCompute m_compute;
uint64_t m_flags;
- uint32_t m_constBegin;
- uint32_t m_constEnd;
+ uint32_t m_uniformBegin;
+ uint32_t m_uniformEnd;
+ uint32_t m_uniformMax;
- ConstantBuffer* m_constantBuffer;
+ UniformBuffer* m_uniformBuffer;
RenderItemCount m_num;
RenderItemCount m_numRenderItems;
@@ -1645,11 +1668,11 @@ namespace bgfx
TextVideoMem* m_textVideoMem;
HMD m_hmd;
Stats m_perfStats;
- bool m_hmdInitialized;
int64_t m_waitSubmit;
int64_t m_waitRender;
+ bool m_hmdInitialized;
bool m_discard;
};
@@ -1887,7 +1910,7 @@ namespace bgfx
{
}
- void rendererUpdateUniforms(RendererContextI* _renderCtx, ConstantBuffer* _constantBuffer, uint32_t _begin, uint32_t _end);
+ void rendererUpdateUniforms(RendererContextI* _renderCtx, UniformBuffer* _uniformBuffer, uint32_t _begin, uint32_t _end);
#if BGFX_CONFIG_DEBUG
# define BGFX_API_FUNC(_func) BX_NO_INLINE _func
@@ -1902,7 +1925,7 @@ namespace bgfx
, m_submit(&m_frame[BGFX_CONFIG_MULTITHREADED ? 1 : 0])
, m_numFreeDynamicIndexBufferHandles(0)
, m_numFreeDynamicVertexBufferHandles(0)
- , m_clearColorDirty(0)
+ , m_colorPaletteDirty(0)
, m_instBufferCount(0)
, m_frames(0)
, m_debug(BGFX_DEBUG_NONE)
@@ -2927,7 +2950,7 @@ namespace bgfx
, _handle.idx
, _width
, _height
- , getName(TextureFormat::Enum(textureRef.m_format) )
+ , bgfx::getName(TextureFormat::Enum(textureRef.m_format) )
);
CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::ResizeTexture);
@@ -3164,14 +3187,14 @@ namespace bgfx
cmdbuf.write(_filePath, len);
}
- BGFX_API_FUNC(void setClearColor(uint8_t _index, const float _rgba[4]) )
+ BGFX_API_FUNC(void setPaletteColor(uint8_t _index, const float _rgba[4]) )
{
- BX_CHECK(_index < BGFX_CONFIG_MAX_CLEAR_COLOR_PALETTE, "Clear color palette index out of bounds %d (max: %d)."
+ BX_CHECK(_index < BGFX_CONFIG_MAX_COLOR_PALETTE, "Color palette index out of bounds %d (max: %d)."
, _index
- , BGFX_CONFIG_MAX_CLEAR_COLOR_PALETTE
+ , BGFX_CONFIG_MAX_COLOR_PALETTE
);
memcpy(&m_clearColor[_index][0], _rgba, 16);
- m_clearColorDirty = 2;
+ m_colorPaletteDirty = 2;
}
BGFX_API_FUNC(void setViewName(uint8_t _id, const char* _name) )
@@ -3336,6 +3359,15 @@ namespace bgfx
BGFX_CHECK_HANDLE("setUniform", m_uniformHandle, _handle);
UniformRef& uniform = m_uniformRef[_handle.idx];
BX_CHECK(uniform.m_num >= _num, "Truncated uniform update. %d (max: %d)", _num, uniform.m_num);
+ if (BX_ENABLED(BGFX_CONFIG_DEBUG_UNIFORM) )
+ {
+ BX_CHECK(m_uniformSet.end() == m_uniformSet.find(_handle.idx)
+ , "Uniform %d (%s) was already set for this draw call."
+ , _handle.idx
+ , getName(_handle)
+ );
+ m_uniformSet.insert(_handle.idx);
+ }
m_submit->writeUniform(uniform.m_type, _handle, _value, bx::uint16_min(uniform.m_num, _num) );
}
@@ -3353,6 +3385,7 @@ namespace bgfx
BGFX_API_FUNC(void setIndexBuffer(const TransientIndexBuffer* _tib, uint32_t _firstIndex, uint32_t _numIndices) )
{
+ BGFX_CHECK_HANDLE("setIndexBuffer", m_indexBufferHandle, _tib->handle);
m_submit->setIndexBuffer(_tib, _firstIndex, _numIndices);
}
@@ -3370,6 +3403,7 @@ namespace bgfx
BGFX_API_FUNC(void setVertexBuffer(const TransientVertexBuffer* _tvb, uint32_t _startVertex, uint32_t _numVertices) )
{
+ BGFX_CHECK_HANDLE("setVertexBuffer", m_vertexBufferHandle, _tvb->handle);
m_submit->setVertexBuffer(_tvb, _startVertex, _numVertices);
}
@@ -3423,6 +3457,10 @@ namespace bgfx
BGFX_API_FUNC(uint32_t submit(uint8_t _id, ProgramHandle _handle, int32_t _depth) )
{
BGFX_CHECK_HANDLE_INVALID_OK("submit", m_programHandle, _handle);
+ if (BX_ENABLED(BGFX_CONFIG_DEBUG_UNIFORM) )
+ {
+ m_uniformSet.clear();
+ }
return m_submit->submit(_id, _handle, _depth);
}
@@ -3430,6 +3468,10 @@ namespace bgfx
{
BGFX_CHECK_HANDLE_INVALID_OK("submit", m_programHandle, _handle);
BGFX_CHECK_HANDLE("submit", m_vertexBufferHandle, _indirectHandle);
+ if (BX_ENABLED(BGFX_CONFIG_DEBUG_UNIFORM) )
+ {
+ m_uniformSet.clear();
+ }
return m_submit->submit(_id, _handle, _indirectHandle, _start, _num, _depth);
}
@@ -3492,16 +3534,28 @@ namespace bgfx
BGFX_API_FUNC(uint32_t dispatch(uint8_t _id, ProgramHandle _handle, uint16_t _numX, uint16_t _numY, uint16_t _numZ, uint8_t _flags) )
{
+ if (BX_ENABLED(BGFX_CONFIG_DEBUG_UNIFORM) )
+ {
+ m_uniformSet.clear();
+ }
return m_submit->dispatch(_id, _handle, _numX, _numY, _numZ, _flags);
}
BGFX_API_FUNC(uint32_t dispatch(uint8_t _id, ProgramHandle _handle, IndirectBufferHandle _indirectHandle, uint16_t _start, uint16_t _num, uint8_t _flags) )
{
+ if (BX_ENABLED(BGFX_CONFIG_DEBUG_UNIFORM) )
+ {
+ m_uniformSet.clear();
+ }
return m_submit->dispatch(_id, _handle, _indirectHandle, _start, _num, _flags);
}
BGFX_API_FUNC(void discard() )
{
+ if (BX_ENABLED(BGFX_CONFIG_DEBUG_UNIFORM) )
+ {
+ m_uniformSet.clear();
+ }
m_submit->discard();
}
@@ -3512,6 +3566,7 @@ namespace bgfx
void freeAllHandles(Frame* _frame);
void frameNoRenderWait();
void swap();
+ const char* getName(UniformHandle _handle) const;
// render thread
bool renderFrame();
@@ -3653,6 +3708,8 @@ namespace bgfx
typedef stl::unordered_map<stl::string, UniformHandle> UniformHashMap;
UniformHashMap m_uniformHashMap;
+ typedef stl::unordered_set<uint16_t> UniformSet;
+ UniformSet m_uniformSet;
UniformRef m_uniformRef[BGFX_CONFIG_MAX_UNIFORMS];
ShaderRef m_shaderRef[BGFX_CONFIG_MAX_SHADERS];
@@ -3669,7 +3726,7 @@ namespace bgfx
FrameBufferHandle m_fb[BGFX_CONFIG_MAX_VIEWS];
Clear m_clear[BGFX_CONFIG_MAX_VIEWS];
- float m_clearColor[BGFX_CONFIG_MAX_CLEAR_COLOR_PALETTE][4];
+ float m_clearColor[BGFX_CONFIG_MAX_COLOR_PALETTE][4];
Rect m_rect[BGFX_CONFIG_MAX_VIEWS];
Rect m_scissor[BGFX_CONFIG_MAX_VIEWS];
Matrix4 m_view[BGFX_CONFIG_MAX_VIEWS];
@@ -3678,7 +3735,7 @@ namespace bgfx
uint16_t m_seq[BGFX_CONFIG_MAX_VIEWS];
uint16_t m_seqMask[BGFX_CONFIG_MAX_VIEWS];
- uint8_t m_clearColorDirty;
+ uint8_t m_colorPaletteDirty;
Resolution m_resolution;
int32_t m_instBufferCount;
diff --git a/3rdparty/bgfx/src/config.h b/3rdparty/bgfx/src/config.h
index 61ed7f6a4c8..7aecc9b064b 100644
--- a/3rdparty/bgfx/src/config.h
+++ b/3rdparty/bgfx/src/config.h
@@ -41,10 +41,10 @@
? 1 : 0)
# endif // BGFX_CONFIG_RENDERER_DIRECT3D12
- //TODO: should check if iOS8 or greater
# ifndef BGFX_CONFIG_RENDERER_METAL
# define BGFX_CONFIG_RENDERER_METAL (0 \
|| BX_PLATFORM_IOS \
+ || BX_PLATFORM_OSX \
? 1 : 0)
# endif // BGFX_CONFIG_RENDERER_METAL
@@ -164,6 +164,11 @@
# define BGFX_CONFIG_DEBUG_MTL BGFX_CONFIG_DEBUG
#endif // BGFX_CONFIG_DEBUG_MTL
+///
+#ifndef BGFX_CONFIG_DEBUG_UNIFORM
+# define BGFX_CONFIG_DEBUG_UNIFORM BGFX_CONFIG_DEBUG
+#endif // BGFX_CONFIG_DEBUG_UNIFORM
+
#ifndef BGFX_CONFIG_MULTITHREADED
# define BGFX_CONFIG_MULTITHREADED ( (!BGFX_CONFIG_RENDERER_NULL)&&(0 \
|| BX_PLATFORM_ANDROID \
@@ -258,7 +263,7 @@
#ifndef BGFX_CONFIG_MAX_UNIFORMS
# define BGFX_CONFIG_MAX_UNIFORMS 512
-#endif // BGFX_CONFIG_MAX_CONSTANTS
+#endif // BGFX_CONFIG_MAX_UNIFORMS
#ifndef BGFX_CONFIG_MAX_COMMAND_BUFFER_SIZE
# define BGFX_CONFIG_MAX_COMMAND_BUFFER_SIZE (64<<10)
@@ -272,16 +277,12 @@
# define BGFX_CONFIG_TRANSIENT_INDEX_BUFFER_SIZE (2<<20)
#endif // BGFX_CONFIG_TRANSIENT_INDEX_BUFFER_SIZE
-#ifndef BGFX_CONFIG_MAX_CONSTANT_BUFFER_SIZE
-# define BGFX_CONFIG_MAX_CONSTANT_BUFFER_SIZE (1<<20)
-#endif // BGFX_CONFIG_MAX_CONSTANT_BUFFER_SIZE
-
#ifndef BGFX_CONFIG_MAX_INSTANCE_DATA_COUNT
# define BGFX_CONFIG_MAX_INSTANCE_DATA_COUNT 5
#endif // BGFX_CONFIG_MAX_INSTANCE_DATA_COUNT
#ifndef BGFX_CONFIG_MAX_CLEAR_COLOR_PALETTE
-# define BGFX_CONFIG_MAX_CLEAR_COLOR_PALETTE 16
+# define BGFX_CONFIG_MAX_COLOR_PALETTE 16
#endif // BGFX_CONFIG_MAX_CLEAR_COLOR_PALETTE
#define BGFX_CONFIG_DRAW_INDIRECT_STRIDE 32
diff --git a/3rdparty/bgfx/src/glcontext_ppapi.cpp b/3rdparty/bgfx/src/glcontext_ppapi.cpp
index bdbb50680b2..fb17a11ff5c 100644
--- a/3rdparty/bgfx/src/glcontext_ppapi.cpp
+++ b/3rdparty/bgfx/src/glcontext_ppapi.cpp
@@ -6,7 +6,7 @@
#include "bgfx_p.h"
#if BX_PLATFORM_NACL && (BGFX_CONFIG_RENDERER_OPENGLES || BGFX_CONFIG_RENDERER_OPENGL)
-# include <bgfxplatform.h>
+# include <bgfx/bgfxplatform.h>
# include "renderer_gl.h"
namespace bgfx { namespace gl
diff --git a/3rdparty/bgfx/src/glimports.h b/3rdparty/bgfx/src/glimports.h
index 2215357b84a..42f966ece35 100644
--- a/3rdparty/bgfx/src/glimports.h
+++ b/3rdparty/bgfx/src/glimports.h
@@ -439,6 +439,8 @@ GL_IMPORT______(true, PFNGLPUSHGROUPMARKEREXTPROC, glPushGroupMa
GL_IMPORT______(true, PFNGLPOPGROUPMARKEREXTPROC, glPopGroupMarker);
#else
GL_IMPORT______(true, PFNGLVERTEXATTRIBIPOINTERPROC, glVertexAttribIPointer);
+GL_IMPORT______(true, PFNGLGETINTERNALFORMATIVPROC, glGetInternalformativ);
+GL_IMPORT______(true, PFNGLGETINTERNALFORMATI64VPROC, glGetInternalformati64v);
#endif // BGFX_USE_GL_DYNAMIC_LIB
GL_IMPORT______(true, PFNGLSTRINGMARKERGREMEDYPROC, glStringMarkerGREMEDY);
@@ -454,9 +456,6 @@ GL_IMPORT_KHR__(true, PFNGLDEBUGMESSAGEINSERTPROC, glDebugMessag
GL_IMPORT_KHR__(true, PFNGLDEBUGMESSAGECALLBACKPROC, glDebugMessageCallback);
GL_IMPORT_KHR__(true, PFNGLGETDEBUGMESSAGELOGPROC, glGetDebugMessageLog);
-GL_IMPORT______(true, PFNGLGETINTERNALFORMATIVPROC, glGetInternalformativ);
-GL_IMPORT______(true, PFNGLGETINTERNALFORMATI64VPROC, glGetInternalformati64v);
-
# if BGFX_CONFIG_RENDERER_OPENGLES < 30
GL_IMPORT_OES__(true, PFNGLTEXIMAGE3DPROC, glTexImage3D);
GL_IMPORT_OES__(true, PFNGLTEXSUBIMAGE3DPROC, glTexSubImage3D);
diff --git a/3rdparty/bgfx/src/image.cpp b/3rdparty/bgfx/src/image.cpp
index 4db41e096d0..8a9ea639336 100644
--- a/3rdparty/bgfx/src/image.cpp
+++ b/3rdparty/bgfx/src/image.cpp
@@ -66,6 +66,7 @@ namespace bgfx
{ 64, 1, 1, 8, 1, 1, 0, 0, uint8_t(EncodingType::Int ) }, // RG32I
{ 64, 1, 1, 8, 1, 1, 0, 0, uint8_t(EncodingType::Uint ) }, // RG32U
{ 64, 1, 1, 8, 1, 1, 0, 0, uint8_t(EncodingType::Float) }, // RG32F
+ { 32, 1, 1, 4, 1, 1, 0, 0, uint8_t(EncodingType::Float) }, // RGB9E5F
{ 32, 1, 1, 4, 1, 1, 0, 0, uint8_t(EncodingType::Unorm) }, // BGRA8
{ 32, 1, 1, 4, 1, 1, 0, 0, uint8_t(EncodingType::Unorm) }, // RGBA8
{ 32, 1, 1, 4, 1, 1, 0, 0, uint8_t(EncodingType::Int ) }, // RGBA8I
@@ -142,6 +143,7 @@ namespace bgfx
"RG32I", // RG32I
"RG32U", // RG32U
"RG32F", // RG32F
+ "RGB9E5", // RGB9E5F
"BGRA8", // BGRA8
"RGBA8", // RGBA8
"RGBA8I", // RGBA8I
diff --git a/3rdparty/bgfx/src/renderdoc.cpp b/3rdparty/bgfx/src/renderdoc.cpp
index b7d66e37e35..ac2e2917fa6 100644
--- a/3rdparty/bgfx/src/renderdoc.cpp
+++ b/3rdparty/bgfx/src/renderdoc.cpp
@@ -55,27 +55,8 @@ namespace bgfx
return false;
}
-#define RENDERDOC_IMPORT \
- RENDERDOC_IMPORT_FUNC(RENDERDOC_Shutdown); \
- RENDERDOC_IMPORT_FUNC(RENDERDOC_SetLogFile); \
- RENDERDOC_IMPORT_FUNC(RENDERDOC_GetCapture); \
- RENDERDOC_IMPORT_FUNC(RENDERDOC_SetCaptureOptions); \
- RENDERDOC_IMPORT_FUNC(RENDERDOC_SetActiveWindow); \
- RENDERDOC_IMPORT_FUNC(RENDERDOC_TriggerCapture); \
- RENDERDOC_IMPORT_FUNC(RENDERDOC_StartFrameCapture); \
- RENDERDOC_IMPORT_FUNC(RENDERDOC_EndFrameCapture); \
- RENDERDOC_IMPORT_FUNC(RENDERDOC_GetOverlayBits); \
- RENDERDOC_IMPORT_FUNC(RENDERDOC_MaskOverlayBits); \
- RENDERDOC_IMPORT_FUNC(RENDERDOC_SetFocusToggleKeys); \
- RENDERDOC_IMPORT_FUNC(RENDERDOC_SetCaptureKeys); \
- RENDERDOC_IMPORT_FUNC(RENDERDOC_InitRemoteAccess); \
- RENDERDOC_IMPORT_FUNC(RENDERDOC_UnloadCrashHandler);
-
-#define RENDERDOC_IMPORT_FUNC(_func) p##_func _func
- RENDERDOC_IMPORT
-#undef RENDERDOC_IMPORT_FUNC
-
- pRENDERDOC_GetAPIVersion RENDERDOC_GetAPIVersion;
+ pRENDERDOC_GetAPI RENDERDOC_GetAPI;
+ static RENDERDOC_API_1_0_0* s_renderDoc;
void* loadRenderDoc()
{
@@ -89,33 +70,21 @@ namespace bgfx
if (NULL != renderdocdll)
{
- RENDERDOC_GetAPIVersion = (pRENDERDOC_GetAPIVersion)bx::dlsym(renderdocdll, "RENDERDOC_GetAPIVersion");
- if (NULL != RENDERDOC_GetAPIVersion
- && RENDERDOC_API_VERSION == RENDERDOC_GetAPIVersion() )
+ RENDERDOC_GetAPI = (pRENDERDOC_GetAPI)bx::dlsym(renderdocdll, "RENDERDOC_GetAPI");
+ if (NULL != RENDERDOC_GetAPI
+ && 1 == RENDERDOC_GetAPI(eRENDERDOC_API_Version_1_0_0, (void**)&s_renderDoc) )
{
-#define RENDERDOC_IMPORT_FUNC(_func) \
- _func = (p##_func)bx::dlsym(renderdocdll, #_func); \
- BX_TRACE("%p " #_func, _func);
-RENDERDOC_IMPORT
-#undef RENDERDOC_IMPORT_FUNC
+ s_renderDoc->SetLogFilePathTemplate("temp/bgfx");
- RENDERDOC_SetLogFile("temp/bgfx");
+ s_renderDoc->SetFocusToggleKeys(NULL, 0);
- RENDERDOC_SetFocusToggleKeys(NULL, 0);
+ RENDERDOC_InputButton captureKey = eRENDERDOC_Key_F11;
+ s_renderDoc->SetCaptureKeys(&captureKey, 1);
- KeyButton captureKey = eKey_F11;
- RENDERDOC_SetCaptureKeys(&captureKey, 1);
+ s_renderDoc->SetCaptureOptionU32(eRENDERDOC_Option_AllowVSync, 1);
+ s_renderDoc->SetCaptureOptionU32(eRENDERDOC_Option_SaveAllInitials, 1);
- CaptureOptions opt;
- memset(&opt, 0, sizeof(opt) );
- opt.AllowVSync = 1;
- opt.SaveAllInitials = 1;
- RENDERDOC_SetCaptureOptions(&opt);
-
- uint32_t ident = 0;
- RENDERDOC_InitRemoteAccess(&ident);
-
- RENDERDOC_MaskOverlayBits(eOverlay_None, eOverlay_None);
+ s_renderDoc->MaskOverlayBits(eRENDERDOC_Overlay_None, eRENDERDOC_Overlay_None);
}
else
{
@@ -131,7 +100,7 @@ RENDERDOC_IMPORT
{
if (NULL != _renderdocdll)
{
- RENDERDOC_Shutdown();
+ s_renderDoc->Shutdown();
bx::dlclose(_renderdocdll);
}
}
diff --git a/3rdparty/bgfx/src/renderer_d3d11.cpp b/3rdparty/bgfx/src/renderer_d3d11.cpp
index 4c50f1124d8..a7a383d3b7d 100644
--- a/3rdparty/bgfx/src/renderer_d3d11.cpp
+++ b/3rdparty/bgfx/src/renderer_d3d11.cpp
@@ -8,6 +8,11 @@
#if BGFX_CONFIG_RENDERER_DIRECT3D11
# include "renderer_d3d11.h"
+#if BX_PLATFORM_WINRT
+# include <inspectable.h>
+# include <windows.ui.xaml.media.dxinterop.h>
+#endif // BX_PLATFORM_WINRT
+
namespace bgfx { namespace d3d11
{
static wchar_t s_viewNameW[BGFX_CONFIG_MAX_VIEWS][BGFX_CONFIG_MAX_VIEW_NAME];
@@ -52,6 +57,7 @@ namespace bgfx { namespace d3d11
ID3D11ShaderResourceView* m_srv[D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT];
ID3D11SamplerState* m_sampler[D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT];
uint32_t m_zero[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];
+ float m_zerof[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];
};
BX_PRAGMA_DIAGNOSTIC_PUSH();
@@ -237,6 +243,7 @@ namespace bgfx { namespace d3d11
{ DXGI_FORMAT_R32G32_SINT, DXGI_FORMAT_R32G32_SINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN }, // RG32I
{ DXGI_FORMAT_R32G32_UINT, DXGI_FORMAT_R32G32_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN }, // RG32U
{ DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN }, // RG32F
+ { DXGI_FORMAT_R9G9B9E5_SHAREDEXP, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN }, // RGB9E5F
{ DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_B8G8R8A8_UNORM_SRGB }, // BGRA8
{ DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB }, // RGBA8
{ DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB }, // RGBA8I
@@ -1016,16 +1023,46 @@ BX_PRAGMA_DIAGNOSTIC_POP();
m_scd.SampleDesc.Quality = 0;
m_scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
m_scd.BufferCount = 2;
- m_scd.Scaling = DXGI_SCALING_NONE;
- m_scd.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
- m_scd.AlphaMode = DXGI_ALPHA_MODE_IGNORE;
+ m_scd.Scaling = 0 == g_platformData.ndt
+ ? DXGI_SCALING_NONE
+ : DXGI_SCALING_STRETCH;
+ m_scd.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
+ m_scd.AlphaMode = DXGI_ALPHA_MODE_IGNORE;
- hr = m_factory->CreateSwapChainForCoreWindow(m_device
- , (::IUnknown*)g_platformData.nwh
- , &m_scd
- , NULL
- , &m_swapChain
- );
+ if (NULL == g_platformData.ndt)
+ {
+ hr = m_factory->CreateSwapChainForCoreWindow(m_device
+ , (::IUnknown*)g_platformData.nwh
+ , &m_scd
+ , NULL
+ , &m_swapChain
+ );
+ BGFX_FATAL(SUCCEEDED(hr), Fatal::UnableToInitialize, "Unable to create Direct3D11 swap chain.");
+ }
+ else
+ {
+ BGFX_FATAL(g_platformData.ndt == reinterpret_cast<void*>(1), Fatal::UnableToInitialize, "Unable to set swap chain on panel.");
+
+ hr = m_factory->CreateSwapChainForComposition(m_device
+ , &m_scd
+ , NULL
+ , &m_swapChain
+ );
+ BX_WARN(SUCCEEDED(hr), "Unable to create Direct3D11 swap chain.");
+
+ IInspectable* nativeWindow = reinterpret_cast<IInspectable *>(g_platformData.nwh);
+ ISwapChainBackgroundPanelNative* panel = NULL;
+ hr = nativeWindow->QueryInterface(__uuidof(ISwapChainBackgroundPanelNative), (void**)&panel);
+ BGFX_FATAL(SUCCEEDED(hr), Fatal::UnableToInitialize, "Unable to set swap chain on panel.");
+
+ if (NULL != panel)
+ {
+ hr = panel->SetSwapChain(m_swapChain);
+ BGFX_FATAL(SUCCEEDED(hr), Fatal::UnableToInitialize, "Unable to set swap chain on panel.");
+
+ panel->Release();
+ }
+ }
#else
hr = adapter->GetParent(IID_IDXGIFactory, (void**)&m_factory);
BX_WARN(SUCCEEDED(hr), "Unable to create Direct3D11 device.");
@@ -1451,6 +1488,11 @@ BX_PRAGMA_DIAGNOSTIC_POP();
invalidateCache();
+ for (uint32_t ii = 0; ii < BX_COUNTOF(m_frameBuffers); ++ii)
+ {
+ m_frameBuffers[ii].destroy();
+ }
+
for (uint32_t ii = 0; ii < BX_COUNTOF(m_indexBuffers); ++ii)
{
m_indexBuffers[ii].destroy();
@@ -1844,7 +1886,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
setShaderUniform(flags, predefined.m_loc, proj, 4);
commitShaderConstants();
- m_textures[_blitter.m_texture.idx].commit(0);
+ m_textures[_blitter.m_texture.idx].commit(0, BGFX_SAMPLER_DEFAULT_FLAGS, NULL);
commitTextureStage();
}
@@ -2115,18 +2157,46 @@ BX_PRAGMA_DIAGNOSTIC_POP();
#if BX_PLATFORM_WINRT
HRESULT hr;
- hr = m_factory->CreateSwapChainForCoreWindow(m_device
- , (::IUnknown*)g_platformData.nwh
- , scd
- , NULL
- , &m_swapChain
- );
+ if (g_platformData.ndt == 0)
+ {
+ hr = m_factory->CreateSwapChainForCoreWindow(m_device
+ , (::IUnknown*)g_platformData.nwh
+ , scd
+ , NULL
+ , &m_swapChain
+ );
+ BGFX_FATAL(SUCCEEDED(hr), Fatal::UnableToInitialize, "Unable to create Direct3D11 swap chain.");
+ }
+ else
+ {
+ BGFX_FATAL(g_platformData.ndt == reinterpret_cast<void*>(1), Fatal::UnableToInitialize, "Invalid native display type.");
+
+ hr = m_factory->CreateSwapChainForComposition(m_device
+ , &m_scd
+ , NULL
+ , &m_swapChain
+ );
+ BGFX_FATAL(SUCCEEDED(hr), Fatal::UnableToInitialize, "Unable to create Direct3D11 swap chain.");
+
+ IInspectable *nativeWindow = reinterpret_cast<IInspectable *>(g_platformData.nwh);
+ ISwapChainBackgroundPanelNative* panel = NULL;
+ hr = nativeWindow->QueryInterface(__uuidof(ISwapChainBackgroundPanelNative), (void **)&panel);
+ BGFX_FATAL(SUCCEEDED(hr), Fatal::UnableToInitialize, "Unable to set swap chain on panel.");
+
+ if (NULL != panel)
+ {
+ hr = panel->SetSwapChain(m_swapChain);
+ BGFX_FATAL(SUCCEEDED(hr), Fatal::UnableToInitialize, "Unable to set swap chain on panel.");
+
+ panel->Release();
+ }
+ }
#else
HRESULT hr;
hr = m_factory->CreateSwapChain(m_device
- , scd
- , &m_swapChain
- );
+ , scd
+ , &m_swapChain
+ );
#endif // BX_PLATFORM_WINRT
BGFX_FATAL(SUCCEEDED(hr), bgfx::Fatal::UnableToInitialize, "Failed to create swap chain.");
}
@@ -2500,7 +2570,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
{
_state &= BGFX_STATE_CULL_MASK|BGFX_STATE_MSAA;
_state |= _wireframe ? BGFX_STATE_PT_LINES : BGFX_STATE_NONE;
- _state |= _scissor ? BGFX_STATE_RESERVED_MASK : 0;
+ _state |= _scissor ? BGFX_STATE_RESERVED_MASK : 0;
ID3D11RasterizerState* rs = m_rasterizerStateCache.find(_state);
if (NULL == rs)
@@ -2527,37 +2597,74 @@ BX_PRAGMA_DIAGNOSTIC_POP();
m_deviceCtx->RSSetState(rs);
}
- ID3D11SamplerState* getSamplerState(uint32_t _flags)
+ ID3D11SamplerState* getSamplerState(uint32_t _flags, const float _rgba[4])
{
+ const uint32_t index = (_flags & BGFX_TEXTURE_BORDER_COLOR_MASK) >> BGFX_TEXTURE_BORDER_COLOR_SHIFT;
_flags &= BGFX_TEXTURE_SAMPLER_BITS_MASK;
- ID3D11SamplerState* sampler = m_samplerStateCache.find(_flags);
+
+ uint32_t hash;
+ ID3D11SamplerState* sampler;
+ if (!needBorderColor(_flags) )
+ {
+ bx::HashMurmur2A murmur;
+ murmur.begin();
+ murmur.add(_flags);
+ murmur.add(-1);
+ hash = murmur.end();
+ _rgba = s_zero.m_zerof;
+
+ sampler = m_samplerStateCache.find(hash);
+ }
+ else
+ {
+ bx::HashMurmur2A murmur;
+ murmur.begin();
+ murmur.add(_flags);
+ murmur.add(index);
+ hash = murmur.end();
+ _rgba = NULL == _rgba ? s_zero.m_zerof : _rgba;
+
+ sampler = m_samplerStateCache.find(hash);
+ if (NULL != sampler)
+ {
+ D3D11_SAMPLER_DESC sd;
+ sampler->GetDesc(&sd);
+ if (0 != memcmp(_rgba, sd.BorderColor, 16) )
+ {
+ // Sampler will be released when updated sampler
+ // is added to cache.
+ sampler = NULL;
+ }
+ }
+ }
+
if (NULL == sampler)
{
- const uint32_t cmpFunc = (_flags&BGFX_TEXTURE_COMPARE_MASK)>>BGFX_TEXTURE_COMPARE_SHIFT;
- const uint8_t minFilter = s_textureFilter[0][(_flags&BGFX_TEXTURE_MIN_MASK)>>BGFX_TEXTURE_MIN_SHIFT];
- const uint8_t magFilter = s_textureFilter[1][(_flags&BGFX_TEXTURE_MAG_MASK)>>BGFX_TEXTURE_MAG_SHIFT];
- const uint8_t mipFilter = s_textureFilter[2][(_flags&BGFX_TEXTURE_MIP_MASK)>>BGFX_TEXTURE_MIP_SHIFT];
- const uint8_t filter = 0 == cmpFunc ? 0 : D3D11_COMPARISON_FILTERING_BIT;
+ const uint32_t cmpFunc = (_flags&BGFX_TEXTURE_COMPARE_MASK)>>BGFX_TEXTURE_COMPARE_SHIFT;
+ const uint8_t minFilter = s_textureFilter[0][(_flags&BGFX_TEXTURE_MIN_MASK)>>BGFX_TEXTURE_MIN_SHIFT];
+ const uint8_t magFilter = s_textureFilter[1][(_flags&BGFX_TEXTURE_MAG_MASK)>>BGFX_TEXTURE_MAG_SHIFT];
+ const uint8_t mipFilter = s_textureFilter[2][(_flags&BGFX_TEXTURE_MIP_MASK)>>BGFX_TEXTURE_MIP_SHIFT];
+ const uint8_t filter = 0 == cmpFunc ? 0 : D3D11_COMPARISON_FILTERING_BIT;
D3D11_SAMPLER_DESC sd;
- sd.Filter = (D3D11_FILTER)(filter|minFilter|magFilter|mipFilter);
- sd.AddressU = s_textureAddress[(_flags&BGFX_TEXTURE_U_MASK)>>BGFX_TEXTURE_U_SHIFT];
- sd.AddressV = s_textureAddress[(_flags&BGFX_TEXTURE_V_MASK)>>BGFX_TEXTURE_V_SHIFT];
- sd.AddressW = s_textureAddress[(_flags&BGFX_TEXTURE_W_MASK)>>BGFX_TEXTURE_W_SHIFT];
- sd.MipLODBias = 0.0f;
+ sd.Filter = (D3D11_FILTER)(filter|minFilter|magFilter|mipFilter);
+ sd.AddressU = s_textureAddress[(_flags&BGFX_TEXTURE_U_MASK)>>BGFX_TEXTURE_U_SHIFT];
+ sd.AddressV = s_textureAddress[(_flags&BGFX_TEXTURE_V_MASK)>>BGFX_TEXTURE_V_SHIFT];
+ sd.AddressW = s_textureAddress[(_flags&BGFX_TEXTURE_W_MASK)>>BGFX_TEXTURE_W_SHIFT];
+ sd.MipLODBias = 0.0f;
sd.MaxAnisotropy = m_maxAnisotropy;
sd.ComparisonFunc = 0 == cmpFunc ? D3D11_COMPARISON_NEVER : s_cmpFunc[cmpFunc];
- sd.BorderColor[0] = 0.0f;
- sd.BorderColor[1] = 0.0f;
- sd.BorderColor[2] = 0.0f;
- sd.BorderColor[3] = 0.0f;
+ sd.BorderColor[0] = _rgba[0];
+ sd.BorderColor[1] = _rgba[1];
+ sd.BorderColor[2] = _rgba[2];
+ sd.BorderColor[3] = _rgba[3];
sd.MinLOD = 0;
sd.MaxLOD = D3D11_FLOAT32_MAX;
m_device->CreateSamplerState(&sd, &sampler);
DX_CHECK_REFCOUNT(sampler, 1);
- m_samplerStateCache.add(_flags, sampler);
+ m_samplerStateCache.add(hash, sampler);
}
return sampler;
@@ -2885,13 +2992,13 @@ BX_PRAGMA_DIAGNOSTIC_POP();
}
}
- void commit(ConstantBuffer& _constantBuffer)
+ void commit(UniformBuffer& _uniformBuffer)
{
- _constantBuffer.reset();
+ _uniformBuffer.reset();
for (;;)
{
- uint32_t opcode = _constantBuffer.read();
+ uint32_t opcode = _uniformBuffer.read();
if (UniformType::End == opcode)
{
@@ -2902,17 +3009,17 @@ BX_PRAGMA_DIAGNOSTIC_POP();
uint16_t loc;
uint16_t num;
uint16_t copy;
- ConstantBuffer::decodeOpcode(opcode, type, loc, num, copy);
+ UniformBuffer::decodeOpcode(opcode, type, loc, num, copy);
const char* data;
if (copy)
{
- data = _constantBuffer.read(g_uniformTypeSize[type]*num);
+ data = _uniformBuffer.read(g_uniformTypeSize[type]*num);
}
else
{
UniformHandle handle;
- memcpy(&handle, _constantBuffer.read(sizeof(UniformHandle) ), sizeof(UniformHandle) );
+ memcpy(&handle, _uniformBuffer.read(sizeof(UniformHandle) ), sizeof(UniformHandle) );
data = (const char*)m_uniforms[handle.idx];
}
@@ -2958,7 +3065,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
break;
default:
- BX_TRACE("%4d: INVALID 0x%08x, t %d, l %d, n %d, c %d", _constantBuffer.getPos(), opcode, type, loc, num, copy);
+ BX_TRACE("%4d: INVALID 0x%08x, t %d, l %d, n %d, c %d", _uniformBuffer.getPos(), opcode, type, loc, num, copy);
break;
}
#undef CASE_IMPLEMENT_UNIFORM
@@ -3035,7 +3142,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
float mrtClear[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS][4];
for (uint32_t ii = 0; ii < numMrt; ++ii)
{
- uint8_t index = (uint8_t)bx::uint32_min(BGFX_CONFIG_MAX_CLEAR_COLOR_PALETTE-1, _clear.m_index[ii]);
+ uint8_t index = (uint8_t)bx::uint32_min(BGFX_CONFIG_MAX_COLOR_PALETTE-1, _clear.m_index[ii]);
memcpy(mrtClear[ii], _palette[index], 16);
}
@@ -3214,6 +3321,25 @@ BX_PRAGMA_DIAGNOSTIC_POP();
s_renderD3D11 = NULL;
}
+ void trim()
+ {
+#if BX_PLATFORM_WINRT
+ if (NULL != s_renderD3D11)
+ {
+ if (s_renderD3D11->m_device)
+ {
+ IDXGIDevice3* pDXGIDevice;
+ HRESULT hr = s_renderD3D11->m_device->QueryInterface(__uuidof(IDXGIDevice3),(void **)&pDXGIDevice);
+ if (SUCCEEDED(hr) )
+ {
+ pDXGIDevice->Trim();
+ pDXGIDevice->Release();
+ }
+ }
+ }
+#endif // BX_PLATFORM_WINRT
+ }
+
void stubMultiDrawInstancedIndirect(uint32_t _numDrawIndirect, ID3D11Buffer* _ptr, uint32_t _offset, uint32_t _stride)
{
ID3D11DeviceContext* deviceCtx = s_renderD3D11->m_deviceCtx;
@@ -3566,12 +3692,13 @@ BX_PRAGMA_DIAGNOSTIC_POP();
else if (0 == (BGFX_UNIFORM_SAMPLERBIT & type) )
{
const UniformInfo* info = s_renderD3D11->m_uniformReg.find(name);
+ BX_CHECK(NULL != info, "User defined uniform '%s' is not found, it won't be set.", name);
if (NULL != info)
{
if (NULL == m_constantBuffer)
{
- m_constantBuffer = ConstantBuffer::create(1024);
+ m_constantBuffer = UniformBuffer::create(1024);
}
kind = "user";
@@ -3662,8 +3789,6 @@ BX_PRAGMA_DIAGNOSTIC_POP();
void TextureD3D11::create(const Memory* _mem, uint32_t _flags, uint8_t _skip)
{
- m_sampler = s_renderD3D11->getSamplerState(_flags);
-
ImageContainer imageContainer;
if (imageParse(imageContainer, _mem->data, _mem->size) )
@@ -3953,14 +4078,18 @@ BX_PRAGMA_DIAGNOSTIC_POP();
}
}
- void TextureD3D11::commit(uint8_t _stage, uint32_t _flags)
+ void TextureD3D11::commit(uint8_t _stage, uint32_t _flags, const float _palette[][4])
{
TextureStage& ts = s_renderD3D11->m_textureStage;
ts.m_srv[_stage] = m_srv;
- ts.m_sampler[_stage] = 0 == (BGFX_SAMPLER_DEFAULT_FLAGS & _flags)
- ? s_renderD3D11->getSamplerState(_flags)
- : m_sampler
+ uint32_t flags = 0 == (BGFX_SAMPLER_DEFAULT_FLAGS & _flags)
+ ? _flags
+ : m_flags
;
+ uint32_t index = (flags & BGFX_TEXTURE_BORDER_COLOR_MASK) >> BGFX_TEXTURE_BORDER_COLOR_SHIFT;
+ ts.m_sampler[_stage] = s_renderD3D11->getSamplerState(flags
+ , _palette[index])
+ ;
}
void TextureD3D11::resolve()
@@ -4451,7 +4580,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
if (BGFX_CLEAR_NONE != (clr.m_flags & BGFX_CLEAR_MASK) )
{
- clearQuad(_clearQuad, viewState.m_rect, clr, _render->m_clearColor);
+ clearQuad(_clearQuad, viewState.m_rect, clr, _render->m_colorPalette);
prim = s_primInfo[BX_COUNTOF(s_primName)]; // Force primitive type update after clear quad.
}
}
@@ -4490,7 +4619,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
bool programChanged = false;
bool constantsChanged = compute.m_constBegin < compute.m_constEnd;
- rendererUpdateUniforms(this, _render->m_constantBuffer, compute.m_constBegin, compute.m_constEnd);
+ rendererUpdateUniforms(this, _render->m_uniformBuffer, compute.m_constBegin, compute.m_constEnd);
if (key.m_program != programIdx)
{
@@ -4512,7 +4641,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
if (constantsChanged)
{
- ConstantBuffer* vcb = program.m_vsh->m_constantBuffer;
+ UniformBuffer* vcb = program.m_vsh->m_constantBuffer;
if (NULL != vcb)
{
commit(*vcb);
@@ -4555,7 +4684,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
? texture.m_srv
: s_renderD3D11->getCachedSrv(texture.getHandle(), bind.m_un.m_compute.m_mip)
;
- sampler[ii] = texture.m_sampler;
+ sampler[ii] = s_renderD3D11->getSamplerState(texture.m_flags, NULL);
}
}
break;
@@ -4739,7 +4868,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
bool programChanged = false;
bool constantsChanged = draw.m_constBegin < draw.m_constEnd;
- rendererUpdateUniforms(this, _render->m_constantBuffer, draw.m_constBegin, draw.m_constEnd);
+ rendererUpdateUniforms(this, _render->m_uniformBuffer, draw.m_constBegin, draw.m_constEnd);
if (key.m_program != programIdx)
{
@@ -4784,13 +4913,13 @@ BX_PRAGMA_DIAGNOSTIC_POP();
if (constantsChanged)
{
- ConstantBuffer* vcb = program.m_vsh->m_constantBuffer;
+ UniformBuffer* vcb = program.m_vsh->m_constantBuffer;
if (NULL != vcb)
{
commit(*vcb);
}
- ConstantBuffer* fcb = program.m_fsh->m_constantBuffer;
+ UniformBuffer* fcb = program.m_fsh->m_constantBuffer;
if (NULL != fcb)
{
commit(*fcb);
@@ -4819,7 +4948,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
if (invalidHandle != bind.m_idx)
{
TextureD3D11& texture = m_textures[bind.m_idx];
- texture.commit(stage, bind.m_un.m_draw.m_flags);
+ texture.commit(stage, bind.m_un.m_draw.m_flags, _render->m_colorPalette);
}
else
{
@@ -5193,7 +5322,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
}
tvm.printf(10, pos++, 0x8e, " Indices: %7d ", statsNumIndices);
- tvm.printf(10, pos++, 0x8e, " Uniform size: %7d ", _render->m_constEnd);
+ tvm.printf(10, pos++, 0x8e, " Uniform size: %7d, Max: %7d ", _render->m_uniformEnd, _render->m_uniformMax);
tvm.printf(10, pos++, 0x8e, " DVB size: %7d ", _render->m_vboffset);
tvm.printf(10, pos++, 0x8e, " DIB size: %7d ", _render->m_iboffset);
diff --git a/3rdparty/bgfx/src/renderer_d3d11.h b/3rdparty/bgfx/src/renderer_d3d11.h
index 359f936899c..d0560957f72 100644
--- a/3rdparty/bgfx/src/renderer_d3d11.h
+++ b/3rdparty/bgfx/src/renderer_d3d11.h
@@ -20,7 +20,7 @@ BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4005) // warning C4005: '' : macro redefinitio
#include <sal.h>
#define D3D11_NO_HELPERS
#if BX_PLATFORM_WINRT
-# include <d3d11_2.h>
+# include <d3d11_3.h>
#else
# include <d3d11.h>
#endif // BX_PLATFORM_WINRT
@@ -124,7 +124,7 @@ namespace bgfx { namespace d3d11
{
if (NULL != m_constantBuffer)
{
- ConstantBuffer::destroy(m_constantBuffer);
+ UniformBuffer::destroy(m_constantBuffer);
m_constantBuffer = NULL;
}
@@ -154,7 +154,7 @@ namespace bgfx { namespace d3d11
};
const Memory* m_code;
ID3D11Buffer* m_buffer;
- ConstantBuffer* m_constantBuffer;
+ UniformBuffer* m_constantBuffer;
PredefinedUniform m_predefined[PredefinedUniform::Count];
uint16_t m_attrMask[Attrib::Count];
@@ -217,7 +217,6 @@ namespace bgfx { namespace d3d11
: m_ptr(NULL)
, m_srv(NULL)
, m_uav(NULL)
- , m_sampler(NULL)
, m_numMips(0)
{
}
@@ -225,7 +224,7 @@ namespace bgfx { namespace d3d11
void create(const Memory* _mem, uint32_t _flags, uint8_t _skip);
void destroy();
void update(uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem);
- void commit(uint8_t _stage, uint32_t _flags = BGFX_SAMPLER_DEFAULT_FLAGS);
+ void commit(uint8_t _stage, uint32_t _flags, const float _palette[][4]);
void resolve();
TextureHandle getHandle() const;
@@ -238,7 +237,6 @@ namespace bgfx { namespace d3d11
ID3D11ShaderResourceView* m_srv;
ID3D11UnorderedAccessView* m_uav;
- ID3D11SamplerState* m_sampler;
uint32_t m_flags;
uint8_t m_type;
uint8_t m_requestedFormat;
@@ -250,6 +248,7 @@ namespace bgfx { namespace d3d11
{
FrameBufferD3D11()
: m_dsv(NULL)
+ , m_swapChain(NULL)
, m_width(0)
, m_height(0)
, m_denseIdx(UINT16_MAX)
diff --git a/3rdparty/bgfx/src/renderer_d3d12.cpp b/3rdparty/bgfx/src/renderer_d3d12.cpp
index 46d2ac38624..902eb8b4610 100644
--- a/3rdparty/bgfx/src/renderer_d3d12.cpp
+++ b/3rdparty/bgfx/src/renderer_d3d12.cpp
@@ -221,6 +221,7 @@ namespace bgfx { namespace d3d12
{ DXGI_FORMAT_R32G32_SINT, DXGI_FORMAT_R32G32_SINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN }, // RG32I
{ DXGI_FORMAT_R32G32_UINT, DXGI_FORMAT_R32G32_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN }, // RG32U
{ DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN }, // RG32F
+ { DXGI_FORMAT_R9G9B9E5_SHAREDEXP, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN }, // RGB9E5F
{ DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_B8G8R8A8_UNORM_SRGB }, // BGRA8
{ DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB }, // RGBA8
{ DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB }, // RGBA8I
@@ -457,6 +458,7 @@ namespace bgfx { namespace d3d12
RendererContextD3D12()
: m_wireframe(false)
, m_flags(BGFX_RESET_NONE)
+ , m_maxAnisotropy(1)
, m_fsChanges(0)
, m_vsChanges(0)
, m_backBufferColorIdx(0)
@@ -835,10 +837,10 @@ namespace bgfx { namespace d3d12
D3D12_ROOT_PARAMETER rootParameter[] =
{
- { D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, { 1, &descRange[Rdt::Sampler] }, D3D12_SHADER_VISIBILITY_ALL },
- { D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, { 1, &descRange[Rdt::SRV] }, D3D12_SHADER_VISIBILITY_ALL },
- { D3D12_ROOT_PARAMETER_TYPE_CBV, { 0, 0 }, D3D12_SHADER_VISIBILITY_ALL },
- { D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, { 1, &descRange[Rdt::UAV] }, D3D12_SHADER_VISIBILITY_ALL },
+ { D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, { { 1, &descRange[Rdt::Sampler] } }, D3D12_SHADER_VISIBILITY_ALL },
+ { D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, { { 1, &descRange[Rdt::SRV] } }, D3D12_SHADER_VISIBILITY_ALL },
+ { D3D12_ROOT_PARAMETER_TYPE_CBV, { { 0, 0 } }, D3D12_SHADER_VISIBILITY_ALL },
+ { D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, { { 1, &descRange[Rdt::UAV] } }, D3D12_SHADER_VISIBILITY_ALL },
};
rootParameter[Rdt::CBV].Descriptor.RegisterSpace = 0;
rootParameter[Rdt::CBV].Descriptor.ShaderRegister = 0;
@@ -1364,7 +1366,7 @@ namespace bgfx { namespace d3d12
box.back = 1;
setResourceBarrier(m_commandList, backBuffer, D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_COPY_SOURCE);
- D3D12_TEXTURE_COPY_LOCATION dst = { readback, D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT, layout };
+ D3D12_TEXTURE_COPY_LOCATION dst = { readback, D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT, { layout } };
D3D12_TEXTURE_COPY_LOCATION src = { backBuffer, D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX, {} };
m_commandList->CopyTextureRegion(&dst, 0, 0, 0, &src, &box);
setResourceBarrier(m_commandList, backBuffer, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_PRESENT);
@@ -1467,7 +1469,7 @@ namespace bgfx { namespace d3d12
TextureD3D12& texture = m_textures[_blitter.m_texture.idx];
uint32_t samplerFlags[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS] = { texture.m_flags & BGFX_TEXTURE_SAMPLER_BITS_MASK };
- uint16_t samplerStateIdx = getSamplerState(samplerFlags);
+ uint16_t samplerStateIdx = getSamplerState(samplerFlags, BGFX_CONFIG_MAX_TEXTURE_SAMPLERS, NULL);
m_commandList->SetGraphicsRootDescriptorTable(Rdt::Sampler, m_samplerAllocator.get(samplerStateIdx) );
D3D12_GPU_DESCRIPTOR_HANDLE srvHandle;
scratchBuffer.allocSrv(srvHandle, texture);
@@ -1627,6 +1629,15 @@ data.NumQualityLevels = 0;
void updateResolution(const Resolution& _resolution)
{
+ if (!!(_resolution.m_flags & BGFX_RESET_MAXANISOTROPY) )
+ {
+ m_maxAnisotropy = D3D12_REQ_MAXANISOTROPY;
+ }
+ else
+ {
+ m_maxAnisotropy = 1;
+ }
+
if ( (uint32_t)m_scd.BufferDesc.Width != _resolution.m_width
|| (uint32_t)m_scd.BufferDesc.Height != _resolution.m_height
|| m_flags != _resolution.m_flags)
@@ -1761,7 +1772,7 @@ data.NumQualityLevels = 0;
m_currentColor = &m_rtvHandle;
m_currentDepthStencil = &m_dsvHandle;
- m_commandList->OMSetRenderTargets(1, m_currentColor, false, m_currentDepthStencil);
+ m_commandList->OMSetRenderTargets(1, m_currentColor, true, m_currentDepthStencil);
}
else
{
@@ -1805,7 +1816,7 @@ data.NumQualityLevels = 0;
m_commandList->OMSetRenderTargets(frameBuffer.m_num
, m_currentColor
- , true //NULL == m_currentDepthStencil
+ , true
, m_currentDepthStencil
);
}
@@ -2265,7 +2276,7 @@ data.NumQualityLevels = 0;
return pso;
}
- uint16_t getSamplerState(const uint32_t* _flags, uint32_t _num = BGFX_CONFIG_MAX_TEXTURE_SAMPLERS)
+ uint16_t getSamplerState(const uint32_t* _flags, uint32_t _num, const float _palette[][4])
{
bx::HashMurmur2A murmur;
murmur.begin();
@@ -2275,20 +2286,20 @@ data.NumQualityLevels = 0;
uint16_t sampler = m_samplerStateCache.find(hash);
if (UINT16_MAX == sampler)
{
- sampler = m_samplerAllocator.alloc(_flags, _num);
+ sampler = m_samplerAllocator.alloc(_flags, _num, _palette);
m_samplerStateCache.add(hash, sampler);
}
return sampler;
}
- void commit(ConstantBuffer& _constantBuffer)
+ void commit(UniformBuffer& _uniformBuffer)
{
- _constantBuffer.reset();
+ _uniformBuffer.reset();
for (;;)
{
- uint32_t opcode = _constantBuffer.read();
+ uint32_t opcode = _uniformBuffer.read();
if (UniformType::End == opcode)
{
@@ -2299,17 +2310,17 @@ data.NumQualityLevels = 0;
uint16_t loc;
uint16_t num;
uint16_t copy;
- ConstantBuffer::decodeOpcode(opcode, type, loc, num, copy);
+ UniformBuffer::decodeOpcode(opcode, type, loc, num, copy);
const char* data;
if (copy)
{
- data = _constantBuffer.read(g_uniformTypeSize[type]*num);
+ data = _uniformBuffer.read(g_uniformTypeSize[type]*num);
}
else
{
UniformHandle handle;
- memcpy(&handle, _constantBuffer.read(sizeof(UniformHandle) ), sizeof(UniformHandle) );
+ memcpy(&handle, _uniformBuffer.read(sizeof(UniformHandle) ), sizeof(UniformHandle) );
data = (const char*)m_uniforms[handle.idx];
}
@@ -2355,7 +2366,7 @@ data.NumQualityLevels = 0;
break;
default:
- BX_TRACE("%4d: INVALID 0x%08x, t %d, l %d, n %d, c %d", _constantBuffer.getPos(), opcode, type, loc, num, copy);
+ BX_TRACE("%4d: INVALID 0x%08x, t %d, l %d, n %d, c %d", _uniformBuffer.getPos(), opcode, type, loc, num, copy);
break;
}
#undef CASE_IMPLEMENT_UNIFORM
@@ -2522,6 +2533,7 @@ data.NumQualityLevels = 0;
DXGI_SWAP_CHAIN_DESC m_scd;
uint32_t m_flags;
+ uint32_t m_maxAnisotropy;
BufferD3D12 m_indexBuffers[BGFX_CONFIG_MAX_INDEX_BUFFERS];
VertexBufferD3D12 m_vertexBuffers[BGFX_CONFIG_MAX_VERTEX_BUFFERS];
@@ -2784,11 +2796,12 @@ data.NumQualityLevels = 0;
return idx;
}
- uint16_t DescriptorAllocatorD3D12::alloc(const uint32_t* _flags, uint32_t _num)
+ uint16_t DescriptorAllocatorD3D12::alloc(const uint32_t* _flags, uint32_t _num, const float _palette[][4])
{
uint16_t idx = m_handleAlloc->alloc();
- ID3D12Device* device = s_renderD3D12->m_device;
+ ID3D12Device* device = s_renderD3D12->m_device;
+ uint32_t maxAnisotropy = s_renderD3D12->m_maxAnisotropy;
for (uint32_t ii = 0; ii < _num; ++ii)
{
@@ -2806,12 +2819,27 @@ data.NumQualityLevels = 0;
sd.AddressV = s_textureAddress[(flags&BGFX_TEXTURE_V_MASK)>>BGFX_TEXTURE_V_SHIFT];
sd.AddressW = s_textureAddress[(flags&BGFX_TEXTURE_W_MASK)>>BGFX_TEXTURE_W_SHIFT];
sd.MipLODBias = 0.0f;
- sd.MaxAnisotropy = 1; //m_maxAnisotropy;
+ sd.MaxAnisotropy = maxAnisotropy;
sd.ComparisonFunc = 0 == cmpFunc ? D3D12_COMPARISON_FUNC_NEVER : s_cmpFunc[cmpFunc];
- sd.BorderColor[0] = 0.0f;
- sd.BorderColor[1] = 0.0f;
- sd.BorderColor[2] = 0.0f;
- sd.BorderColor[3] = 0.0f;
+
+ uint32_t index = (flags & BGFX_TEXTURE_BORDER_COLOR_MASK) >> BGFX_TEXTURE_BORDER_COLOR_SHIFT;
+
+ if (NULL != _palette
+ && needBorderColor(flags) )
+ {
+ const float* rgba = _palette[index];
+ sd.BorderColor[0] = rgba[0];
+ sd.BorderColor[1] = rgba[1];
+ sd.BorderColor[2] = rgba[2];
+ sd.BorderColor[3] = rgba[3];
+ }
+ else
+ {
+ sd.BorderColor[0] = 0.0f;
+ sd.BorderColor[1] = 0.0f;
+ sd.BorderColor[2] = 0.0f;
+ sd.BorderColor[3] = 0.0f;
+ }
sd.MinLOD = 0;
sd.MaxLOD = D3D12_FLOAT32_MAX;
@@ -3000,10 +3028,10 @@ data.NumQualityLevels = 0;
D3D12_INDIRECT_ARGUMENT_DESC drawArgDesc[] =
{
- { D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT_BUFFER_VIEW, { Rdt::CBV } },
- { D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW, 0 },
- { D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW, 1 },
- { D3D12_INDIRECT_ARGUMENT_TYPE_DRAW, 0 },
+ { D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT_BUFFER_VIEW, { { Rdt::CBV } } },
+ { D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW, { { 0 } } },
+ { D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW, { { 1 } } },
+ { D3D12_INDIRECT_ARGUMENT_TYPE_DRAW, { { 0 } } },
};
D3D12_COMMAND_SIGNATURE_DESC drawCommandSignature =
@@ -3022,11 +3050,11 @@ data.NumQualityLevels = 0;
D3D12_INDIRECT_ARGUMENT_DESC drawIndexedArgDesc[] =
{
- { D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT_BUFFER_VIEW, { Rdt::CBV } },
- { D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW, 0 },
- { D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW, 1 },
- { D3D12_INDIRECT_ARGUMENT_TYPE_INDEX_BUFFER_VIEW, 0 },
- { D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED, 0 },
+ { D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT_BUFFER_VIEW, { { Rdt::CBV } } },
+ { D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW, { { 0 } } },
+ { D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW, { { 1 } } },
+ { D3D12_INDIRECT_ARGUMENT_TYPE_INDEX_BUFFER_VIEW, { { 0 } } },
+ { D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED, { { 0 } } },
};
D3D12_COMMAND_SIGNATURE_DESC drawIndexedCommandSignature =
@@ -3528,12 +3556,13 @@ data.NumQualityLevels = 0;
else if (0 == (BGFX_UNIFORM_SAMPLERBIT & type) )
{
const UniformInfo* info = s_renderD3D12->m_uniformReg.find(name);
+ BX_CHECK(NULL != info, "User defined uniform '%s' is not found, it won't be set.", name);
if (NULL != info)
{
if (NULL == m_constantBuffer)
{
- m_constantBuffer = ConstantBuffer::create(1024);
+ m_constantBuffer = UniformBuffer::create(1024);
}
kind = "user";
@@ -3998,9 +4027,9 @@ data.NumQualityLevels = 0;
box.front = _z;
box.back = _z+_depth;
- D3D12_TEXTURE_COPY_LOCATION dst = { m_ptr, D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX, {} };
+ D3D12_TEXTURE_COPY_LOCATION dst = { m_ptr, D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX, { } };
dst.SubresourceIndex = subres;
- D3D12_TEXTURE_COPY_LOCATION src = { staging, D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT, layout };
+ D3D12_TEXTURE_COPY_LOCATION src = { staging, D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT, { layout } };
_commandList->CopyTextureRegion(&dst, _rect.m_x, _rect.m_y, 0, &src, &box);
setState(_commandList, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
@@ -4351,7 +4380,7 @@ data.NumQualityLevels = 0;
{
Rect clearRect = rect;
clearRect.intersect(rect, viewScissorRect);
- clearQuad(clearRect, clr, _render->m_clearColor);
+ clearQuad(clearRect, clr, _render->m_colorPalette);
}
prim = s_primInfo[BX_COUNTOF(s_primName)]; // Force primitive type update.
@@ -4386,8 +4415,8 @@ data.NumQualityLevels = 0;
{
currentBindHash = bindHash;
- Bind* bind = bindLru.find(bindHash);
- if (NULL == bind)
+ Bind* bindCached = bindLru.find(bindHash);
+ if (NULL == bindCached)
{
D3D12_GPU_DESCRIPTOR_HANDLE srvHandle[BGFX_MAX_COMPUTE_BINDINGS] = {};
uint32_t samplerFlags[BGFX_MAX_COMPUTE_BINDINGS] = {};
@@ -4441,7 +4470,7 @@ data.NumQualityLevels = 0;
}
}
- uint16_t samplerStateIdx = getSamplerState(samplerFlags, BGFX_MAX_COMPUTE_BINDINGS);
+ uint16_t samplerStateIdx = getSamplerState(samplerFlags, BGFX_MAX_COMPUTE_BINDINGS, _render->m_colorPalette);
if (samplerStateIdx != currentSamplerStateIdx)
{
currentSamplerStateIdx = samplerStateIdx;
@@ -4458,14 +4487,14 @@ data.NumQualityLevels = 0;
}
else
{
- uint16_t samplerStateIdx = bind->m_samplerStateIdx;
+ uint16_t samplerStateIdx = bindCached->m_samplerStateIdx;
if (samplerStateIdx != currentSamplerStateIdx)
{
currentSamplerStateIdx = samplerStateIdx;
m_commandList->SetComputeRootDescriptorTable(Rdt::Sampler, m_samplerAllocator.get(samplerStateIdx) );
}
- m_commandList->SetComputeRootDescriptorTable(Rdt::SRV, bind->m_srvHandle);
- m_commandList->SetComputeRootDescriptorTable(Rdt::UAV, bind->m_srvHandle);
+ m_commandList->SetComputeRootDescriptorTable(Rdt::SRV, bindCached->m_srvHandle);
+ m_commandList->SetComputeRootDescriptorTable(Rdt::UAV, bindCached->m_srvHandle);
}
}
@@ -4473,12 +4502,12 @@ data.NumQualityLevels = 0;
if (compute.m_constBegin < compute.m_constEnd
|| currentProgramIdx != key.m_program)
{
- rendererUpdateUniforms(this, _render->m_constantBuffer, compute.m_constBegin, compute.m_constEnd);
+ rendererUpdateUniforms(this, _render->m_uniformBuffer, compute.m_constBegin, compute.m_constEnd);
currentProgramIdx = key.m_program;
ProgramD3D12& program = m_program[currentProgramIdx];
- ConstantBuffer* vcb = program.m_vsh->m_constantBuffer;
+ UniformBuffer* vcb = program.m_vsh->m_constantBuffer;
if (NULL != vcb)
{
commit(*vcb);
@@ -4569,7 +4598,7 @@ data.NumQualityLevels = 0;
primIndex = uint8_t(pt>>BGFX_STATE_PT_SHIFT);
}
- rendererUpdateUniforms(this, _render->m_constantBuffer, draw.m_constBegin, draw.m_constEnd);
+ rendererUpdateUniforms(this, _render->m_uniformBuffer, draw.m_constBegin, draw.m_constEnd);
if (isValid(draw.m_vertexBuffer) )
{
@@ -4607,8 +4636,8 @@ data.NumQualityLevels = 0;
{
currentBindHash = bindHash;
- Bind* bind = bindLru.find(bindHash);
- if (NULL == bind)
+ Bind* bindCached = bindLru.find(bindHash);
+ if (NULL == bindCached)
{
D3D12_GPU_DESCRIPTOR_HANDLE srvHandle[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS];
uint32_t samplerFlags[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS];
@@ -4625,7 +4654,7 @@ data.NumQualityLevels = 0;
samplerFlags[stage] = (0 == (BGFX_SAMPLER_DEFAULT_FLAGS & bind.m_un.m_draw.m_flags)
? bind.m_un.m_draw.m_flags
: texture.m_flags
- ) & BGFX_TEXTURE_SAMPLER_BITS_MASK
+ ) & (BGFX_TEXTURE_SAMPLER_BITS_MASK|BGFX_TEXTURE_BORDER_COLOR_MASK)
;
}
else
@@ -4638,7 +4667,7 @@ data.NumQualityLevels = 0;
if (srvHandle[0].ptr != 0)
{
- uint16_t samplerStateIdx = getSamplerState(samplerFlags);
+ uint16_t samplerStateIdx = getSamplerState(samplerFlags, BGFX_CONFIG_MAX_TEXTURE_SAMPLERS, _render->m_colorPalette);
if (samplerStateIdx != currentSamplerStateIdx)
{
currentSamplerStateIdx = samplerStateIdx;
@@ -4655,13 +4684,13 @@ data.NumQualityLevels = 0;
}
else
{
- uint16_t samplerStateIdx = bind->m_samplerStateIdx;
+ uint16_t samplerStateIdx = bindCached->m_samplerStateIdx;
if (samplerStateIdx != currentSamplerStateIdx)
{
currentSamplerStateIdx = samplerStateIdx;
m_commandList->SetGraphicsRootDescriptorTable(Rdt::Sampler, m_samplerAllocator.get(samplerStateIdx) );
}
- m_commandList->SetGraphicsRootDescriptorTable(Rdt::SRV, bind->m_srvHandle);
+ m_commandList->SetGraphicsRootDescriptorTable(Rdt::SRV, bindCached->m_srvHandle);
}
}
@@ -4740,13 +4769,13 @@ data.NumQualityLevels = 0;
currentProgramIdx = key.m_program;
ProgramD3D12& program = m_program[currentProgramIdx];
- ConstantBuffer* vcb = program.m_vsh->m_constantBuffer;
+ UniformBuffer* vcb = program.m_vsh->m_constantBuffer;
if (NULL != vcb)
{
commit(*vcb);
}
- ConstantBuffer* fcb = program.m_fsh->m_constantBuffer;
+ UniformBuffer* fcb = program.m_fsh->m_constantBuffer;
if (NULL != fcb)
{
commit(*fcb);
@@ -4925,7 +4954,7 @@ data.NumQualityLevels = 0;
// }
tvm.printf(10, pos++, 0x8e, " Indices: %7d ", statsNumIndices);
- tvm.printf(10, pos++, 0x8e, " Uniform size: %7d ", _render->m_constEnd);
+ tvm.printf(10, pos++, 0x8e, " Uniform size: %7d, Max: %7d ", _render->m_uniformEnd, _render->m_uniformMax);
tvm.printf(10, pos++, 0x8e, " DVB size: %7d ", _render->m_vboffset);
tvm.printf(10, pos++, 0x8e, " DIB size: %7d ", _render->m_iboffset);
diff --git a/3rdparty/bgfx/src/renderer_d3d12.h b/3rdparty/bgfx/src/renderer_d3d12.h
index 563db92931d..00f9a17f89a 100644
--- a/3rdparty/bgfx/src/renderer_d3d12.h
+++ b/3rdparty/bgfx/src/renderer_d3d12.h
@@ -107,7 +107,7 @@ namespace bgfx { namespace d3d12
void destroy();
uint16_t alloc(ID3D12Resource* _ptr, const D3D12_SHADER_RESOURCE_VIEW_DESC* _desc);
- uint16_t alloc(const uint32_t* _flags, uint32_t _num = BGFX_CONFIG_MAX_TEXTURE_SAMPLERS);
+ uint16_t alloc(const uint32_t* _flags, uint32_t _num, const float _palette[][4]);
void free(uint16_t _handle);
void reset();
@@ -179,7 +179,7 @@ namespace bgfx { namespace d3d12
{
if (NULL != m_constantBuffer)
{
- ConstantBuffer::destroy(m_constantBuffer);
+ UniformBuffer::destroy(m_constantBuffer);
m_constantBuffer = NULL;
}
@@ -194,7 +194,7 @@ namespace bgfx { namespace d3d12
}
const Memory* m_code;
- ConstantBuffer* m_constantBuffer;
+ UniformBuffer* m_constantBuffer;
PredefinedUniform m_predefined[PredefinedUniform::Count];
uint16_t m_attrMask[Attrib::Count];
diff --git a/3rdparty/bgfx/src/renderer_d3d9.cpp b/3rdparty/bgfx/src/renderer_d3d9.cpp
index 05536157d62..d14956ab49d 100644
--- a/3rdparty/bgfx/src/renderer_d3d9.cpp
+++ b/3rdparty/bgfx/src/renderer_d3d9.cpp
@@ -214,6 +214,7 @@ namespace bgfx { namespace d3d9
{ D3DFMT_UNKNOWN }, // RG32I
{ D3DFMT_UNKNOWN }, // RG32U
{ D3DFMT_G32R32F }, // RG32F
+ { D3DFMT_UNKNOWN }, // RGB9E5F
{ D3DFMT_A8R8G8B8 }, // BGRA8
{ D3DFMT_UNKNOWN }, // RGBA8
{ D3DFMT_UNKNOWN }, // RGBA8I
@@ -1083,7 +1084,7 @@ namespace bgfx { namespace d3d9
uint8_t flags = predefined.m_type;
setShaderUniform(flags, predefined.m_loc, proj, 4);
- m_textures[_blitter.m_texture.idx].commit(0);
+ m_textures[_blitter.m_texture.idx].commit(0, BGFX_SAMPLER_DEFAULT_FLAGS, NULL);
}
void blitRender(TextVideoMemBlitter& _blitter, uint32_t _numIndices) BX_OVERRIDE
@@ -1420,7 +1421,7 @@ namespace bgfx { namespace d3d9
}
}
- static void setSamplerState(IDirect3DDevice9* _device, DWORD _stage, D3DSAMPLERSTATETYPE _type,DWORD _value)
+ static void setSamplerState(IDirect3DDevice9* _device, DWORD _stage, D3DSAMPLERSTATETYPE _type, DWORD _value)
{
DX_CHECK(_device->SetSamplerState(_stage, _type, _value) );
if (4 > _stage)
@@ -1429,7 +1430,7 @@ namespace bgfx { namespace d3d9
}
}
- void setSamplerState(uint8_t _stage, uint32_t _flags)
+ void setSamplerState(uint8_t _stage, uint32_t _flags, const float _rgba[4])
{
const uint32_t flags = _flags&( (~BGFX_TEXTURE_RESERVED_MASK) | BGFX_TEXTURE_SAMPLER_BITS_MASK | BGFX_TEXTURE_SRGB);
BX_CHECK(_stage < BX_COUNTOF(m_samplerFlags), "");
@@ -1445,7 +1446,6 @@ namespace bgfx { namespace d3d9
D3DTEXTUREFILTERTYPE mipFilter = s_textureFilter[(_flags&BGFX_TEXTURE_MIP_MASK)>>BGFX_TEXTURE_MIP_SHIFT];
setSamplerState(device, _stage, D3DSAMP_ADDRESSU, tau);
- setSamplerState(device, _stage, D3DSAMP_ADDRESSU, tau);
setSamplerState(device, _stage, D3DSAMP_ADDRESSV, tav);
setSamplerState(device, _stage, D3DSAMP_ADDRESSW, taw);
setSamplerState(device, _stage, D3DSAMP_MINFILTER, minFilter);
@@ -1453,6 +1453,18 @@ namespace bgfx { namespace d3d9
setSamplerState(device, _stage, D3DSAMP_MIPFILTER, mipFilter);
setSamplerState(device, _stage, D3DSAMP_MAXANISOTROPY, m_maxAnisotropy);
setSamplerState(device, _stage, D3DSAMP_SRGBTEXTURE, 0 != (flags & BGFX_TEXTURE_SRGB) );
+ if (NULL != _rgba)
+ {
+ if (needBorderColor(_flags) )
+ {
+ DWORD bc = D3DCOLOR_COLORVALUE(_rgba[0], _rgba[1], _rgba[2], _rgba[3]);
+ setSamplerState(device
+ , _stage
+ , D3DSAMP_BORDERCOLOR
+ , bc
+ );
+ }
+ }
}
}
@@ -1539,15 +1551,15 @@ namespace bgfx { namespace d3d9
}
}
- void commit(ConstantBuffer& _constantBuffer)
+ void commit(UniformBuffer& _uniformBuffer)
{
- _constantBuffer.reset();
+ _uniformBuffer.reset();
IDirect3DDevice9* device = m_device;
for (;;)
{
- uint32_t opcode = _constantBuffer.read();
+ uint32_t opcode = _uniformBuffer.read();
if (UniformType::End == opcode)
{
@@ -1558,17 +1570,17 @@ namespace bgfx { namespace d3d9
uint16_t loc;
uint16_t num;
uint16_t copy;
- ConstantBuffer::decodeOpcode(opcode, type, loc, num, copy);
+ UniformBuffer::decodeOpcode(opcode, type, loc, num, copy);
const char* data;
if (copy)
{
- data = _constantBuffer.read(g_uniformTypeSize[type]*num);
+ data = _uniformBuffer.read(g_uniformTypeSize[type]*num);
}
else
{
UniformHandle handle;
- memcpy(&handle, _constantBuffer.read(sizeof(UniformHandle) ), sizeof(UniformHandle) );
+ memcpy(&handle, _uniformBuffer.read(sizeof(UniformHandle) ), sizeof(UniformHandle) );
data = (const char*)m_uniforms[handle.idx];
}
@@ -1643,7 +1655,7 @@ namespace bgfx { namespace d3d9
break;
default:
- BX_TRACE("%4d: INVALID 0x%08x, t %d, l %d, n %d, c %d", _constantBuffer.getPos(), opcode, type, loc, num, copy);
+ BX_TRACE("%4d: INVALID 0x%08x, t %d, l %d, n %d, c %d", _uniformBuffer.getPos(), opcode, type, loc, num, copy);
break;
}
#undef CASE_IMPLEMENT_UNIFORM
@@ -1671,7 +1683,7 @@ namespace bgfx { namespace d3d9
{
if (BGFX_CLEAR_COLOR_USE_PALETTE & _clear.m_flags)
{
- uint8_t index = (uint8_t)bx::uint32_min(BGFX_CONFIG_MAX_CLEAR_COLOR_PALETTE-1, _clear.m_index[0]);
+ uint8_t index = (uint8_t)bx::uint32_min(BGFX_CONFIG_MAX_COLOR_PALETTE-1, _clear.m_index[0]);
const float* rgba = _palette[index];
const float rr = rgba[0];
const float gg = rgba[1];
@@ -1810,7 +1822,7 @@ namespace bgfx { namespace d3d9
float mrtClear[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS][4];
for (uint32_t ii = 0; ii < numMrt; ++ii)
{
- uint8_t index = (uint8_t)bx::uint32_min(BGFX_CONFIG_MAX_CLEAR_COLOR_PALETTE-1, _clear.m_index[ii]);
+ uint8_t index = (uint8_t)bx::uint32_min(BGFX_CONFIG_MAX_COLOR_PALETTE-1, _clear.m_index[ii]);
memcpy(mrtClear[ii], _palette[index], 16);
}
@@ -2223,11 +2235,12 @@ namespace bgfx { namespace d3d9
{
const UniformInfo* info = s_renderD3D9->m_uniformReg.find(name);
BX_CHECK(NULL != info, "User defined uniform '%s' is not found, it won't be set.", name);
+
if (NULL != info)
{
if (NULL == m_constantBuffer)
{
- m_constantBuffer = ConstantBuffer::create(1024);
+ m_constantBuffer = UniformBuffer::create(1024);
}
kind = "user";
@@ -2547,8 +2560,6 @@ namespace bgfx { namespace d3d9
void TextureD3D9::create(const Memory* _mem, uint32_t _flags, uint8_t _skip)
{
- m_flags = _flags;
-
ImageContainer imageContainer;
if (imageParse(imageContainer, _mem->data, _mem->size) )
@@ -2560,6 +2571,7 @@ namespace bgfx { namespace d3d9
const uint32_t textureWidth = bx::uint32_max(blockInfo.blockWidth, imageContainer.m_width >>startLod);
const uint32_t textureHeight = bx::uint32_max(blockInfo.blockHeight, imageContainer.m_height>>startLod);
+ m_flags = _flags;
m_requestedFormat = imageContainer.m_format;
m_textureFormat = imageContainer.m_format;
@@ -2692,7 +2704,7 @@ namespace bgfx { namespace d3d9
{
uint32_t slicePitch;
s_renderD3D9->m_updateTextureSide = _side;
- s_renderD3D9->m_updateTextureMip = _mip;
+ s_renderD3D9->m_updateTextureMip = _mip;
s_renderD3D9->m_updateTextureBits = lock(_side, _mip, s_renderD3D9->m_updateTexturePitch, slicePitch);
}
@@ -2743,11 +2755,15 @@ namespace bgfx { namespace d3d9
unlock(s_renderD3D9->m_updateTextureSide, s_renderD3D9->m_updateTextureMip);
}
- void TextureD3D9::commit(uint8_t _stage, uint32_t _flags)
+ void TextureD3D9::commit(uint8_t _stage, uint32_t _flags, const float _palette[][4])
{
- s_renderD3D9->setSamplerState(_stage
- , 0 == (BGFX_SAMPLER_DEFAULT_FLAGS & _flags) ? _flags : m_flags
- );
+ uint32_t flags = 0 == (BGFX_SAMPLER_DEFAULT_FLAGS & _flags)
+ ? _flags
+ : m_flags
+ ;
+ uint32_t index = (flags & BGFX_TEXTURE_BORDER_COLOR_MASK) >> BGFX_TEXTURE_BORDER_COLOR_SHIFT;
+ s_renderD3D9->setSamplerState(_stage, flags, _palette[index]);
+
IDirect3DDevice9* device = s_renderD3D9->m_device;
DX_CHECK(device->SetTexture(_stage, m_ptr) );
if (4 > _stage)
@@ -3267,7 +3283,7 @@ namespace bgfx { namespace d3d9
if (BGFX_CLEAR_NONE != (clear.m_flags & BGFX_CLEAR_MASK) )
{
- clearQuad(_clearQuad, viewState.m_rect, clear, _render->m_clearColor);
+ clearQuad(_clearQuad, viewState.m_rect, clear, _render->m_colorPalette);
prim = s_primInfo[BX_COUNTOF(s_primName)]; // Force primitive type update after clear quad.
}
@@ -3481,7 +3497,7 @@ namespace bgfx { namespace d3d9
bool programChanged = false;
bool constantsChanged = draw.m_constBegin < draw.m_constEnd;
- rendererUpdateUniforms(this, _render->m_constantBuffer, draw.m_constBegin, draw.m_constEnd);
+ rendererUpdateUniforms(this, _render->m_uniformBuffer, draw.m_constBegin, draw.m_constEnd);
if (key.m_program != programIdx)
{
@@ -3509,13 +3525,13 @@ namespace bgfx { namespace d3d9
if (constantsChanged)
{
- ConstantBuffer* vcb = program.m_vsh->m_constantBuffer;
+ UniformBuffer* vcb = program.m_vsh->m_constantBuffer;
if (NULL != vcb)
{
commit(*vcb);
}
- ConstantBuffer* fcb = program.m_fsh->m_constantBuffer;
+ UniformBuffer* fcb = program.m_fsh->m_constantBuffer;
if (NULL != fcb)
{
commit(*fcb);
@@ -3536,7 +3552,7 @@ namespace bgfx { namespace d3d9
{
if (invalidHandle != bind.m_idx)
{
- m_textures[bind.m_idx].commit(stage, bind.m_un.m_draw.m_flags);
+ m_textures[bind.m_idx].commit(stage, bind.m_un.m_draw.m_flags, _render->m_colorPalette);
}
else
{
@@ -3801,7 +3817,7 @@ namespace bgfx { namespace d3d9
}
tvm.printf(10, pos++, 0x8e, " Indices: %7d ", statsNumIndices);
- tvm.printf(10, pos++, 0x8e, " Uniform size: %7d ", _render->m_constEnd);
+ tvm.printf(10, pos++, 0x8e, " Uniform size: %7d, Max: %7d ", _render->m_uniformEnd, _render->m_uniformMax);
tvm.printf(10, pos++, 0x8e, " DVB size: %7d ", _render->m_vboffset);
tvm.printf(10, pos++, 0x8e, " DIB size: %7d ", _render->m_iboffset);
diff --git a/3rdparty/bgfx/src/renderer_d3d9.h b/3rdparty/bgfx/src/renderer_d3d9.h
index 9fc67766e3f..58676cec900 100644
--- a/3rdparty/bgfx/src/renderer_d3d9.h
+++ b/3rdparty/bgfx/src/renderer_d3d9.h
@@ -245,7 +245,7 @@ namespace bgfx { namespace d3d9
{
if (NULL != m_constantBuffer)
{
- ConstantBuffer::destroy(m_constantBuffer);
+ UniformBuffer::destroy(m_constantBuffer);
m_constantBuffer = NULL;
}
m_numPredefined = 0;
@@ -263,7 +263,7 @@ namespace bgfx { namespace d3d9
IDirect3DVertexShader9* m_vertexShader;
IDirect3DPixelShader9* m_pixelShader;
};
- ConstantBuffer* m_constantBuffer;
+ UniformBuffer* m_constantBuffer;
PredefinedUniform m_predefined[PredefinedUniform::Count];
uint8_t m_numPredefined;
uint8_t m_type;
@@ -334,7 +334,7 @@ namespace bgfx { namespace d3d9
void updateBegin(uint8_t _side, uint8_t _mip);
void update(uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem);
void updateEnd();
- void commit(uint8_t _stage, uint32_t _flags = BGFX_SAMPLER_DEFAULT_FLAGS);
+ void commit(uint8_t _stage, uint32_t _flags, const float _palette[][4]);
void resolve() const;
void preReset();
diff --git a/3rdparty/bgfx/src/renderer_gl.cpp b/3rdparty/bgfx/src/renderer_gl.cpp
index 9527346aed1..557614ef960 100644
--- a/3rdparty/bgfx/src/renderer_gl.cpp
+++ b/3rdparty/bgfx/src/renderer_gl.cpp
@@ -232,6 +232,7 @@ namespace bgfx { namespace gl
{ GL_RG32I, GL_ZERO, GL_RG, GL_INT, false }, // RG32I
{ GL_RG32UI, GL_ZERO, GL_RG, GL_UNSIGNED_INT, false }, // RG32U
{ GL_RG32F, GL_ZERO, GL_RG, GL_FLOAT, false }, // RG32F
+ { GL_RGB9_E5, GL_ZERO, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, false }, // RGB9E5F
{ GL_RGBA8, GL_SRGB8_ALPHA8, GL_BGRA, GL_UNSIGNED_BYTE, false }, // BGRA8
{ GL_RGBA8, GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, false }, // RGBA8
{ GL_RGBA8I, GL_ZERO, GL_RGBA, GL_BYTE, false }, // RGBA8I
@@ -310,6 +311,7 @@ namespace bgfx { namespace gl
GL_RG32I, // RG32I
GL_RG32UI, // RG32U
GL_RG32F, // RG32F
+ GL_RGB9_E5, // RGB9E5F
GL_RGBA8, // BGRA8
GL_RGBA8, // RGBA8
GL_RGBA8I, // RGBA8I
@@ -386,6 +388,7 @@ namespace bgfx { namespace gl
GL_RG32I, // RG32I
GL_RG32UI, // RG32U
GL_RG32F, // RG32F
+ GL_RGB9_E5, // RGB9E5F
GL_RGBA8, // BGRA8
GL_RGBA8, // RGBA8
GL_RGBA8I, // RGBA8I
@@ -522,6 +525,7 @@ namespace bgfx { namespace gl
EXT_texture_filter_anisotropic,
EXT_texture_format_BGRA8888,
EXT_texture_rg,
+ EXT_texture_shared_exponent,
EXT_texture_snorm,
EXT_texture_sRGB,
EXT_texture_storage,
@@ -720,6 +724,7 @@ namespace bgfx { namespace gl
{ "EXT_texture_filter_anisotropic", false, true },
{ "EXT_texture_format_BGRA8888", false, true },
{ "EXT_texture_rg", false, true }, // GLES2 extension.
+ { "EXT_texture_shared_exponent", false, true },
{ "EXT_texture_snorm", BGFX_CONFIG_RENDERER_OPENGL >= 30, true },
{ "EXT_texture_sRGB", false, true },
{ "EXT_texture_storage", false, true },
@@ -1034,7 +1039,7 @@ namespace bgfx { namespace gl
;
GLsizei size = (16*16*getBitsPerPixel(_format) )/8;
- void* data = alloca(size);
+ void* data = bx::alignPtr(alloca(size+16), 0, 16);
if (isCompressed(_format) )
{
@@ -1053,8 +1058,7 @@ namespace bgfx { namespace gl
? tfi.m_internalFmtSrgb
: tfi.m_internalFmt
;
- if (!s_textureFormat[_format].m_supported
- || GL_ZERO == internalFmt)
+ if (GL_ZERO == internalFmt)
{
return false;
}
@@ -1194,6 +1198,7 @@ namespace bgfx { namespace gl
, m_vaoSupport(false)
, m_samplerObjectSupport(false)
, m_shadowSamplersSupport(false)
+ , m_borderColorSupport(BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGL) )
, m_programBinarySupport(false)
, m_textureSwizzleSupport(false)
, m_depthTextureSupport(false)
@@ -1372,13 +1377,6 @@ namespace bgfx { namespace gl
// Allow all texture filters.
memset(s_textureFilter, true, BX_COUNTOF(s_textureFilter) );
- for (uint32_t ii = 0; ii < TextureFormat::Count; ++ii)
- {
- s_textureFormat[ii].m_supported = true
- && TextureFormat::Unknown != ii
- && TextureFormat::UnknownDepth != ii
- ;
- }
bool bc123Supported = 0
|| s_extension[Extension::EXT_texture_compression_s3tc ].m_supported
@@ -1556,7 +1554,10 @@ namespace bgfx { namespace gl
s_textureFormat[TextureFormat::R8].m_fmt = GL_LUMINANCE;
}
- for (uint32_t ii = 0; ii < TextureFormat::Count; ++ii)
+ for (uint32_t ii = BX_ENABLED(BX_PLATFORM_IOS) ? TextureFormat::Unknown : 0 // skip test on iOS!
+ ; ii < TextureFormat::Count
+ ; ++ii
+ )
{
if (TextureFormat::Unknown != ii
&& TextureFormat::UnknownDepth != ii)
@@ -1782,6 +1783,7 @@ namespace bgfx { namespace gl
if (BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGLES) )
{
+ m_borderColorSupport = s_extension[Extension::NV_texture_border_clamp].m_supported;
s_textureAddress[BGFX_TEXTURE_U_BORDER>>BGFX_TEXTURE_U_SHIFT] = s_extension[Extension::NV_texture_border_clamp].m_supported
? GL_CLAMP_TO_BORDER
: GL_CLAMP_TO_EDGE
@@ -2517,21 +2519,53 @@ namespace bgfx { namespace gl
}
}
- void setSamplerState(uint32_t _stage, uint32_t _numMips, uint32_t _flags)
+ void setSamplerState(uint32_t _stage, uint32_t _numMips, uint32_t _flags, const float _rgba[4])
{
if (BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGL)
|| BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGLES >= 30) )
{
if (0 == (BGFX_SAMPLER_DEFAULT_FLAGS & _flags) )
{
+ const uint32_t index = (_flags & BGFX_TEXTURE_BORDER_COLOR_MASK) >> BGFX_TEXTURE_BORDER_COLOR_SHIFT;
+
_flags &= ~BGFX_TEXTURE_RESERVED_MASK;
_flags &= BGFX_TEXTURE_SAMPLER_BITS_MASK;
_flags |= _numMips<<BGFX_TEXTURE_RESERVED_SHIFT;
- GLuint sampler = m_samplerStateCache.find(_flags);
+
+ GLuint sampler;
+
+ bool hasBorderColor = false;
+ bx::HashMurmur2A murmur;
+ uint32_t hash;
+
+ murmur.begin();
+ murmur.add(_flags);
+ if (!needBorderColor(_flags) )
+ {
+ murmur.add(-1);
+ hash = murmur.end();
+
+ sampler = m_samplerStateCache.find(hash);
+ }
+ else
+ {
+ murmur.add(index);
+ hash = murmur.end();
+
+ if (NULL != _rgba)
+ {
+ hasBorderColor = true;
+ sampler = UINT32_MAX;
+ }
+ else
+ {
+ sampler = m_samplerStateCache.find(hash);
+ }
+ }
if (UINT32_MAX == sampler)
{
- sampler = m_samplerStateCache.add(_flags);
+ sampler = m_samplerStateCache.add(hash);
GL_CHECK(glSamplerParameteri(sampler
, GL_TEXTURE_WRAP_S
@@ -2552,8 +2586,14 @@ namespace bgfx { namespace gl
GL_CHECK(glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, magFilter) );
GL_CHECK(glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, minFilter) );
- const float color[] = { 0.0f, 0.0f, 0.0f, 0.0f };
- GL_CHECK(glSamplerParameterfv(sampler, GL_TEXTURE_BORDER_COLOR, color) );
+ if (BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGL)
+ || m_borderColorSupport)
+ {
+ if (hasBorderColor)
+ {
+ GL_CHECK(glSamplerParameterfv(sampler, GL_TEXTURE_BORDER_COLOR, _rgba) );
+ }
+ }
if (0 != (_flags & (BGFX_TEXTURE_MIN_ANISOTROPIC|BGFX_TEXTURE_MAG_ANISOTROPIC) )
&& 0.0f < m_maxAnisotropy)
@@ -2767,13 +2807,13 @@ namespace bgfx { namespace gl
}
}
- void commit(ConstantBuffer& _constantBuffer)
+ void commit(UniformBuffer& _uniformBuffer)
{
- _constantBuffer.reset();
+ _uniformBuffer.reset();
for (;;)
{
- uint32_t opcode = _constantBuffer.read();
+ uint32_t opcode = _uniformBuffer.read();
if (UniformType::End == opcode)
{
@@ -2784,21 +2824,21 @@ namespace bgfx { namespace gl
uint16_t ignore;
uint16_t num;
uint16_t copy;
- ConstantBuffer::decodeOpcode(opcode, type, ignore, num, copy);
+ UniformBuffer::decodeOpcode(opcode, type, ignore, num, copy);
const char* data;
if (copy)
{
- data = _constantBuffer.read(g_uniformTypeSize[type]*num);
+ data = _uniformBuffer.read(g_uniformTypeSize[type]*num);
}
else
{
UniformHandle handle;
- memcpy(&handle, _constantBuffer.read(sizeof(UniformHandle) ), sizeof(UniformHandle) );
+ memcpy(&handle, _uniformBuffer.read(sizeof(UniformHandle) ), sizeof(UniformHandle) );
data = (const char*)m_uniforms[handle.idx];
}
- uint32_t loc = _constantBuffer.read();
+ uint32_t loc = _uniformBuffer.read();
#define CASE_IMPLEMENT_UNIFORM(_uniform, _glsuffix, _dxsuffix, _type) \
case UniformType::_uniform: \
@@ -2835,7 +2875,7 @@ namespace bgfx { namespace gl
break;
default:
- BX_TRACE("%4d: INVALID 0x%08x, t %d, l %d, n %d, c %d", _constantBuffer.getPos(), opcode, type, loc, num, copy);
+ BX_TRACE("%4d: INVALID 0x%08x, t %d, l %d, n %d, c %d", _uniformBuffer.getPos(), opcode, type, loc, num, copy);
break;
}
@@ -2862,7 +2902,7 @@ namespace bgfx { namespace gl
{
if (BGFX_CLEAR_COLOR_USE_PALETTE & _clear.m_flags)
{
- uint8_t index = (uint8_t)bx::uint32_min(BGFX_CONFIG_MAX_CLEAR_COLOR_PALETTE-1, _clear.m_index[0]);
+ uint8_t index = (uint8_t)bx::uint32_min(BGFX_CONFIG_MAX_COLOR_PALETTE-1, _clear.m_index[0]);
const float* rgba = _palette[index];
const float rr = rgba[0];
const float gg = rgba[1];
@@ -2987,7 +3027,7 @@ namespace bgfx { namespace gl
float mrtClear[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS][4];
for (uint32_t ii = 0; ii < numMrt; ++ii)
{
- uint8_t index = (uint8_t)bx::uint32_min(BGFX_CONFIG_MAX_CLEAR_COLOR_PALETTE-1, _clear.m_index[ii]);
+ uint8_t index = (uint8_t)bx::uint32_min(BGFX_CONFIG_MAX_COLOR_PALETTE-1, _clear.m_index[ii]);
memcpy(mrtClear[ii], _palette[index], 16);
}
@@ -3047,6 +3087,7 @@ namespace bgfx { namespace gl
bool m_vaoSupport;
bool m_samplerObjectSupport;
bool m_shadowSamplersSupport;
+ bool m_borderColorSupport;
bool m_programBinarySupport;
bool m_textureSwizzleSupport;
bool m_depthTextureSupport;
@@ -3295,7 +3336,7 @@ namespace bgfx { namespace gl
{
if (NULL != m_constantBuffer)
{
- ConstantBuffer::destroy(m_constantBuffer);
+ UniformBuffer::destroy(m_constantBuffer);
m_constantBuffer = NULL;
}
m_numPredefined = 0;
@@ -3476,11 +3517,13 @@ namespace bgfx { namespace gl
else
{
const UniformInfo* info = s_renderGL->m_uniformReg.find(name);
+ BX_WARN(NULL != info, "User defined uniform '%s' is not found, it won't be set.", name);
+
if (NULL != info)
{
if (NULL == m_constantBuffer)
{
- m_constantBuffer = ConstantBuffer::create(1024);
+ m_constantBuffer = UniformBuffer::create(1024);
}
UniformType::Enum type = convertGlType(gltype);
@@ -3719,7 +3762,7 @@ namespace bgfx { namespace gl
m_width = _width;
m_height = _height;
m_depth = _depth;
- m_currentFlags = UINT32_MAX;
+ m_currentSamplerHash = UINT32_MAX;
m_requestedFormat = _format;
m_textureFormat = _format;
@@ -3779,7 +3822,7 @@ namespace bgfx { namespace gl
}
}
- setSamplerState(_flags);
+ setSamplerState(_flags, NULL);
if (BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGL)
&& TextureFormat::BGRA8 == m_requestedFormat
@@ -4156,7 +4199,7 @@ namespace bgfx { namespace gl
}
}
- void TextureGL::setSamplerState(uint32_t _flags)
+ void TextureGL::setSamplerState(uint32_t _flags, const float _rgba[4])
{
if (BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGLES < 30)
&& !s_textureFilter[m_textureFormat])
@@ -4175,9 +4218,26 @@ namespace bgfx { namespace gl
}
const uint32_t flags = (0 != (BGFX_SAMPLER_DEFAULT_FLAGS & _flags) ? m_flags : _flags) & BGFX_TEXTURE_SAMPLER_BITS_MASK;
- if (flags != m_currentFlags)
+
+ bool hasBorderColor = false;
+ bx::HashMurmur2A murmur;
+ murmur.begin();
+ murmur.add(flags);
+ if (NULL != _rgba)
{
- const GLenum target = m_target;
+ if (BGFX_TEXTURE_U_BORDER == (flags & BGFX_TEXTURE_U_BORDER)
+ || BGFX_TEXTURE_V_BORDER == (flags & BGFX_TEXTURE_V_BORDER)
+ || BGFX_TEXTURE_W_BORDER == (flags & BGFX_TEXTURE_W_BORDER) )
+ {
+ murmur.add(_rgba, 16);
+ hasBorderColor = true;
+ }
+ }
+ uint32_t hash = murmur.end();
+
+ if (hash != m_currentSamplerHash)
+ {
+ const GLenum target = m_target;
const uint8_t numMips = m_numMips;
GL_CHECK(glTexParameteri(target, GL_TEXTURE_WRAP_S, s_textureAddress[(flags&BGFX_TEXTURE_U_MASK)>>BGFX_TEXTURE_U_SHIFT]) );
@@ -4200,8 +4260,14 @@ namespace bgfx { namespace gl
GL_CHECK(glTexParameteri(target, GL_TEXTURE_MAG_FILTER, magFilter) );
GL_CHECK(glTexParameteri(target, GL_TEXTURE_MIN_FILTER, minFilter) );
- const float color[] = { 0.0f, 0.0f, 0.0f, 0.0f };
- GL_CHECK(glTexParameterfv(target, GL_TEXTURE_BORDER_COLOR, color) );
+ if (BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGL)
+ || s_renderGL->m_borderColorSupport)
+ {
+ if (hasBorderColor)
+ {
+ GL_CHECK(glTexParameterfv(target, GL_TEXTURE_BORDER_COLOR, _rgba) );
+ }
+ }
if (0 != (flags & (BGFX_TEXTURE_MIN_ANISOTROPIC|BGFX_TEXTURE_MAG_ANISOTROPIC) )
&& 0.0f < s_renderGL->m_maxAnisotropy)
@@ -4224,12 +4290,18 @@ namespace bgfx { namespace gl
}
}
- m_currentFlags = flags;
+ m_currentSamplerHash = hash;
}
}
- void TextureGL::commit(uint32_t _stage, uint32_t _flags)
+ void TextureGL::commit(uint32_t _stage, uint32_t _flags, const float _palette[][4])
{
+ const uint32_t flags = 0 == (BGFX_SAMPLER_DEFAULT_FLAGS & _flags)
+ ? _flags
+ : m_flags
+ ;
+ const uint32_t index = (flags & BGFX_TEXTURE_BORDER_COLOR_MASK) >> BGFX_TEXTURE_BORDER_COLOR_SHIFT;
+
GL_CHECK(glActiveTexture(GL_TEXTURE0+_stage) );
GL_CHECK(glBindTexture(m_target, m_id) );
@@ -4237,7 +4309,7 @@ namespace bgfx { namespace gl
&& BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGLES < 30) )
{
// GLES2 doesn't have support for sampler object.
- setSamplerState(_flags);
+ setSamplerState(flags, _palette[index]);
}
else if (BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGL)
&& BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGL < 31) )
@@ -4245,17 +4317,17 @@ namespace bgfx { namespace gl
// In case that GL 2.1 sampler object is supported via extension.
if (s_renderGL->m_samplerObjectSupport)
{
- s_renderGL->setSamplerState(_stage, m_numMips, _flags);
+ s_renderGL->setSamplerState(_stage, m_numMips, flags, _palette[index]);
}
else
{
- setSamplerState(_flags);
+ setSamplerState(flags, _palette[index]);
}
}
else
{
// Everything else has sampler object.
- s_renderGL->setSamplerState(_stage, m_numMips, _flags);
+ s_renderGL->setSamplerState(_stage, m_numMips, flags, _palette[index]);
}
}
@@ -5177,7 +5249,7 @@ namespace bgfx { namespace gl
if (BGFX_CLEAR_NONE != (clear.m_flags & BGFX_CLEAR_MASK) )
{
- clearQuad(_clearQuad, viewState.m_rect, clear, height, _render->m_clearColor);
+ clearQuad(_clearQuad, viewState.m_rect, clear, height, _render->m_colorPalette);
}
GL_CHECK(glDisable(GL_STENCIL_TEST) );
@@ -5253,7 +5325,7 @@ namespace bgfx { namespace gl
if (0 != barrier)
{
bool constantsChanged = compute.m_constBegin < compute.m_constEnd;
- rendererUpdateUniforms(this, _render->m_constantBuffer, compute.m_constBegin, compute.m_constEnd);
+ rendererUpdateUniforms(this, _render->m_uniformBuffer, compute.m_constBegin, compute.m_constEnd);
if (constantsChanged
&& NULL != program.m_constantBuffer)
@@ -5609,7 +5681,7 @@ namespace bgfx { namespace gl
bool programChanged = false;
bool constantsChanged = draw.m_constBegin < draw.m_constEnd;
bool bindAttribs = false;
- rendererUpdateUniforms(this, _render->m_constantBuffer, draw.m_constBegin, draw.m_constEnd);
+ rendererUpdateUniforms(this, _render->m_uniformBuffer, draw.m_constBegin, draw.m_constEnd);
if (key.m_program != programIdx)
{
@@ -5649,7 +5721,7 @@ namespace bgfx { namespace gl
if (invalidHandle != bind.m_idx)
{
TextureGL& texture = m_textures[bind.m_idx];
- texture.commit(stage, bind.m_un.m_draw.m_flags);
+ texture.commit(stage, bind.m_un.m_draw.m_flags, _render->m_colorPalette);
}
}
@@ -6072,7 +6144,7 @@ namespace bgfx { namespace gl
}
tvm.printf(10, pos++, 0x8e, " Indices: %7d ", statsNumIndices);
- tvm.printf(10, pos++, 0x8e, " Uniform size: %7d ", _render->m_constEnd);
+ tvm.printf(10, pos++, 0x8e, " Uniform size: %7d, Max: %7d ", _render->m_uniformEnd, _render->m_uniformMax);
tvm.printf(10, pos++, 0x8e, " DVB size: %7d ", _render->m_vboffset);
tvm.printf(10, pos++, 0x8e, " DIB size: %7d ", _render->m_iboffset);
diff --git a/3rdparty/bgfx/src/renderer_gl.h b/3rdparty/bgfx/src/renderer_gl.h
index 734ed29fa03..1a17070d7e6 100644
--- a/3rdparty/bgfx/src/renderer_gl.h
+++ b/3rdparty/bgfx/src/renderer_gl.h
@@ -309,6 +309,14 @@ typedef uint64_t GLuint64;
# define GL_RGBA16UI 0x8D76
#endif // GL_RGBA16UI
+#ifndef GL_RGB9_E5
+# define GL_RGB9_E5 0x8C3D
+#endif // GL_RGB9_E5
+
+#ifndef GL_UNSIGNED_INT_5_9_9_9_REV
+# define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E
+#endif // GL_UNSIGNED_INT_5_9_9_9_REV
+
#ifndef GL_R11F_G11F_B10F
# define GL_R11F_G11F_B10F 0x8C3A
#endif // GL_R11F_G11F_B10F
@@ -807,7 +815,7 @@ typedef uint64_t GLuint64;
namespace bgfx
{
- class ConstantBuffer;
+ class UniformBuffer;
} // namespace bgfx
namespace bgfx { namespace gl
@@ -1074,7 +1082,7 @@ namespace bgfx { namespace gl
, m_fmt(GL_ZERO)
, m_type(GL_ZERO)
, m_flags(0)
- , m_currentFlags(UINT32_MAX)
+ , m_currentSamplerHash(UINT32_MAX)
, m_numMips(0)
{
}
@@ -1083,8 +1091,8 @@ namespace bgfx { namespace gl
void create(const Memory* _mem, uint32_t _flags, uint8_t _skip);
void destroy();
void update(uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem);
- void setSamplerState(uint32_t _flags);
- void commit(uint32_t _stage, uint32_t _flags);
+ void setSamplerState(uint32_t _flags, const float _rgba[4]);
+ void commit(uint32_t _stage, uint32_t _flags, const float _palette[][4]);
GLuint m_id;
GLuint m_rbo;
@@ -1092,7 +1100,7 @@ namespace bgfx { namespace gl
GLenum m_fmt;
GLenum m_type;
uint32_t m_flags;
- uint32_t m_currentFlags;
+ uint32_t m_currentSamplerHash;
uint32_t m_width;
uint32_t m_height;
uint32_t m_depth;
@@ -1174,7 +1182,7 @@ namespace bgfx { namespace gl
GLint m_sampler[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS];
uint8_t m_numSamplers;
- ConstantBuffer* m_constantBuffer;
+ UniformBuffer* m_constantBuffer;
PredefinedUniform m_predefined[PredefinedUniform::Count];
uint8_t m_numPredefined;
VaoCacheRef m_vcref;
diff --git a/3rdparty/bgfx/src/renderer_mtl.h b/3rdparty/bgfx/src/renderer_mtl.h
index 41ba78725ce..495f7abf499 100644
--- a/3rdparty/bgfx/src/renderer_mtl.h
+++ b/3rdparty/bgfx/src/renderer_mtl.h
@@ -13,17 +13,17 @@
#import <QuartzCore/CAMetalLayer.h>
#import <Metal/Metal.h>
-#ifdef BX_PLATFORM_IOS
+#if BX_PLATFORM_IOS
# import <UIKit/UIKit.h>
-#endif // BX_PLATFORM_IOS
+#endif // BX_PLATFORM_*
namespace bgfx { namespace mtl
{
- //c++ wrapper
- // objects with creation functions starting with 'new' has a refcount 1 after creation, object must be destroyed with release.
- // commandBuffer, commandEncoders are autoreleased objects. Needs AutoreleasePool!
+ // c++ wrapper
+ // objects with creation functions starting with 'new' has a refcount 1 after creation, object must be destroyed with release.
+ // commandBuffer, commandEncoders are autoreleased objects. Needs AutoreleasePool!
-#define MTL_CLASS(name) \
+#define MTL_CLASS(name) \
class name \
{ \
public: \
@@ -35,104 +35,200 @@ namespace bgfx { namespace mtl
typedef void (*mtlCallback)(void* userData);
- //TODO: ??MTLBlitCommandEncoder??
MTL_CLASS(Buffer)
- void* contents() { return m_obj.contents; }
- uint32_t length() { return (uint32_t)m_obj.length; }
+ void* contents()
+ {
+ return m_obj.contents;
+ }
+
+ uint32_t length()
+ {
+ return (uint32_t)m_obj.length;
+ }
MTL_CLASS_END
MTL_CLASS(CommandBuffer)
// Creating Command Encoders
- id<MTLRenderCommandEncoder> renderCommandEncoderWithDescriptor( MTLRenderPassDescriptor *_renderPassDescriptor){
+ id<MTLRenderCommandEncoder> renderCommandEncoderWithDescriptor( MTLRenderPassDescriptor* _renderPassDescriptor){
return [m_obj renderCommandEncoderWithDescriptor:_renderPassDescriptor];
}
- id<MTLComputeCommandEncoder> computeCommandEncoder() { return [m_obj computeCommandEncoder]; }
+
+ id<MTLComputeCommandEncoder> computeCommandEncoder()
+ {
+ return [m_obj computeCommandEncoder];
+ }
// Scheduling and Executing Commands
- void enqueue() { [m_obj enqueue]; }
- void commit() { [m_obj commit]; }
- void addCompletedHandler(mtlCallback _cb, void* _data) { [m_obj addCompletedHandler:^(id <MTLCommandBuffer> cmdb){ _cb(_data); }]; }
- void presentDrawable(id<MTLDrawable> _drawable) { [m_obj presentDrawable:_drawable]; }
- void waitUntilCompleted() { [m_obj waitUntilCompleted]; }
+ void enqueue()
+ {
+ [m_obj enqueue];
+ }
+
+ void commit()
+ {
+ [m_obj commit];
+ }
+
+ void addCompletedHandler(mtlCallback _cb, void* _data)
+ {
+ [m_obj addCompletedHandler:^(id <MTLCommandBuffer>){ _cb(_data); }];
+ }
+
+ void presentDrawable(id<MTLDrawable> _drawable)
+ {
+ [m_obj presentDrawable:_drawable];
+ }
+
+ void waitUntilCompleted()
+ {
+ [m_obj waitUntilCompleted];
+ }
MTL_CLASS_END
MTL_CLASS(CommandQueue)
- id<MTLCommandBuffer> commandBuffer() { return [m_obj commandBuffer]; }
- id<MTLCommandBuffer> commandBufferWithUnretainedReferences() { return [m_obj commandBufferWithUnretainedReferences]; }
+ id<MTLCommandBuffer> commandBuffer()
+ {
+ return [m_obj commandBuffer];
+ }
+
+ id<MTLCommandBuffer> commandBufferWithUnretainedReferences()
+ {
+ return [m_obj commandBufferWithUnretainedReferences];
+ }
MTL_CLASS_END
MTL_CLASS(ComputeCommandEncoder)
- void setComputePipelineState(id<MTLComputePipelineState> _state) { [m_obj setComputePipelineState:_state]; }
+ void setComputePipelineState(id<MTLComputePipelineState> _state)
+ {
+ [m_obj setComputePipelineState:_state];
+ }
- void setBuffer(id<MTLBuffer> _buffer, NSUInteger _offset, NSUInteger _index) { [m_obj setBuffer:_buffer offset:_offset atIndex:_index]; }
+ void setBuffer(id<MTLBuffer> _buffer, NSUInteger _offset, NSUInteger _index)
+ {
+ [m_obj setBuffer:_buffer offset:_offset atIndex:_index];
+ }
- void setTexture(id<MTLTexture> _texture, NSUInteger _index) { [m_obj setTexture:_texture atIndex:_index]; }
+ void setTexture(id<MTLTexture> _texture, NSUInteger _index)
+ {
+ [m_obj setTexture:_texture atIndex:_index];
+ }
- void setSamplerState(id<MTLSamplerState> _sampler, NSUInteger _index) { [m_obj setSamplerState:_sampler atIndex:_index]; }
+ void setSamplerState(id<MTLSamplerState> _sampler, NSUInteger _index)
+ {
+ [m_obj setSamplerState:_sampler atIndex:_index];
+ }
- void endEncoding() {[m_obj endEncoding] ;}
+ void endEncoding()
+ {
+ [m_obj endEncoding];
+ }
MTL_CLASS_END
MTL_CLASS(Device)
- bool supportsFeatureSet(MTLFeatureSet _featureSet) { return [m_obj supportsFeatureSet:_featureSet]; }
+ bool supportsFeatureSet(MTLFeatureSet _featureSet)
+ {
+ return [m_obj supportsFeatureSet:_featureSet];
+ }
- id<MTLLibrary> newLibraryWithData(const void* _data) {
+ id<MTLLibrary> newLibraryWithData(const void* _data)
+ {
NSError* error;
id<MTLLibrary> lib = [m_obj newLibraryWithData:(dispatch_data_t)_data error:&error];
- BX_WARN(error==NULL,"newLibraryWithData failed:%s", [error.localizedDescription UTF8String] );
+ BX_WARN(NULL == error
+ , "newLibraryWithData failed: %s"
+ , error.localizedDescription.UTF8String
+ );
return lib;
}
- id<MTLLibrary> newLibraryWithSource(const char* _source) {
+
+ id<MTLLibrary> newLibraryWithSource(const char* _source)
+ {
NSError* error;
id<MTLLibrary> lib = [m_obj newLibraryWithSource:@(_source) options:nil error:&error];
- if (error!=nil) NSLog(@"Shader compilation failed:%@", error.localizedDescription);
//TODO: sometimes prints null as paremeter. string is too large
- BX_WARN(error==NULL,"Shader compilation failed:%s", [error.localizedDescription UTF8String]);
+ BX_WARN(NULL == error
+ , "Shader compilation failed: %s"
+ , error.localizedDescription.UTF8String
+ );
return lib;
}
- id<MTLCommandQueue> newCommandQueue() { return [m_obj newCommandQueue]; }
- id<MTLCommandQueue> newCommandQueueWithMaxCommandBufferCount(NSUInteger _maxCommandBufferCount) { return [m_obj newCommandQueueWithMaxCommandBufferCount:_maxCommandBufferCount]; }
+ id<MTLCommandQueue> newCommandQueue()
+ {
+ return [m_obj newCommandQueue];
+ }
+
+ id<MTLCommandQueue> newCommandQueueWithMaxCommandBufferCount(NSUInteger _maxCommandBufferCount)
+ {
+ return [m_obj newCommandQueueWithMaxCommandBufferCount:_maxCommandBufferCount];
+ }
// Creating Resources
- id<MTLBuffer> newBufferWithLength(unsigned int _length, MTLResourceOptions _options) { return [m_obj newBufferWithLength:_length options:_options ]; }
- id<MTLBuffer> newBufferWithBytes(const void *_pointer, NSUInteger _length, MTLResourceOptions _options) { return [m_obj newBufferWithBytes:_pointer length:_length options:_options]; }
+ id<MTLBuffer> newBufferWithLength(unsigned int _length, MTLResourceOptions _options)
+ {
+ return [m_obj newBufferWithLength:_length options:_options ];
+ }
- id<MTLTexture> newTextureWithDescriptor(MTLTextureDescriptor * _descriptor) { return [m_obj newTextureWithDescriptor:_descriptor]; }
- id<MTLSamplerState> newSamplerStateWithDescriptor(MTLSamplerDescriptor * _descriptor) { return [m_obj newSamplerStateWithDescriptor:_descriptor]; }
+ id<MTLBuffer> newBufferWithBytes(const void* _pointer, NSUInteger _length, MTLResourceOptions _options)
+ {
+ return [m_obj newBufferWithBytes:_pointer length:_length options:_options];
+ }
+
+ id<MTLTexture> newTextureWithDescriptor(MTLTextureDescriptor* _descriptor)
+ {
+ return [m_obj newTextureWithDescriptor:_descriptor];
+ }
+
+ id<MTLSamplerState> newSamplerStateWithDescriptor(MTLSamplerDescriptor* _descriptor)
+ {
+ return [m_obj newSamplerStateWithDescriptor:_descriptor];
+ }
// Creating Command Objects Needed to Render Graphics
- id<MTLDepthStencilState> newDepthStencilStateWithDescriptor(MTLDepthStencilDescriptor * _descriptor) { return [m_obj newDepthStencilStateWithDescriptor:_descriptor]; }
+ id<MTLDepthStencilState> newDepthStencilStateWithDescriptor(MTLDepthStencilDescriptor* _descriptor)
+ {
+ return [m_obj newDepthStencilStateWithDescriptor:_descriptor];
+ }
- id <MTLRenderPipelineState> newRenderPipelineStateWithDescriptor(MTLRenderPipelineDescriptor *_descriptor)
+ id <MTLRenderPipelineState> newRenderPipelineStateWithDescriptor(MTLRenderPipelineDescriptor* _descriptor)
{
- NSError *error;
+ NSError* error;
id <MTLRenderPipelineState> state = [m_obj newRenderPipelineStateWithDescriptor:_descriptor error:&error];
- BX_WARN(error==NULL,"newRenderPipelineStateWithDescriptor failed:%s", [error.localizedDescription UTF8String] );
+ BX_WARN(NULL == error
+ , "newRenderPipelineStateWithDescriptor failed: %s"
+ , error.localizedDescription.UTF8String
+ );
return state;
}
- id <MTLRenderPipelineState> newRenderPipelineStateWithDescriptor(MTLRenderPipelineDescriptor *_descriptor, MTLPipelineOption _options, MTLRenderPipelineReflection** _reflection)
+ id <MTLRenderPipelineState> newRenderPipelineStateWithDescriptor(MTLRenderPipelineDescriptor* _descriptor, MTLPipelineOption _options, MTLRenderPipelineReflection** _reflection)
{
- NSError *error;
+ NSError* error;
id <MTLRenderPipelineState> state = [m_obj newRenderPipelineStateWithDescriptor:_descriptor options:_options reflection:_reflection error:&error];
- BX_WARN(error==NULL,"newRenderPipelineStateWithDescriptor failed:%s", [error.localizedDescription UTF8String] );
+ BX_WARN(NULL == error
+ , "newRenderPipelineStateWithDescriptor failed: %s"
+ , error.localizedDescription.UTF8String
+ );
return state;
}
// Creating Command Objects Needed to Perform Computational Tasks
id <MTLComputePipelineState> newComputePipelineStateWithFunction(id <MTLFunction> _computeFunction)
{
- NSError *error;
+ NSError* error;
id <MTLComputePipelineState> state = [m_obj newComputePipelineStateWithFunction:_computeFunction error:&error];
- BX_WARN(error==NULL,"newComputePipelineStateWithFunction failed:%s", [error.localizedDescription UTF8String] );
+
+ BX_WARN(NULL == error
+ , "newComputePipelineStateWithFunction failed: %s"
+ , error.localizedDescription.UTF8String
+ );
return state;
}
MTL_CLASS_END
MTL_CLASS(Function)
- NSArray *vertexAttributes() { return m_obj.vertexAttributes; }
+ NSArray* vertexAttributes() { return m_obj.vertexAttributes; }
MTL_CLASS_END
MTL_CLASS(Library)
@@ -141,27 +237,92 @@ namespace bgfx { namespace mtl
MTL_CLASS(RenderCommandEncoder)
// Setting Graphics Rendering State
- void setBlendColor(float _red, float _green, float _blue, float _alpha) { [m_obj setBlendColorRed:_red green:_green blue:_blue alpha:_alpha]; }
- void setCullMode(MTLCullMode _cullMode) { [m_obj setCullMode:_cullMode]; }
- void setDepthBias(float _depthBias, float _slopeScale, float _clamp) { [m_obj setDepthBias:_depthBias slopeScale:_slopeScale clamp:_clamp]; }
- void setDepthStencilState(id<MTLDepthStencilState> _depthStencilState) { [m_obj setDepthStencilState:_depthStencilState];}
- void setFrontFacingWinding(MTLWinding _frontFacingWinding) { [m_obj setFrontFacingWinding:_frontFacingWinding]; }
- void setRenderPipelineState(id<MTLRenderPipelineState> _pipelineState) { [m_obj setRenderPipelineState:_pipelineState]; }
- void setScissorRect(MTLScissorRect _rect) { [m_obj setScissorRect:_rect]; }
- void setStencilReferenceValue(uint32_t _ref) { [m_obj setStencilReferenceValue:_ref]; }
- void setTriangleFillMode(MTLTriangleFillMode _fillMode) { [m_obj setTriangleFillMode:_fillMode]; }
- void setViewport(MTLViewport _viewport) { [m_obj setViewport:_viewport]; }
- void setVisibilityResultMode(MTLVisibilityResultMode _mode, NSUInteger _offset) { [m_obj setVisibilityResultMode:_mode offset:_offset]; }
+ void setBlendColor(float _red, float _green, float _blue, float _alpha)
+ {
+ [m_obj setBlendColorRed:_red green:_green blue:_blue alpha:_alpha];
+ }
+
+ void setCullMode(MTLCullMode _cullMode)
+ {
+ [m_obj setCullMode:_cullMode];
+ }
+
+ void setDepthBias(float _depthBias, float _slopeScale, float _clamp)
+ {
+ [m_obj setDepthBias:_depthBias slopeScale:_slopeScale clamp:_clamp];
+ }
+
+ void setDepthStencilState(id<MTLDepthStencilState> _depthStencilState)
+ {
+ [m_obj setDepthStencilState:_depthStencilState];
+ }
+
+ void setFrontFacingWinding(MTLWinding _frontFacingWinding)
+ {
+ [m_obj setFrontFacingWinding:_frontFacingWinding];
+ }
+
+ void setRenderPipelineState(id<MTLRenderPipelineState> _pipelineState)
+ {
+ [m_obj setRenderPipelineState:_pipelineState];
+ }
+
+ void setScissorRect(MTLScissorRect _rect)
+ {
+ [m_obj setScissorRect:_rect];
+ }
+
+ void setStencilReferenceValue(uint32_t _ref)
+ {
+ [m_obj setStencilReferenceValue:_ref];
+ }
+
+ void setTriangleFillMode(MTLTriangleFillMode _fillMode)
+ {
+ [m_obj setTriangleFillMode:_fillMode];
+ }
+
+ void setViewport(MTLViewport _viewport)
+ {
+ [m_obj setViewport:_viewport];
+ }
+
+ void setVisibilityResultMode(MTLVisibilityResultMode _mode, NSUInteger _offset)
+ {
+ [m_obj setVisibilityResultMode:_mode offset:_offset];
+ }
// Specifying Resources for a Vertex Function
- void setVertexBuffer(id<MTLBuffer> _buffer, NSUInteger _offset, NSUInteger _index) { [m_obj setVertexBuffer:_buffer offset:_offset atIndex:_index]; }
- void setVertexSamplerState(id<MTLSamplerState> _sampler, NSUInteger _index) { [m_obj setVertexSamplerState:_sampler atIndex:_index]; }
- void setVertexTexture(id<MTLTexture> _texture, NSUInteger _index) { [m_obj setVertexTexture:_texture atIndex:_index]; }
+ void setVertexBuffer(id<MTLBuffer> _buffer, NSUInteger _offset, NSUInteger _index)
+ {
+ [m_obj setVertexBuffer:_buffer offset:_offset atIndex:_index];
+ }
+
+ void setVertexSamplerState(id<MTLSamplerState> _sampler, NSUInteger _index)
+ {
+ [m_obj setVertexSamplerState:_sampler atIndex:_index];
+ }
+
+ void setVertexTexture(id<MTLTexture> _texture, NSUInteger _index)
+ {
+ [m_obj setVertexTexture:_texture atIndex:_index];
+ }
// Specifying Resources for a Fragment Function
- void setFragmentBuffer(id<MTLBuffer> _buffer, NSUInteger _offset, NSUInteger _index) { [m_obj setFragmentBuffer:_buffer offset:_offset atIndex:_index]; }
- void setFragmentSamplerState(id<MTLSamplerState> _sampler, NSUInteger _index) { [m_obj setFragmentSamplerState:_sampler atIndex:_index]; }
- void setFragmentTexture(id<MTLTexture> _texture, NSUInteger _index) { [m_obj setFragmentTexture:_texture atIndex:_index]; }
+ void setFragmentBuffer(id<MTLBuffer> _buffer, NSUInteger _offset, NSUInteger _index)
+ {
+ [m_obj setFragmentBuffer:_buffer offset:_offset atIndex:_index];
+ }
+
+ void setFragmentSamplerState(id<MTLSamplerState> _sampler, NSUInteger _index)
+ {
+ [m_obj setFragmentSamplerState:_sampler atIndex:_index];
+ }
+
+ void setFragmentTexture(id<MTLTexture> _texture, NSUInteger _index)
+ {
+ [m_obj setFragmentTexture:_texture atIndex:_index];
+ }
//Drawing Geometric Primitives
//NOTE: not exposing functions without instanceCount, it seems they are just wrappers
@@ -170,29 +331,66 @@ namespace bgfx { namespace mtl
[m_obj drawIndexedPrimitives:_primitiveType indexCount:_indexCount indexType:_indexType indexBuffer:_indexBuffer indexBufferOffset:_indexBufferOffset instanceCount:_instanceCount];
}
- void drawPrimitives(MTLPrimitiveType _primitiveType, NSUInteger _vertexStart, NSUInteger _vertexCount, NSUInteger _instanceCount) {
- [m_obj drawPrimitives:_primitiveType vertexStart:_vertexStart vertexCount:_vertexCount instanceCount:_instanceCount];}
+ void drawPrimitives(MTLPrimitiveType _primitiveType, NSUInteger _vertexStart, NSUInteger _vertexCount, NSUInteger _instanceCount)
+ {
+ [m_obj drawPrimitives:_primitiveType vertexStart:_vertexStart vertexCount:_vertexCount instanceCount:_instanceCount];
+ }
- void insertDebugSignpost(const char* _string) { [m_obj insertDebugSignpost:@(_string)]; }
- void pushDebugGroup(const char* _string) { [m_obj pushDebugGroup:@(_string)]; }
- void popDebugGroup() { [m_obj popDebugGroup]; }
+ void insertDebugSignpost(const char* _string)
+ {
+ [m_obj insertDebugSignpost:@(_string)];
+ }
- void endEncoding() { [m_obj endEncoding]; }
+ void pushDebugGroup(const char* _string)
+ {
+ [m_obj pushDebugGroup:@(_string)];
+ }
+
+ void popDebugGroup()
+ {
+ [m_obj popDebugGroup];
+ }
+
+ void endEncoding()
+ {
+ [m_obj endEncoding];
+ }
MTL_CLASS_END
MTL_CLASS(Texture)
// Copying Data into a Texture Image
- void replaceRegion(MTLRegion _region, NSUInteger _level, NSUInteger _slice, const void *_pixelBytes, NSUInteger _bytesPerRow, NSUInteger _bytesPerImage) { [m_obj replaceRegion:_region mipmapLevel:_level slice:_slice withBytes:_pixelBytes bytesPerRow:_bytesPerRow bytesPerImage:_bytesPerImage]; }
+ void replaceRegion(MTLRegion _region, NSUInteger _level, NSUInteger _slice, const void* _pixelBytes, NSUInteger _bytesPerRow, NSUInteger _bytesPerImage)
+ {
+ [m_obj replaceRegion:_region mipmapLevel:_level slice:_slice withBytes:_pixelBytes bytesPerRow:_bytesPerRow bytesPerImage:_bytesPerImage];
+ }
// Copying Data from a Texture Image
- void getBytes(void *_pixelBytes, NSUInteger _bytesPerRow, NSUInteger _bytesPerImage, MTLRegion _region, NSUInteger _mipmapLevel, NSUInteger _slice) { [m_obj getBytes:_pixelBytes bytesPerRow:_bytesPerRow bytesPerImage:_bytesPerImage fromRegion:_region mipmapLevel:_mipmapLevel slice:_slice]; }
+ void getBytes(void* _pixelBytes, NSUInteger _bytesPerRow, NSUInteger _bytesPerImage, MTLRegion _region, NSUInteger _mipmapLevel, NSUInteger _slice)
+ {
+ [m_obj getBytes:_pixelBytes bytesPerRow:_bytesPerRow bytesPerImage:_bytesPerImage fromRegion:_region mipmapLevel:_mipmapLevel slice:_slice];
+ }
// Creating Textures by Reusing Image Data
- id<MTLTexture> newTextureViewWithPixelFormat(MTLPixelFormat _pixelFormat) { return [m_obj newTextureViewWithPixelFormat:_pixelFormat]; }
+ id<MTLTexture> newTextureViewWithPixelFormat(MTLPixelFormat _pixelFormat)
+ {
+ return [m_obj newTextureViewWithPixelFormat:_pixelFormat];
+ }
+
//properties
- uint32_t width() { return (uint32_t)m_obj.width; }
- uint32_t height() { return (uint32_t)m_obj.height; }
- MTLPixelFormat pixelFormat() const { return m_obj.pixelFormat; }
+ uint32_t width()
+ {
+ return (uint32_t)m_obj.width;
+ }
+
+ uint32_t height()
+ {
+ return (uint32_t)m_obj.height;
+ }
+
+ MTLPixelFormat pixelFormat() const
+ {
+ return m_obj.pixelFormat;
+ }
MTL_CLASS_END
typedef id<MTLComputePipelineState> ComputePipelineState;
@@ -200,52 +398,105 @@ namespace bgfx { namespace mtl
typedef id<MTLRenderPipelineState> RenderPipelineState;
typedef id<MTLSamplerState> SamplerState;
- //descriptors
+ //descriptors
//NOTE: [class new] is same as [[class alloc] init]
typedef MTLRenderPipelineDescriptor* RenderPipelineDescriptor;
- RenderPipelineDescriptor newRenderPipelineDescriptor() { return [MTLRenderPipelineDescriptor new]; }
- void reset(RenderPipelineDescriptor _desc) { [_desc reset]; };
+
+ inline RenderPipelineDescriptor newRenderPipelineDescriptor()
+ {
+ return [MTLRenderPipelineDescriptor new];
+ }
+
+ inline void reset(RenderPipelineDescriptor _desc)
+ {
+ [_desc reset];
+ }
typedef MTLRenderPipelineColorAttachmentDescriptor* RenderPipelineColorAttachmentDescriptor;
typedef MTLDepthStencilDescriptor* DepthStencilDescriptor;
- MTLDepthStencilDescriptor* newDepthStencilDescriptor() { return [MTLDepthStencilDescriptor new]; }
+
+ inline MTLDepthStencilDescriptor* newDepthStencilDescriptor()
+ {
+ return [MTLDepthStencilDescriptor new];
+ }
typedef MTLStencilDescriptor* StencilDescriptor;
- MTLStencilDescriptor* newStencilDescriptor() { return [MTLStencilDescriptor new]; }
+
+ inline MTLStencilDescriptor* newStencilDescriptor()
+ {
+ return [MTLStencilDescriptor new];
+ }
typedef MTLRenderPassColorAttachmentDescriptor* RenderPassColorAttachmentDescriptor;
typedef MTLRenderPassDepthAttachmentDescriptor* RenderPassDepthAttachmentDescriptor;
typedef MTLRenderPassStencilAttachmentDescriptor* RenderPassStencilAttachmentDescriptor;
typedef MTLRenderPassDescriptor* RenderPassDescriptor;
- MTLRenderPassDescriptor* newRenderPassDescriptor() { return [MTLRenderPassDescriptor new]; }
+
+ inline MTLRenderPassDescriptor* newRenderPassDescriptor()
+ {
+ return [MTLRenderPassDescriptor new];
+ }
typedef MTLVertexDescriptor* VertexDescriptor;
- MTLVertexDescriptor* newVertexDescriptor() { return [MTLVertexDescriptor new]; }
- void reset(VertexDescriptor _desc) { [_desc reset]; };
+
+ inline MTLVertexDescriptor* newVertexDescriptor()
+ {
+ return [MTLVertexDescriptor new];
+ }
+
+ inline void reset(VertexDescriptor _desc)
+ {
+ [_desc reset];
+ }
typedef MTLSamplerDescriptor* SamplerDescriptor;
- MTLSamplerDescriptor* newSamplerDescriptor() { return [MTLSamplerDescriptor new]; }
+
+ inline MTLSamplerDescriptor* newSamplerDescriptor()
+ {
+ return [MTLSamplerDescriptor new];
+ }
typedef MTLTextureDescriptor* TextureDescriptor;
- MTLTextureDescriptor* newTextureDescriptor() { return [MTLTextureDescriptor new]; }
+
+ inline MTLTextureDescriptor* newTextureDescriptor()
+ {
+ return [MTLTextureDescriptor new];
+ }
typedef MTLRenderPipelineReflection* RenderPipelineReflection;
- //helper functions
- void release(NSObject* _obj) { [_obj release]; }
- void retain(NSObject* _obj) { [_obj retain]; }
- const char* utf8String(NSString* _str) { return [_str UTF8String]; }
+ //helper functions
+ inline void release(NSObject* _obj)
+ {
+ [_obj release];
+ }
+
+ inline void retain(NSObject* _obj)
+ {
+ [_obj retain];
+ }
+
+ inline const char* utf8String(NSString* _str)
+ {
+ return [_str UTF8String];
+ }
-#define MTL_RELEASE(_obj) \
- [_obj release]; \
- _obj = nil;
+#define MTL_RELEASE(_obj) \
+ BX_MACRO_BLOCK_BEGIN \
+ [_obj release]; \
+ _obj = nil; \
+ BX_MACRO_BLOCK_END
-#ifdef BX_PLATFORM_IOS
- bool OsVersionEqualOrGreater(const char* _version) { return ([[[UIDevice currentDevice] systemVersion] compare:@(_version) options:NSNumericSearch] != NSOrderedAscending); }
+#if BX_PLATFORM_IOS
+ inline bool OsVersionEqualOrGreater(const char* _version)
+ {
+ return ([[[UIDevice currentDevice] systemVersion] compare:@(_version) options:NSNumericSearch] != NSOrderedAscending);
+ }
//TODO: this could be in bx ?
-#endif
+#endif //
+
// end of c++ wrapper
template <typename Ty>
@@ -359,20 +610,19 @@ namespace bgfx { namespace mtl
Function m_function;
};
-
struct ProgramMtl
{
ProgramMtl()
: m_vsh(NULL)
, m_fsh(NULL)
- , m_processedUniforms(false)
, m_vshConstantBuffer(NULL)
, m_fshConstantBuffer(NULL)
- , m_numPredefined(0)
, m_vshConstantBufferSize(0)
, m_vshConstantBufferAlignmentMask(0)
, m_fshConstantBufferSize(0)
, m_fshConstantBufferAlignmentMask(0)
+ , m_numPredefined(0)
+ , m_processedUniforms(false)
{
}
@@ -383,22 +633,22 @@ namespace bgfx { namespace mtl
StateCacheT<RenderPipelineState> m_renderPipelineStateCache;
- uint8_t m_used[Attrib::Count+1]; // dense
+ uint8_t m_used[Attrib::Count+1]; // dense
uint32_t m_attributes[Attrib::Count]; // sparse
uint32_t m_instanceData[BGFX_CONFIG_MAX_INSTANCE_DATA_COUNT+1];
const ShaderMtl* m_vsh;
const ShaderMtl* m_fsh;
+ UniformBuffer* m_vshConstantBuffer;
+ UniformBuffer* m_fshConstantBuffer;
- bool m_processedUniforms;
uint32_t m_vshConstantBufferSize;
uint32_t m_vshConstantBufferAlignmentMask;
uint32_t m_fshConstantBufferSize;
uint32_t m_fshConstantBufferAlignmentMask;
- ConstantBuffer* m_fshConstantBuffer;
- ConstantBuffer* m_vshConstantBuffer;
PredefinedUniform m_predefined[PredefinedUniform::Count*2];
uint8_t m_numPredefined;
+ bool m_processedUniforms;
};
struct TextureMtl
@@ -407,8 +657,8 @@ namespace bgfx { namespace mtl
: m_ptr(NULL)
, m_ptrStencil(NULL)
, m_sampler(NULL)
- , m_numMips(0)
, m_flags(0)
+ , m_numMips(0)
{
}
@@ -433,10 +683,9 @@ namespace bgfx { namespace mtl
struct FrameBufferMtl
{
FrameBufferMtl()
- : //m_swapChain(NULL) //TODO: swapchain
- m_denseIdx(UINT16_MAX)
- , m_num(0)
+ : m_denseIdx(UINT16_MAX)
, m_pixelFormatHash(0)
+ , m_num(0)
{
m_depthHandle.idx = invalidHandle;
}
@@ -455,12 +704,11 @@ namespace bgfx { namespace mtl
TextureHandle m_colorHandle[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS-1];
TextureHandle m_depthHandle;
- uint8_t m_num; // number of color handles
+ uint8_t m_num; // number of color handles
};
-
-#endif
-
} /* namespace metal */ } // namespace bgfx
+#endif // BGFX_CONFIG_RENDERER_METAL
+
#endif // BGFX_RENDERER_METAL_H_HEADER_GUARD
diff --git a/3rdparty/bgfx/src/renderer_mtl.mm b/3rdparty/bgfx/src/renderer_mtl.mm
index 78d5810594d..007c2bcb786 100644
--- a/3rdparty/bgfx/src/renderer_mtl.mm
+++ b/3rdparty/bgfx/src/renderer_mtl.mm
@@ -220,6 +220,7 @@ namespace bgfx { namespace mtl
MTLSamplerAddressModeRepeat,
MTLSamplerAddressModeMirrorRepeat,
MTLSamplerAddressModeClampToEdge,
+ MTLSamplerAddressModeClampToZero,
};
static const MTLSamplerMinMagFilter s_textureFilterMinMag[] =
@@ -241,81 +242,80 @@ namespace bgfx { namespace mtl
MTLPixelFormat m_fmtSrgb;
};
- //TODO: add new ios/osx formats
- //TODO: add caps for format support
static TextureFormatInfo s_textureFormat[] =
{
- { MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // BC1
- { MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // BC2
- { MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // BC3
- { MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // BC4
- { MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // BC5
- { MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // BC6H
- { MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // BC7
- { MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // ETC1
- { MTLPixelFormatETC2_RGB8, MTLPixelFormatETC2_RGB8_sRGB }, // ETC2
- { MTLPixelFormatEAC_RGBA8, MTLPixelFormatEAC_RGBA8_sRGB }, // ETC2A
- { MTLPixelFormatETC2_RGB8A1, MTLPixelFormatETC2_RGB8A1_sRGB }, // ETC2A1
- { MTLPixelFormatPVRTC_RGB_2BPP, MTLPixelFormatPVRTC_RGB_2BPP_sRGB }, // PTC12
- { MTLPixelFormatPVRTC_RGB_4BPP, MTLPixelFormatPVRTC_RGB_4BPP_sRGB }, // PTC14
- { MTLPixelFormatPVRTC_RGBA_2BPP, MTLPixelFormatPVRTC_RGBA_2BPP_sRGB }, // PTC12A
- { MTLPixelFormatPVRTC_RGBA_4BPP, MTLPixelFormatPVRTC_RGBA_4BPP_sRGB }, // PTC14A
- { MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // PTC22
- { MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // PTC24
- { MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // Unknown
- { MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // R1
- { MTLPixelFormatA8Unorm, MTLPixelFormatInvalid }, // A8
- { MTLPixelFormatR8Unorm, MTLPixelFormatR8Unorm_sRGB }, // R8
- { MTLPixelFormatR8Sint, MTLPixelFormatInvalid }, // R8I
- { MTLPixelFormatR8Uint, MTLPixelFormatInvalid }, // R8U
- { MTLPixelFormatR8Snorm, MTLPixelFormatInvalid }, // R8S
- { MTLPixelFormatR16Unorm, MTLPixelFormatInvalid }, // R16
- { MTLPixelFormatR16Sint, MTLPixelFormatInvalid }, // R16I
- { MTLPixelFormatR16Uint, MTLPixelFormatInvalid }, // R16U
- { MTLPixelFormatR16Float, MTLPixelFormatInvalid }, // R16F
- { MTLPixelFormatR16Snorm, MTLPixelFormatInvalid }, // R16S
- { MTLPixelFormatR32Sint, MTLPixelFormatInvalid }, // R32I
- { MTLPixelFormatR32Uint, MTLPixelFormatInvalid }, // R32U
- { MTLPixelFormatR32Float, MTLPixelFormatInvalid }, // R32F
- { MTLPixelFormatRG8Unorm, MTLPixelFormatRG8Unorm_sRGB }, // RG8
- { MTLPixelFormatRG8Sint, MTLPixelFormatInvalid }, // RG8I
- { MTLPixelFormatRG8Uint, MTLPixelFormatInvalid }, // RG8U
- { MTLPixelFormatRG8Snorm, MTLPixelFormatInvalid }, // RG8S
- { MTLPixelFormatRG16Unorm, MTLPixelFormatInvalid }, // RG16
- { MTLPixelFormatRG16Sint, MTLPixelFormatInvalid }, // RG16I
- { MTLPixelFormatRG16Uint, MTLPixelFormatInvalid }, // RG16U
- { MTLPixelFormatRG16Float, MTLPixelFormatInvalid }, // RG16F
- { MTLPixelFormatRG16Snorm, MTLPixelFormatInvalid }, // RG16S
- { MTLPixelFormatRG32Sint, MTLPixelFormatInvalid }, // RG32I
- { MTLPixelFormatRG32Uint, MTLPixelFormatInvalid }, // RG32U
- { MTLPixelFormatRG32Float, MTLPixelFormatInvalid }, // RG32F
- { MTLPixelFormatBGRA8Unorm, MTLPixelFormatBGRA8Unorm_sRGB }, // BGRA8
- { MTLPixelFormatRGBA8Unorm, MTLPixelFormatRGBA8Unorm_sRGB }, // RGBA8
- { MTLPixelFormatRGBA8Sint, MTLPixelFormatInvalid }, // RGBA8I
- { MTLPixelFormatRGBA8Uint, MTLPixelFormatInvalid }, // RGBA8U
- { MTLPixelFormatRGBA8Snorm, MTLPixelFormatInvalid }, // RGBA8S
- { MTLPixelFormatRGBA16Unorm, MTLPixelFormatInvalid }, // RGBA16
- { MTLPixelFormatRGBA16Sint, MTLPixelFormatInvalid }, // RGBA16I
- { MTLPixelFormatRGBA16Uint, MTLPixelFormatInvalid }, // RGBA16I
- { MTLPixelFormatRGBA16Float, MTLPixelFormatInvalid }, // RGBA16F
- { MTLPixelFormatRGBA16Snorm, MTLPixelFormatInvalid }, // RGBA16S
- { MTLPixelFormatRGBA32Sint, MTLPixelFormatInvalid }, // RGBA32I
- { MTLPixelFormatRGBA32Uint, MTLPixelFormatInvalid }, // RGBA32U
- { MTLPixelFormatRGBA32Float, MTLPixelFormatInvalid }, // RGBA32F
- { MTLPixelFormatB5G6R5Unorm, MTLPixelFormatInvalid }, // R5G6B5
- { MTLPixelFormatABGR4Unorm, MTLPixelFormatInvalid }, // RGBA4
- { MTLPixelFormatA1BGR5Unorm, MTLPixelFormatInvalid }, // RGB5A1
- { MTLPixelFormatRGB10A2Unorm, MTLPixelFormatInvalid }, // RGB10A2
- { MTLPixelFormatRG11B10Float, MTLPixelFormatInvalid }, // R11G11B10F
- { MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // UnknownDepth
- { MTLPixelFormatDepth32Float, MTLPixelFormatInvalid }, // D16
- { MTLPixelFormatDepth32Float, MTLPixelFormatInvalid }, // D24
- { MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // D24S8
- { MTLPixelFormatDepth32Float, MTLPixelFormatInvalid }, // D32
- { MTLPixelFormatDepth32Float, MTLPixelFormatInvalid }, // D16F
- { MTLPixelFormatDepth32Float, MTLPixelFormatInvalid }, // D24F
- { MTLPixelFormatDepth32Float, MTLPixelFormatInvalid }, // D32F
- { MTLPixelFormatStencil8, MTLPixelFormatInvalid }, // D0S8
+ { MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // BC1
+ { MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // BC2
+ { MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // BC3
+ { MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // BC4
+ { MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // BC5
+ { MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // BC6H
+ { MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // BC7
+ { MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // ETC1
+ { 180 /*MTLPixelFormatETC2_RGB8*/, 181 /*MTLPixelFormatETC2_RGB8_sRGB*/ }, // ETC2
+ { 178 /*MTLPixelFormatEAC_RGBA8*/, 179 /*MTLPixelFormatEAC_RGBA8_sRGB*/ }, // ETC2A
+ { 182 /*MTLPixelFormatETC2_RGB8A1*/, 183 /*MTLPixelFormatETC2_RGB8A1_sRGB*/ }, // ETC2A1
+ { 160 /*MTLPixelFormatPVRTC_RGB_2BPP*/, 161 /*MTLPixelFormatPVRTC_RGB_2BPP_sRGB*/ }, // PTC12
+ { 162 /*MTLPixelFormatPVRTC_RGB_4BPP*/, 163 /*MTLPixelFormatPVRTC_RGB_4BPP_sRGB*/ }, // PTC14
+ { 164 /*MTLPixelFormatPVRTC_RGBA_2BPP*/, 165 /*MTLPixelFormatPVRTC_RGBA_2BPP_sRGB*/ }, // PTC12A
+ { 166 /*MTLPixelFormatPVRTC_RGBA_4BPP*/, 167 /*MTLPixelFormatPVRTC_RGBA_4BPP_sRGB*/ }, // PTC14A
+ { MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // PTC22
+ { MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // PTC24
+ { MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // Unknown
+ { MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // R1
+ { MTLPixelFormatA8Unorm, MTLPixelFormatInvalid }, // A8
+ { MTLPixelFormatR8Unorm, 11 /*MTLPixelFormatR8Unorm_sRGB*/ }, // R8
+ { MTLPixelFormatR8Sint, MTLPixelFormatInvalid }, // R8I
+ { MTLPixelFormatR8Uint, MTLPixelFormatInvalid }, // R8U
+ { MTLPixelFormatR8Snorm, MTLPixelFormatInvalid }, // R8S
+ { MTLPixelFormatR16Unorm, MTLPixelFormatInvalid }, // R16
+ { MTLPixelFormatR16Sint, MTLPixelFormatInvalid }, // R16I
+ { MTLPixelFormatR16Uint, MTLPixelFormatInvalid }, // R16U
+ { MTLPixelFormatR16Float, MTLPixelFormatInvalid }, // R16F
+ { MTLPixelFormatR16Snorm, MTLPixelFormatInvalid }, // R16S
+ { MTLPixelFormatR32Sint, MTLPixelFormatInvalid }, // R32I
+ { MTLPixelFormatR32Uint, MTLPixelFormatInvalid }, // R32U
+ { MTLPixelFormatR32Float, MTLPixelFormatInvalid }, // R32F
+ { MTLPixelFormatRG8Unorm, 31 /*MTLPixelFormatRG8Unorm_sRGB*/ }, // RG8
+ { MTLPixelFormatRG8Sint, MTLPixelFormatInvalid }, // RG8I
+ { MTLPixelFormatRG8Uint, MTLPixelFormatInvalid }, // RG8U
+ { MTLPixelFormatRG8Snorm, MTLPixelFormatInvalid }, // RG8S
+ { MTLPixelFormatRG16Unorm, MTLPixelFormatInvalid }, // RG16
+ { MTLPixelFormatRG16Sint, MTLPixelFormatInvalid }, // RG16I
+ { MTLPixelFormatRG16Uint, MTLPixelFormatInvalid }, // RG16U
+ { MTLPixelFormatRG16Float, MTLPixelFormatInvalid }, // RG16F
+ { MTLPixelFormatRG16Snorm, MTLPixelFormatInvalid }, // RG16S
+ { MTLPixelFormatRG32Sint, MTLPixelFormatInvalid }, // RG32I
+ { MTLPixelFormatRG32Uint, MTLPixelFormatInvalid }, // RG32U
+ { MTLPixelFormatRG32Float, MTLPixelFormatInvalid }, // RG32F
+ { MTLPixelFormatRGB9E5Float, MTLPixelFormatInvalid }, // RGB9E5F
+ { MTLPixelFormatBGRA8Unorm, MTLPixelFormatBGRA8Unorm_sRGB }, // BGRA8
+ { MTLPixelFormatRGBA8Unorm, MTLPixelFormatRGBA8Unorm_sRGB }, // RGBA8
+ { MTLPixelFormatRGBA8Sint, MTLPixelFormatInvalid }, // RGBA8I
+ { MTLPixelFormatRGBA8Uint, MTLPixelFormatInvalid }, // RGBA8U
+ { MTLPixelFormatRGBA8Snorm, MTLPixelFormatInvalid }, // RGBA8S
+ { MTLPixelFormatRGBA16Unorm, MTLPixelFormatInvalid }, // RGBA16
+ { MTLPixelFormatRGBA16Sint, MTLPixelFormatInvalid }, // RGBA16I
+ { MTLPixelFormatRGBA16Uint, MTLPixelFormatInvalid }, // RGBA16I
+ { MTLPixelFormatRGBA16Float, MTLPixelFormatInvalid }, // RGBA16F
+ { MTLPixelFormatRGBA16Snorm, MTLPixelFormatInvalid }, // RGBA16S
+ { MTLPixelFormatRGBA32Sint, MTLPixelFormatInvalid }, // RGBA32I
+ { MTLPixelFormatRGBA32Uint, MTLPixelFormatInvalid }, // RGBA32U
+ { MTLPixelFormatRGBA32Float, MTLPixelFormatInvalid }, // RGBA32F
+ { 40 /*MTLPixelFormatB5G6R5Unorm*/, MTLPixelFormatInvalid }, // R5G6B5
+ { 42 /*MTLPixelFormatABGR4Unorm*/, MTLPixelFormatInvalid }, // RGBA4
+ { 41 /*MTLPixelFormatA1BGR5Unorm*/, MTLPixelFormatInvalid }, // RGB5A1
+ { MTLPixelFormatRGB10A2Unorm, MTLPixelFormatInvalid }, // RGB10A2
+ { MTLPixelFormatRG11B10Float, MTLPixelFormatInvalid }, // R11G11B10F
+ { MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // UnknownDepth
+ { MTLPixelFormatDepth32Float, MTLPixelFormatInvalid }, // D16
+ { MTLPixelFormatDepth32Float, MTLPixelFormatInvalid }, // D24
+ { MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // D24S8
+ { MTLPixelFormatDepth32Float, MTLPixelFormatInvalid }, // D32
+ { MTLPixelFormatDepth32Float, MTLPixelFormatInvalid }, // D16F
+ { MTLPixelFormatDepth32Float, MTLPixelFormatInvalid }, // D24F
+ { MTLPixelFormatDepth32Float, MTLPixelFormatInvalid }, // D32F
+ { MTLPixelFormatStencil8, MTLPixelFormatInvalid }, // D0S8
};
BX_STATIC_ASSERT(TextureFormat::Count == BX_COUNTOF(s_textureFormat) );
@@ -325,12 +325,12 @@ namespace bgfx { namespace mtl
struct RendererContextMtl : public RendererContextI
{
RendererContextMtl()
- : m_numWindows(1),
- m_metalLayer(NULL),
- m_drawable(NULL),
- m_maxAnisotropy(1),
- m_rtMsaa(false),
- m_backBufferPixelFormatHash(0)
+ : m_metalLayer(NULL)
+ , m_backBufferPixelFormatHash(0)
+ , m_maxAnisotropy(1)
+ , m_numWindows(1)
+ , m_rtMsaa(false)
+ , m_drawable(NULL)
{
m_fbh.idx = invalidHandle;
}
@@ -341,12 +341,15 @@ namespace bgfx { namespace mtl
bool init()
{
- if ( NSClassFromString(@"CAMetalLayer") != nil)
+ BX_TRACE("Init.");
+
+ if (NULL != NSClassFromString(@"CAMetalLayer") )
{
//on iOS we need the layer as CAmetalLayer
#if BX_PLATFORM_IOS
CAMetalLayer* metalLayer = (CAMetalLayer*)g_platformData.nwh;
- if (metalLayer == nil || ![metalLayer isKindOfClass:NSClassFromString(@"CAMetalLayer")])
+ if (NULL == metalLayer
+ || ![metalLayer isKindOfClass:NSClassFromString(@"CAMetalLayer")])
{
BX_WARN(NULL != m_device, "Unable to create Metal device. Please set platform data window to a CAMetalLayer");
return false;
@@ -369,22 +372,24 @@ namespace bgfx { namespace mtl
}
}
- if (m_device==NULL || m_metalLayer==nil)
+ if (NULL == m_device
+ || NULL == m_metalLayer)
{
BX_WARN(NULL != m_device, "Unable to create Metal device.");
return false;
}
- m_metalLayer.device = m_device;
+ m_metalLayer.device = m_device;
+ m_metalLayer.pixelFormat = MTLPixelFormatBGRA8Unorm;
m_commandQueue = m_device.newCommandQueue();
BGFX_FATAL(NULL != m_commandQueue, Fatal::UnableToInitialize, "Unable to create Metal device.");
- m_renderPipelineDescriptor = newRenderPipelineDescriptor();
- m_depthStencilDescriptor = newDepthStencilDescriptor();
+ m_renderPipelineDescriptor = newRenderPipelineDescriptor();
+ m_depthStencilDescriptor = newDepthStencilDescriptor();
m_frontFaceStencilDescriptor = newStencilDescriptor();
- m_backFaceStencilDescriptor = newStencilDescriptor();
- m_vertexDescriptor = newVertexDescriptor();
+ m_backFaceStencilDescriptor = newStencilDescriptor();
+ m_vertexDescriptor = newVertexDescriptor();
m_textureDescriptor = newTextureDescriptor();
m_samplerDescriptor = newSamplerDescriptor();
@@ -399,7 +404,7 @@ namespace bgfx { namespace mtl
| BGFX_CAPS_TEXTURE_3D
| BGFX_CAPS_INSTANCING
| BGFX_CAPS_VERTEX_ATTRIB_HALF
-// | BGFX_CAPS_FRAGMENT_DEPTH //TODO: is this supported?
+// | BGFX_CAPS_FRAGMENT_DEPTH
| BGFX_CAPS_BLEND_INDEPENDENT
| BGFX_CAPS_COMPUTE
| BGFX_CAPS_INDEX32
@@ -407,10 +412,7 @@ namespace bgfx { namespace mtl
);
g_caps.maxTextureSize = 2048; //ASK: real caps width/height: 4096, but max depth(3D) size is only: 2048
- //TODO: OSX
-#if BX_PLATFORM_IOS
- g_caps.maxFBAttachments = uint8_t(bx::uint32_min(m_device.supportsFeatureSet(MTLFeatureSet_iOS_GPUFamily2_v1) ? 8 :4, BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS));
-#endif // BX_PLATFORM_*
+ g_caps.maxFBAttachments = 4; // uint8_t(bx::uint32_min(m_device.supportsFeatureSet(MTLFeatureSet_iOS_GPUFamily2_v1) ? 8 : 4, BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS));
//todo: vendor id, device id, gpu enum
//todo: texture format caps
@@ -488,7 +490,6 @@ namespace bgfx { namespace mtl
return BGFX_RENDERER_METAL_NAME;
}
-
void createIndexBuffer(IndexBufferHandle _handle, Memory* _mem, uint16_t _flags) BX_OVERRIDE
{
m_indexBuffers[_handle.idx].create(_mem->size, _mem->data, _flags);
@@ -672,8 +673,11 @@ namespace bgfx { namespace mtl
void saveScreenShot(const char* _filePath) BX_OVERRIDE
{
- if ( NULL == m_drawable || NULL == m_drawable.texture)
+ if (NULL == m_drawable
+ || NULL == m_drawable.texture)
+ {
return;
+ }
//TODO: we should wait for completion of pending commandBuffers
//TODO: implement this with saveScreenshotBegin/End
@@ -684,7 +688,7 @@ namespace bgfx { namespace mtl
uint32_t length = width*height*4;
uint8_t* data = (uint8_t*)BX_ALLOC(g_allocator, length);
- MTLRegion region = { 0, 0, 0, width, height, 1};
+ MTLRegion region = { { 0, 0, 0 }, { width, height, 1 } };
backBuffer.getBytes(data, 4*width, 0, region, 0, 0);
@@ -761,14 +765,14 @@ namespace bgfx { namespace mtl
uint32_t vertexUniformBufferSize = program.m_vshConstantBufferSize;
uint32_t fragmentUniformBufferSize = program.m_fshConstantBufferSize;
- if ( vertexUniformBufferSize )
+ if (vertexUniformBufferSize )
{
m_uniformBufferVertexOffset = BX_ALIGN_MASK(m_uniformBufferVertexOffset, program.m_vshConstantBufferAlignmentMask);
rce.setVertexBuffer(m_uniformBuffer, m_uniformBufferVertexOffset, 0);
}
m_uniformBufferFragmentOffset = m_uniformBufferVertexOffset + vertexUniformBufferSize;
- if ( fragmentUniformBufferSize )
+ if (fragmentUniformBufferSize )
{
m_uniformBufferFragmentOffset = BX_ALIGN_MASK(m_uniformBufferFragmentOffset, program.m_fshConstantBufferAlignmentMask);
rce.setFragmentBuffer(m_uniformBuffer, m_uniformBufferFragmentOffset, 0);
@@ -801,8 +805,11 @@ namespace bgfx { namespace mtl
void flip(HMD& /*_hmd*/) BX_OVERRIDE
{
- if ( m_drawable == nil || m_commandBuffer == nil) //there was no draw call, cannot flip
+ if (NULL == m_drawable
+ || NULL == m_commandBuffer)
+ {
return;
+ }
// Present and commit the command buffer
m_commandBuffer.presentDrawable(m_drawable);
@@ -835,62 +842,59 @@ namespace bgfx { namespace mtl
void updateResolution(const Resolution& _resolution)
{
- if (!!(_resolution.m_flags & BGFX_RESET_MAXANISOTROPY) )
- {
- m_maxAnisotropy = 16;
- }
- else
- {
- m_maxAnisotropy = 1;
- }
+ m_maxAnisotropy = !!(_resolution.m_flags & BGFX_RESET_MAXANISOTROPY)
+ ? 16
+ : 1
+ ;
//TODO: _resolution has wrong dimensions, using m_drawable.texture size now
-
- if ( NULL == m_drawable.texture )
+ if (NULL == m_drawable.texture)
+ {
return;
+ }
- uint32_t width = (uint32_t)m_drawable.texture.width;
+ uint32_t width = (uint32_t)m_drawable.texture.width;
uint32_t height = (uint32_t)m_drawable.texture.height;
//TODO: there should be a way to specify if backbuffer needs stencil/depth.
//TODO: support msaa
- if ( NULL == m_backBufferDepth || width!=m_backBufferDepth.width() || height!=m_backBufferDepth.height())
+ if (NULL == m_backBufferDepth
+ || width != m_backBufferDepth.width()
+ || height != m_backBufferDepth.height() )
{
m_textureDescriptor.textureType = MTLTextureType2D;
-#if BX_PLATFORM_IOS
- m_textureDescriptor.pixelFormat = MTLPixelFormatDepth32Float;
-#else
m_textureDescriptor.pixelFormat = MTLPixelFormatDepth32Float_Stencil8;
-#endif // BX_PLATFORM_*
- m_textureDescriptor.width = width;
+ m_textureDescriptor.width = width;
m_textureDescriptor.height = height;
- m_textureDescriptor.depth = 1;
+ m_textureDescriptor.depth = 1;
m_textureDescriptor.mipmapLevelCount = 1;
m_textureDescriptor.sampleCount = 1;
m_textureDescriptor.arrayLength = 1;
- //m_textureDescriptor.resourceOptions = 0;
+ m_textureDescriptor.resourceOptions = MTLResourceStorageModePrivate;
+ m_textureDescriptor.cpuCacheMode = MTLCPUCacheModeDefaultCache;
+ m_textureDescriptor.storageMode = MTLStorageModePrivate;
+ m_textureDescriptor.usage = MTLTextureUsageRenderTarget;
- if ( NULL != m_backBufferDepth )
+ if (NULL != m_backBufferDepth)
{
release(m_backBufferDepth);
}
m_backBufferDepth = m_device.newTextureWithDescriptor(m_textureDescriptor);
-#if BX_PLATFORM_IOS
+#if 0
m_textureDescriptor.pixelFormat = MTLPixelFormatStencil8;
- m_textureDescriptor.width = width;
- m_textureDescriptor.height = height;
- if ( NULL != m_backBufferStencil )
+ if (NULL != m_backBufferStencil)
{
release(m_backBufferStencil);
}
+
m_backBufferStencil = m_device.newTextureWithDescriptor(m_textureDescriptor);
#else
m_backBufferStencil = m_backBufferDepth;
-#endif // BX_PLATFORM_*
+#endif // 0
bx::HashMurmur2A murmur;
murmur.begin();
@@ -932,13 +936,13 @@ namespace bgfx { namespace mtl
setShaderUniform(_flags, _loc, _val, _numRegs);
}
- void commit(ConstantBuffer& _constantBuffer)
+ void commit(UniformBuffer& _uniformBuffer)
{
- _constantBuffer.reset();
+ _uniformBuffer.reset();
for (;;)
{
- uint32_t opcode = _constantBuffer.read();
+ uint32_t opcode = _uniformBuffer.read();
if (UniformType::End == opcode)
{
@@ -949,17 +953,17 @@ namespace bgfx { namespace mtl
uint16_t loc;
uint16_t num;
uint16_t copy;
- ConstantBuffer::decodeOpcode(opcode, type, loc, num, copy);
+ UniformBuffer::decodeOpcode(opcode, type, loc, num, copy);
const char* data;
if (copy)
{
- data = _constantBuffer.read(g_uniformTypeSize[type]*num);
+ data = _uniformBuffer.read(g_uniformTypeSize[type]*num);
}
else
{
UniformHandle handle;
- memcpy(&handle, _constantBuffer.read(sizeof(UniformHandle) ), sizeof(UniformHandle) );
+ memcpy(&handle, _uniformBuffer.read(sizeof(UniformHandle) ), sizeof(UniformHandle) );
data = (const char*)m_uniforms[handle.idx];
}
@@ -1005,7 +1009,7 @@ namespace bgfx { namespace mtl
break;
default:
- BX_TRACE("%4d: INVALID 0x%08x, t %d, l %d, n %d, c %d", _constantBuffer.getPos(), opcode, type, loc, num, copy);
+ BX_TRACE("%4d: INVALID 0x%08x, t %d, l %d, n %d, c %d", _uniformBuffer.getPos(), opcode, type, loc, num, copy);
break;
}
@@ -1074,25 +1078,25 @@ namespace bgfx { namespace mtl
uint32_t frontAndBack = bstencil != BGFX_STENCIL_NONE && bstencil != fstencil;
bstencil = frontAndBack ? bstencil : fstencil;
- if ( 0 != _stencil)
+ if (0 != _stencil)
{
StencilDescriptor frontFaceDesc = m_frontFaceStencilDescriptor;
StencilDescriptor backfaceDesc = m_backFaceStencilDescriptor;
- uint32_t readMask = (fstencil&BGFX_STENCIL_FUNC_RMASK_MASK)>>BGFX_STENCIL_FUNC_RMASK_SHIFT;
+ uint32_t readMask = (fstencil&BGFX_STENCIL_FUNC_RMASK_MASK)>>BGFX_STENCIL_FUNC_RMASK_SHIFT;
uint32_t writeMask = 0xff;
- frontFaceDesc.stencilFailureOperation = s_stencilOp[(fstencil&BGFX_STENCIL_OP_FAIL_S_MASK)>>BGFX_STENCIL_OP_FAIL_S_SHIFT];
- frontFaceDesc.depthFailureOperation = s_stencilOp[(fstencil&BGFX_STENCIL_OP_FAIL_Z_MASK)>>BGFX_STENCIL_OP_FAIL_Z_SHIFT];
+ frontFaceDesc.stencilFailureOperation = s_stencilOp[(fstencil&BGFX_STENCIL_OP_FAIL_S_MASK)>>BGFX_STENCIL_OP_FAIL_S_SHIFT];
+ frontFaceDesc.depthFailureOperation = s_stencilOp[(fstencil&BGFX_STENCIL_OP_FAIL_Z_MASK)>>BGFX_STENCIL_OP_FAIL_Z_SHIFT];
frontFaceDesc.depthStencilPassOperation = s_stencilOp[(fstencil&BGFX_STENCIL_OP_PASS_Z_MASK)>>BGFX_STENCIL_OP_PASS_Z_SHIFT];
- frontFaceDesc.stencilCompareFunction = s_cmpFunc[(fstencil&BGFX_STENCIL_TEST_MASK)>>BGFX_STENCIL_TEST_SHIFT];
+ frontFaceDesc.stencilCompareFunction = s_cmpFunc[(fstencil&BGFX_STENCIL_TEST_MASK)>>BGFX_STENCIL_TEST_SHIFT];
frontFaceDesc.readMask = readMask;
frontFaceDesc.writeMask = writeMask;
- backfaceDesc.stencilFailureOperation = s_stencilOp[(bstencil&BGFX_STENCIL_OP_FAIL_S_MASK)>>BGFX_STENCIL_OP_FAIL_S_SHIFT];
- backfaceDesc.depthFailureOperation = s_stencilOp[(bstencil&BGFX_STENCIL_OP_FAIL_Z_MASK)>>BGFX_STENCIL_OP_FAIL_Z_SHIFT];
+ backfaceDesc.stencilFailureOperation = s_stencilOp[(bstencil&BGFX_STENCIL_OP_FAIL_S_MASK)>>BGFX_STENCIL_OP_FAIL_S_SHIFT];
+ backfaceDesc.depthFailureOperation = s_stencilOp[(bstencil&BGFX_STENCIL_OP_FAIL_Z_MASK)>>BGFX_STENCIL_OP_FAIL_Z_SHIFT];
backfaceDesc.depthStencilPassOperation = s_stencilOp[(bstencil&BGFX_STENCIL_OP_PASS_Z_MASK)>>BGFX_STENCIL_OP_PASS_Z_SHIFT];
- backfaceDesc.stencilCompareFunction = s_cmpFunc[(bstencil&BGFX_STENCIL_TEST_MASK)>>BGFX_STENCIL_TEST_SHIFT];
+ backfaceDesc.stencilCompareFunction = s_cmpFunc[(bstencil&BGFX_STENCIL_TEST_MASK)>>BGFX_STENCIL_TEST_SHIFT];
backfaceDesc.readMask = readMask;
backfaceDesc.writeMask = writeMask;
@@ -1101,7 +1105,7 @@ namespace bgfx { namespace mtl
}
else
{
- desc.backFaceStencil = NULL;
+ desc.backFaceStencil = NULL;
desc.frontFaceStencil = NULL;
}
@@ -1132,8 +1136,8 @@ namespace bgfx { namespace mtl
m_samplerDescriptor.normalizedCoordinates = TRUE;
m_samplerDescriptor.maxAnisotropy = m_maxAnisotropy;
- //TODO: I haven't found how to specify this. Comparison function can be specified in shader.
- // On OSX this can be specified. There is no support for this on iOS right now.
+ //TODO: I haven't found how to specify this. Comparison function can be specified in shader.
+ // On OSX this can be specified. There is no support for this on iOS right now.
//const uint32_t cmpFunc = (_flags&BGFX_TEXTURE_COMPARE_MASK)>>BGFX_TEXTURE_COMPARE_SHIFT;
//const uint8_t filter = 0 == cmpFunc ? 0 : D3D11_COMPARISON_FILTERING_BIT;
//m_samplerDescriptor.comparisonFunc = 0 == cmpFunc ? D3D11_COMPARISON_NEVER : s_cmpFunc[cmpFunc];
@@ -1155,8 +1159,6 @@ namespace bgfx { namespace mtl
return m_backBufferDepth.height();
}
-
-
Device m_device;
CommandQueue m_commandQueue;
CAMetalLayer* m_metalLayer;
@@ -1334,11 +1336,11 @@ namespace bgfx { namespace mtl
memset(m_attributes, 0xff, sizeof(m_attributes) );
uint32_t used = 0;
uint32_t instUsed = 0;
- if ( NULL != _vsh->m_function.m_obj )
+ if (NULL != _vsh->m_function.m_obj )
{
for (MTLVertexAttribute* attrib in _vsh->m_function.m_obj.vertexAttributes)
{
- if ( attrib.active )
+ if (attrib.active )
{
const char* name = utf8String(attrib.name);
uint32_t loc = (uint32_t)attrib.attributeIndex;
@@ -1366,7 +1368,7 @@ namespace bgfx { namespace mtl
}
}
m_used[used] = Attrib::Count;
- m_instanceData[instUsed] = 0xffff;
+ m_instanceData[instUsed] = UINT16_MAX;
}
void ProgramMtl::destroy()
@@ -1376,13 +1378,13 @@ namespace bgfx { namespace mtl
if (NULL != m_vshConstantBuffer)
{
- ConstantBuffer::destroy(m_vshConstantBuffer);
+ UniformBuffer::destroy(m_vshConstantBuffer);
m_vshConstantBuffer = NULL;
}
if (NULL != m_fshConstantBuffer)
{
- ConstantBuffer::destroy(m_fshConstantBuffer);
+ UniformBuffer::destroy(m_fshConstantBuffer);
m_fshConstantBuffer = NULL;
}
@@ -1432,7 +1434,9 @@ namespace bgfx { namespace mtl
murmur.add(_state);
murmur.add(independentBlendEnable ? _rgba : 0);
if (!isValid(_fbHandle) )
+ {
murmur.add(s_renderMtl->m_backBufferPixelFormatHash);
+ }
else
{
FrameBufferMtl& frameBuffer = s_renderMtl->m_frameBuffers[_fbHandle.idx];
@@ -1443,17 +1447,17 @@ namespace bgfx { namespace mtl
uint32_t hash = murmur.end();
RenderPipelineState rps = m_renderPipelineStateCache.find(hash);
- if ( NULL == rps )
+ if (NULL == rps)
{
- RenderPipelineDescriptor& pipelineDesc = s_renderMtl->m_renderPipelineDescriptor;
- reset(pipelineDesc);
+ RenderPipelineDescriptor& pd = s_renderMtl->m_renderPipelineDescriptor;
+ reset(pd);
uint32_t frameBufferAttachment = 1;
if (!isValid(_fbHandle) )
{
- pipelineDesc.colorAttachments[0].pixelFormat = s_renderMtl->m_drawable.texture.pixelFormat;
- pipelineDesc.depthAttachmentPixelFormat = s_renderMtl->m_backBufferDepth.m_obj.pixelFormat;
- pipelineDesc.stencilAttachmentPixelFormat = s_renderMtl->m_backBufferStencil.m_obj.pixelFormat;
+ pd.colorAttachments[0].pixelFormat = s_renderMtl->m_drawable.texture.pixelFormat;
+ pd.depthAttachmentPixelFormat = s_renderMtl->m_backBufferDepth.m_obj.pixelFormat;
+ pd.stencilAttachmentPixelFormat = s_renderMtl->m_backBufferStencil.m_obj.pixelFormat;
}
else
{
@@ -1463,15 +1467,17 @@ namespace bgfx { namespace mtl
for (uint32_t ii = 0; ii < frameBuffer.m_num; ++ii)
{
const TextureMtl& texture = s_renderMtl->m_textures[frameBuffer.m_colorHandle[ii].idx];
- pipelineDesc.colorAttachments[ii].pixelFormat = texture.m_ptr.m_obj.pixelFormat;
+ pd.colorAttachments[ii].pixelFormat = texture.m_ptr.m_obj.pixelFormat;
}
if (isValid(frameBuffer.m_depthHandle))
{
const TextureMtl& texture = s_renderMtl->m_textures[frameBuffer.m_depthHandle.idx];
- pipelineDesc.depthAttachmentPixelFormat = texture.m_ptr.m_obj.pixelFormat;
- if ( NULL != texture.m_ptrStencil)
- pipelineDesc.stencilAttachmentPixelFormat = texture.m_ptrStencil.m_obj.pixelFormat;
+ pd.depthAttachmentPixelFormat = texture.m_ptr.m_obj.pixelFormat;
+ if (NULL != texture.m_ptrStencil)
+ {
+ pd.stencilAttachmentPixelFormat = MTLPixelFormatInvalid; //texture.m_ptrStencil.m_obj.pixelFormat;
+ }
//todo: stencil attachment should be the same as depth for packed depth/stencil
}
}
@@ -1493,17 +1499,17 @@ namespace bgfx { namespace mtl
for (uint32_t ii = 0; ii < (independentBlendEnable ? 1 : frameBufferAttachment); ++ii)
{
- RenderPipelineColorAttachmentDescriptor drt = pipelineDesc.colorAttachments[ii];
+ RenderPipelineColorAttachmentDescriptor drt = pd.colorAttachments[ii];
drt.blendingEnabled = !!(BGFX_STATE_BLEND_MASK & _state);
- drt.sourceRGBBlendFactor = s_blendFactor[srcRGB][0];
- drt.destinationRGBBlendFactor = s_blendFactor[dstRGB][0];
- drt.rgbBlendOperation = s_blendEquation[equRGB];
+ drt.sourceRGBBlendFactor = s_blendFactor[srcRGB][0];
+ drt.destinationRGBBlendFactor = s_blendFactor[dstRGB][0];
+ drt.rgbBlendOperation = s_blendEquation[equRGB];
- drt.sourceAlphaBlendFactor = s_blendFactor[srcA][1];
+ drt.sourceAlphaBlendFactor = s_blendFactor[srcA][1];
drt.destinationAlphaBlendFactor = s_blendFactor[dstA][1];
- drt.alphaBlendOperation = s_blendEquation[equA];
+ drt.alphaBlendOperation = s_blendEquation[equA];
drt.writeMask = writeMask;
}
@@ -1512,28 +1518,28 @@ namespace bgfx { namespace mtl
{
for (uint32_t ii = 1, rgba = _rgba; ii < frameBufferAttachment; ++ii, rgba >>= 11)
{
- RenderPipelineColorAttachmentDescriptor drt = pipelineDesc.colorAttachments[ii];
+ RenderPipelineColorAttachmentDescriptor drt = pd.colorAttachments[ii];
drt.blendingEnabled = 0 != (rgba&0x7ff);
- const uint32_t src = (rgba )&0xf;
- const uint32_t dst = (rgba>>4)&0xf;
+ const uint32_t src = (rgba )&0xf;
+ const uint32_t dst = (rgba>>4)&0xf;
const uint32_t equationIndex = (rgba>>8)&0x7;
- drt.sourceRGBBlendFactor = s_blendFactor[src][0];
- drt.destinationRGBBlendFactor = s_blendFactor[dst][0];
- drt.rgbBlendOperation = s_blendEquation[equationIndex];
+ drt.sourceRGBBlendFactor = s_blendFactor[src][0];
+ drt.destinationRGBBlendFactor = s_blendFactor[dst][0];
+ drt.rgbBlendOperation = s_blendEquation[equationIndex];
- drt.sourceAlphaBlendFactor = s_blendFactor[src][1];
+ drt.sourceAlphaBlendFactor = s_blendFactor[src][1];
drt.destinationAlphaBlendFactor = s_blendFactor[dst][1];
- drt.alphaBlendOperation = s_blendEquation[equationIndex];
+ drt.alphaBlendOperation = s_blendEquation[equationIndex];
drt.writeMask = writeMask;
}
}
- pipelineDesc.vertexFunction = m_vsh->m_function;
- pipelineDesc.fragmentFunction = m_fsh->m_function;
+ pd.vertexFunction = m_vsh->m_function;
+ pd.fragmentFunction = m_fsh->m_function;
if (isValid(_declHandle))
{
@@ -1551,9 +1557,9 @@ namespace bgfx { namespace mtl
bool normalized;
bool asInt;
vertexDecl.decode(attr, num, type, normalized, asInt);
- BX_CHECK(num<=4, "num must be <=4");
+ BX_CHECK(num <= 4, "num must be <=4");
- if (0xff != vertexDecl.m_attributes[attr])
+ if (UINT16_MAX != vertexDecl.m_attributes[attr])
{
vertexDesc.attributes[loc].format = s_attribType[type][num-1][normalized?1:0];
vertexDesc.attributes[loc].bufferIndex = 1;
@@ -1576,7 +1582,7 @@ namespace bgfx { namespace mtl
if (_numInstanceData > 0)
{
- for (uint32_t ii = 0; 0xffff != m_instanceData[ii]; ++ii)
+ for (uint32_t ii = 0; UINT16_MAX != m_instanceData[ii]; ++ii)
{
uint32_t loc = m_instanceData[ii];
vertexDesc.attributes[loc].format = MTLVertexFormatFloat4;
@@ -1589,39 +1595,40 @@ namespace bgfx { namespace mtl
vertexDesc.layouts[2].stepRate = 1;
}
- pipelineDesc.vertexDescriptor = vertexDesc;
+ pd.vertexDescriptor = vertexDesc;
}
if (m_processedUniforms)
{
- rps = s_renderMtl->m_device.newRenderPipelineStateWithDescriptor(pipelineDesc);
+ rps = s_renderMtl->m_device.newRenderPipelineStateWithDescriptor(pd);
}
else
{
m_numPredefined = 0;
RenderPipelineReflection reflection = NULL;
- rps = s_renderMtl->m_device.newRenderPipelineStateWithDescriptor(pipelineDesc, MTLPipelineOptionBufferTypeInfo, &reflection);
+ rps = s_renderMtl->m_device.newRenderPipelineStateWithDescriptor(pd, MTLPipelineOptionBufferTypeInfo, &reflection);
- if ( NULL != reflection )
+ if (NULL != reflection)
{
- for( int type =0; type<2; ++type)
+ for (uint32_t shaderType = 0; shaderType < 2; ++shaderType)
{
- ConstantBuffer*& constantBuffer = (type==0?m_vshConstantBuffer : m_fshConstantBuffer);
- uint8_t fragmentBit = (1 == type ? BGFX_UNIFORM_FRAGMENTBIT : 0);
+ UniformBuffer*& constantBuffer = (shaderType == 0 ? m_vshConstantBuffer : m_fshConstantBuffer);
+ uint8_t fragmentBit = (1 == shaderType ? BGFX_UNIFORM_FRAGMENTBIT : 0);
- for( MTLArgument* arg in (type==0?reflection.vertexArguments:reflection.fragmentArguments))
+ for (MTLArgument* arg in (shaderType == 0 ? reflection.vertexArguments : reflection.fragmentArguments))
{
BX_TRACE("arg: %s type:%d", utf8String(arg.name), arg.type);
if (arg.active)
{
- if (arg.type == MTLArgumentTypeBuffer && !strcmp(utf8String(arg.name),SHADER_UNIFORM_NAME) )
+ if (arg.type == MTLArgumentTypeBuffer
+ && 0 == strcmp(utf8String(arg.name), SHADER_UNIFORM_NAME) )
{
BX_CHECK( arg.index == 0, "Uniform buffer must be in the buffer slot 0.");
BX_CHECK( MTLDataTypeStruct == arg.bufferDataType, "%s's type must be a struct",SHADER_UNIFORM_NAME );
- if ( MTLDataTypeStruct == arg.bufferDataType )
+ if (MTLDataTypeStruct == arg.bufferDataType)
{
- if ( type == 0)
+ if (shaderType == 0)
{
m_vshConstantBufferSize = (uint32_t)arg.bufferDataSize;
m_vshConstantBufferAlignmentMask = (uint32_t)arg.bufferAlignment - 1;
@@ -1632,7 +1639,7 @@ namespace bgfx { namespace mtl
m_fshConstantBufferAlignmentMask = (uint32_t)arg.bufferAlignment - 1;
}
- for( MTLStructMember* uniform in arg.bufferStructType.members )
+ for (MTLStructMember* uniform in arg.bufferStructType.members )
{
const char* name = utf8String(uniform.name);
BX_TRACE("uniform: %s type:%d", name, uniform.dataType);
@@ -1640,7 +1647,7 @@ namespace bgfx { namespace mtl
MTLDataType dataType = uniform.dataType;
uint32_t num = 1;
- if (dataType==MTLDataTypeArray)
+ if (dataType == MTLDataTypeArray)
{
dataType = uniform.arrayType.elementType;
num = (uint32_t)uniform.arrayType.arrayLength;
@@ -1676,7 +1683,7 @@ namespace bgfx { namespace mtl
{
if (NULL == constantBuffer)
{
- constantBuffer = ConstantBuffer::create(1024);
+ constantBuffer = UniformBuffer::create(1024);
}
UniformType::Enum type = convertMtlType(dataType);
@@ -1687,21 +1694,27 @@ namespace bgfx { namespace mtl
}
}
- } else if (arg.type == MTLArgumentTypeTexture)
+ }
+ else if (arg.type == MTLArgumentTypeTexture)
{
const char* name = utf8String(arg.name);
BX_TRACE("texture: %s index:%d", name, arg.index);
- } else if (arg.type == MTLArgumentTypeSampler)
+ }
+ else if (arg.type == MTLArgumentTypeSampler)
{
const char* name = utf8String(arg.name);
BX_TRACE("sampler: %s index:%d", name, arg.index);
}
}
}
+
if (NULL != constantBuffer)
+ {
constantBuffer->finish();
+ }
}
}
+
m_processedUniforms = true;
}
@@ -1713,15 +1726,23 @@ namespace bgfx { namespace mtl
void BufferMtl::create(uint32_t _size, void* _data, uint16_t _flags, uint16_t _stride, bool _vertex)
{
+ BX_UNUSED(_flags, _stride, _vertex);
+
m_size = _size;
- if ( NULL == _data )
+ if (NULL == _data)
+ {
m_buffer = s_renderMtl->m_device.newBufferWithLength(_size, 0);
+ }
else
+ {
m_buffer = s_renderMtl->m_device.newBufferWithBytes(_data, _size, 0);
+ }
}
void BufferMtl::update(uint32_t _offset, uint32_t _size, void* _data, bool _discard)
{
+ BX_UNUSED(_discard);
+
memcpy( (uint8_t*)m_buffer.contents() + _offset, _data, _size);
}
@@ -1797,9 +1818,9 @@ namespace bgfx { namespace mtl
const bool bufferOnly = 0 != (_flags&BGFX_TEXTURE_RT_BUFFER_ONLY);
const bool computeWrite = 0 != (_flags&BGFX_TEXTURE_COMPUTE_WRITE);
- const bool renderTarget = 0 != (_flags&BGFX_TEXTURE_RT_MASK);
+// const bool renderTarget = 0 != (_flags&BGFX_TEXTURE_RT_MASK);
const bool srgb = 0 != (_flags&BGFX_TEXTURE_SRGB) || imageContainer.m_srgb;
- const uint32_t msaaQuality = bx::uint32_satsub( (_flags&BGFX_TEXTURE_RT_MSAA_MASK)>>BGFX_TEXTURE_RT_MSAA_SHIFT, 1);
+// const uint32_t msaaQuality = bx::uint32_satsub( (_flags&BGFX_TEXTURE_RT_MSAA_MASK)>>BGFX_TEXTURE_RT_MSAA_SHIFT, 1);
// const DXGI_SAMPLE_DESC& msaa = s_msaa[msaaQuality];
MTLPixelFormat format = MTLPixelFormatInvalid;
@@ -1816,16 +1837,21 @@ namespace bgfx { namespace mtl
}
desc.pixelFormat = format;
- desc.width = textureWidth;
+ desc.width = textureWidth;
desc.height = textureHeight;
- desc.depth = bx::uint32_max(1,imageContainer.m_depth);
+ desc.depth = bx::uint32_max(1,imageContainer.m_depth);
desc.mipmapLevelCount = imageContainer.m_numMips;
- desc.sampleCount = 1; //TODO: set samplecount - If textureType is not MTLTextureType2DMultisample, the value must be 1.
+ desc.sampleCount = 1; //TODO: set samplecount - If textureType is not MTLTextureType2DMultisample, the value must be 1.
+ desc.resourceOptions = MTLResourceStorageModePrivate;
+ desc.cpuCacheMode = MTLCPUCacheModeDefaultCache;
+ desc.storageMode = bufferOnly ? 1 /*MTLStorageModeManaged*/ : 2 /*MTLStorageModePrivate*/;
+ desc.usage = MTLTextureUsageShaderRead;
//TODO: set resource flags depending on usage(renderTarget/computeWrite/etc) on iOS9/OSX
m_ptr = s_renderMtl->m_device.newTextureWithDescriptor(desc);
- if ( m_requestedFormat == TextureFormat::D24S8 && desc.pixelFormat == MTLPixelFormatDepth32Float )
+ if (m_requestedFormat == TextureFormat::D24S8
+ && desc.pixelFormat == MTLPixelFormatDepth32Float)
{
desc.pixelFormat = MTLPixelFormatStencil8;
m_ptrStencil = s_renderMtl->m_device.newTextureWithDescriptor(desc);
@@ -1866,14 +1892,15 @@ namespace bgfx { namespace mtl
data = temp;
}
- MTLRegion region = { 0, 0, 0, width, height, depth};
+ MTLRegion region = { { 0, 0, 0 }, { width, height, depth } };
uint32_t bytesPerRow;
uint32_t bytesPerImage;
- if ( compressed && !convert)
+ if (compressed && !convert)
{
- if ( format >= MTLPixelFormatPVRTC_RGB_2BPP && format <= MTLPixelFormatPVRTC_RGBA_4BPP_sRGB)
+ if (format >= 160 /*MTLPixelFormatPVRTC_RGB_2BPP*/
+ && format <= 167 /*MTLPixelFormatPVRTC_RGBA_4BPP_sRGB*/)
{
bytesPerRow = 0;
bytesPerImage = 0;
@@ -1912,7 +1939,7 @@ namespace bgfx { namespace mtl
void TextureMtl::update(uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem)
{
- MTLRegion region = { _rect.m_x, _rect.m_y, _z, _rect.m_width, _rect.m_height, _depth};
+ MTLRegion region = { { _rect.m_x, _rect.m_y, _z }, { _rect.m_width, _rect.m_height, _depth } };
const uint32_t bpp = getBitsPerPixel(TextureFormat::Enum(m_textureFormat) );
const uint32_t rectpitch = _rect.m_width*bpp/8;
@@ -1988,6 +2015,8 @@ namespace bgfx { namespace mtl
void FrameBufferMtl::create(uint16_t _denseIdx, void* _nwh, uint32_t _width, uint32_t _height, TextureFormat::Enum _depthFormat)
{
+ BX_UNUSED(_denseIdx, _nwh, _width, _height, _depthFormat);
+
BX_WARN(false, "FrameBufferMtl::create not yet implemented");
}
@@ -2010,6 +2039,8 @@ namespace bgfx { namespace mtl
void RendererContextMtl::submit(Frame* _render, ClearQuad& _clearQuad, TextVideoMemBlitter& _textVideoMemBlitter) BX_OVERRIDE
{
+ BX_UNUSED(_clearQuad);
+
m_commandBuffer = m_commandQueue.commandBuffer();
retain(m_commandBuffer); // keep alive to be useable at 'flip'
@@ -2018,7 +2049,7 @@ namespace bgfx { namespace mtl
//TODO: acquire CAMetalDrawable just before we really need it. When we are using an encoder with target metalLayer's texture
m_drawable = m_metalLayer.nextDrawable;
- retain(m_drawable); // keep alive to be useable at 'flip'
+// retain(m_drawable); // keep alive to be useable at 'flip'
m_uniformBufferVertexOffset = 0;
m_uniformBufferFragmentOffset = 0;
@@ -2180,8 +2211,8 @@ namespace bgfx { namespace mtl
{
if (BGFX_CLEAR_COLOR_USE_PALETTE & clr.m_flags)
{
- uint8_t index = (uint8_t)bx::uint32_min(BGFX_CONFIG_MAX_CLEAR_COLOR_PALETTE-1, clr.m_index[0]);
- const float* rgba = _render->m_clearColor[index];
+ uint8_t index = (uint8_t)bx::uint32_min(BGFX_CONFIG_MAX_COLOR_PALETTE-1, clr.m_index[0]);
+ const float* rgba = _render->m_colorPalette[index];
const float rr = rgba[0];
const float gg = rgba[1];
const float bb = rgba[2];
@@ -2204,7 +2235,7 @@ namespace bgfx { namespace mtl
//TODO: optimize store actions use discard flag
RenderPassDepthAttachmentDescriptor depthAttachment = renderPassDescriptor.depthAttachment;
- if ( NULL != depthAttachment.texture)
+ if (NULL != depthAttachment.texture)
{
depthAttachment.clearDepth = clr.m_depth;
depthAttachment.loadAction = (BGFX_CLEAR_DEPTH & clr.m_flags) ? MTLLoadActionClear : MTLLoadActionLoad;
@@ -2212,14 +2243,14 @@ namespace bgfx { namespace mtl
}
RenderPassStencilAttachmentDescriptor stencilAttachment = renderPassDescriptor.stencilAttachment;
- if ( NULL != stencilAttachment.texture )
+ if (NULL != stencilAttachment.texture)
{
stencilAttachment.clearStencil = clr.m_stencil;
- stencilAttachment.loadAction = (BGFX_CLEAR_STENCIL & clr.m_flags) ? MTLLoadActionClear : MTLLoadActionLoad;
- stencilAttachment.storeAction = MTLStoreActionStore;
+ stencilAttachment.loadAction = (BGFX_CLEAR_STENCIL & clr.m_flags) ? MTLLoadActionClear : MTLLoadActionLoad;
+ stencilAttachment.storeAction = MTLStoreActionStore;
}
- if ( 0 != m_renderCommandEncoder)
+ if (0 != m_renderCommandEncoder)
{
m_renderCommandEncoder.endEncoding();
}
@@ -2236,7 +2267,7 @@ namespace bgfx { namespace mtl
if (BX_ENABLED(BGFX_CONFIG_DEBUG_MTL) )
{
- if ( item != 1) //ASK: better check ? I don't get the whole restart thing
+ if (item != 1) //ASK: better check ? I don't get the whole restart thing
rce.popDebugGroup();
rce.pushDebugGroup(s_viewName[view]);
@@ -2253,7 +2284,7 @@ namespace bgfx { namespace mtl
if (BGFX_CLEAR_NONE != (clr.m_flags & BGFX_CLEAR_MASK) && !fullscreenRect)
{ //TODO: fallback to clear with quad
- //clearQuad(_clearQuad, viewState.m_rect, clr, _render->m_clearColor);
+ //clearQuad(_clearQuad, viewState.m_rect, clr, _render->m_colorPalette);
}
}
@@ -2338,13 +2369,13 @@ namespace bgfx { namespace mtl
rce.setScissorRect(rc);
}
- if ( (BGFX_STATE_DEPTH_WRITE|BGFX_STATE_DEPTH_TEST_MASK) & changedFlags
+ if ((BGFX_STATE_DEPTH_WRITE|BGFX_STATE_DEPTH_TEST_MASK) & changedFlags
|| 0 != changedStencil)
{
setDepthStencilState(newFlags,newStencil);
}
- if ( (0
+ if ((0
| BGFX_STATE_CULL_MASK
| BGFX_STATE_ALPHA_REF_MASK
| BGFX_STATE_PT_MASK
@@ -2372,7 +2403,7 @@ namespace bgfx { namespace mtl
}
}
- if ( (blendFactor != draw.m_rgba) && !(newFlags & BGFX_STATE_BLEND_INDEPENDENT) )
+ if ((blendFactor != draw.m_rgba) && !(newFlags & BGFX_STATE_BLEND_INDEPENDENT) )
{
const uint32_t rgba = draw.m_rgba;
float rr = ( (rgba>>24) )/255.0f;
@@ -2386,7 +2417,7 @@ namespace bgfx { namespace mtl
bool programChanged = false;
bool constantsChanged = draw.m_constBegin < draw.m_constEnd;
- rendererUpdateUniforms(this, _render->m_constantBuffer, draw.m_constBegin, draw.m_constEnd);
+ rendererUpdateUniforms(this, _render->m_uniformBuffer, draw.m_constBegin, draw.m_constEnd);
if (key.m_program != programIdx ||
(BGFX_STATE_BLEND_MASK|BGFX_STATE_BLEND_EQUATION_MASK|BGFX_STATE_ALPHA_WRITE|BGFX_STATE_RGB_WRITE|BGFX_STATE_BLEND_INDEPENDENT|BGFX_STATE_MSAA) & changedFlags ||
@@ -2415,7 +2446,7 @@ namespace bgfx { namespace mtl
decl.idx = !isValid(vb.m_decl) ? draw.m_vertexDecl.idx : vb.m_decl.idx;
RenderPipelineState pipelineState = program.getRenderPipelineState(newFlags, draw.m_rgba, fbh, decl, draw.m_instanceDataStride/16);
- if ( NULL == pipelineState )
+ if (NULL == pipelineState )
{ //call with invalid program
currentProgram = NULL;
programIdx = invalidHandle;
@@ -2436,14 +2467,14 @@ namespace bgfx { namespace mtl
uint32_t vertexUniformBufferSize = program.m_vshConstantBufferSize;
uint32_t fragmentUniformBufferSize = program.m_fshConstantBufferSize;
- if ( vertexUniformBufferSize )
+ if (vertexUniformBufferSize )
{
m_uniformBufferVertexOffset = BX_ALIGN_MASK(m_uniformBufferVertexOffset, program.m_vshConstantBufferAlignmentMask);
rce.setVertexBuffer(m_uniformBuffer, m_uniformBufferVertexOffset, 0);
}
m_uniformBufferFragmentOffset = m_uniformBufferVertexOffset + vertexUniformBufferSize;
- if ( fragmentUniformBufferSize )
+ if (fragmentUniformBufferSize )
{
m_uniformBufferFragmentOffset = BX_ALIGN_MASK(m_uniformBufferFragmentOffset, program.m_fshConstantBufferAlignmentMask);
rce.setFragmentBuffer(m_uniformBuffer, m_uniformBufferFragmentOffset, 0);
@@ -2453,13 +2484,13 @@ namespace bgfx { namespace mtl
if (constantsChanged)
{
- ConstantBuffer* vcb = program.m_vshConstantBuffer;
+ UniformBuffer* vcb = program.m_vshConstantBuffer;
if (NULL != vcb)
{
commit(*vcb);
}
- ConstantBuffer* fcb = program.m_fshConstantBuffer;
+ UniformBuffer* fcb = program.m_fshConstantBuffer;
if (NULL != fcb)
{
commit(*fcb);
@@ -2613,8 +2644,10 @@ namespace bgfx { namespace mtl
if (BX_ENABLED(BGFX_CONFIG_DEBUG_MTL) )
{
- if ( 0 < _render->m_num)
+ if (0 < _render->m_num)
+ {
rce.popDebugGroup();
+ }
}
//TODO: debug stats
@@ -2636,7 +2669,7 @@ namespace bgfx { namespace mtl
static uint32_t maxGpuLatency = 0;
static double maxGpuElapsed = 0.0f;
- double elapsedGpuMs = 0.0;
+// double elapsedGpuMs = 0.0;
//TODO: gputimer
/* m_gpuTimer.end();
@@ -2709,9 +2742,10 @@ namespace bgfx { namespace mtl
);
}
- tvm.printf(10, pos++, 0x8e, " Indices: %7d", statsNumIndices);
- tvm.printf(10, pos++, 0x8e, " DVB size: %7d", _render->m_vboffset);
- tvm.printf(10, pos++, 0x8e, " DIB size: %7d", _render->m_iboffset);
+ tvm.printf(10, pos++, 0x8e, " Indices: %7d ", statsNumIndices);
+ tvm.printf(10, pos++, 0x8e, " Uniform size: %7d, Max: %7d ", _render->m_uniformEnd, _render->m_uniformMax);
+ tvm.printf(10, pos++, 0x8e, " DVB size: %7d ", _render->m_vboffset);
+ tvm.printf(10, pos++, 0x8e, " DIB size: %7d ", _render->m_iboffset);
double captureMs = double(captureElapsed)*toMs;
tvm.printf(10, pos++, 0x8e, " Capture: %3.4f [ms]", captureMs);
diff --git a/3rdparty/bgfx/src/shader_dxbc.cpp b/3rdparty/bgfx/src/shader_dxbc.cpp
index 5d8d960980e..34e50c14424 100644
--- a/3rdparty/bgfx/src/shader_dxbc.cpp
+++ b/3rdparty/bgfx/src/shader_dxbc.cpp
@@ -490,7 +490,7 @@ namespace bgfx
};
BX_STATIC_ASSERT(BX_COUNTOF(s_dxbcSrvType) == DxbcResourceDim::Count);
- static const char* s_dxbcInterpolationName[] =
+ const char* s_dxbcInterpolationName[] =
{
"",
"constant",
diff --git a/3rdparty/bgfx/src/vertexdecl.h b/3rdparty/bgfx/src/vertexdecl.h
index 6ba12417bfa..46025527594 100644
--- a/3rdparty/bgfx/src/vertexdecl.h
+++ b/3rdparty/bgfx/src/vertexdecl.h
@@ -6,7 +6,7 @@
#ifndef BGFX_VERTEXDECL_H_HEADER_GUARD
#define BGFX_VERTEXDECL_H_HEADER_GUARD
-#include <bgfx.h>
+#include <bgfx/bgfx.h>
#include <bx/readerwriter.h>
namespace bgfx
diff --git a/3rdparty/bgfx/tools/geometryc/geometryc.cpp b/3rdparty/bgfx/tools/geometryc/geometryc.cpp
index d55d4a2e096..0314455b413 100644
--- a/3rdparty/bgfx/tools/geometryc/geometryc.cpp
+++ b/3rdparty/bgfx/tools/geometryc/geometryc.cpp
@@ -10,7 +10,7 @@
#include <stdlib.h>
#include <string.h>
-#include <bgfx.h>
+#include <bgfx/bgfx.h>
#include "../../src/vertexdecl.h"
#include <tinystl/allocator.h>
@@ -514,7 +514,7 @@ int main(int _argc, const char* _argv[])
index.m_normal = -1;
index.m_vertexIndex = -1;
- char* vertex = argv[edge+1];
+ char* vertex = argv[edge+1];
char* texcoord = strchr(vertex, '/');
if (NULL != texcoord)
{
@@ -942,14 +942,14 @@ int main(int _argc, const char* _argv[])
}
}
- if (0 < numVertices)
+ prim.m_numVertices = numVertices - prim.m_startVertex;
+ if (0 < prim.m_numVertices)
{
- prim.m_numVertices = numVertices - prim.m_startVertex;
prim.m_numIndices = numIndices - prim.m_startIndex;
prim.m_name = groupIt->m_name;
primitives.push_back(prim);
prim.m_startVertex = numVertices;
- prim.m_startIndex = numIndices;
+ prim.m_startIndex = numIndices;
}
BX_TRACE("%3d: s %5d, n %5d, %s\n"