mirror of
https://github.com/FyroxEngine/Fyrox.git
synced 2026-10-12 02:02:20 +00:00
font rendering
This commit is contained in:
Generated
+242
-215
@@ -6,10 +6,13 @@
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="1932b2c4-d6ff-413c-9558-19959667326b" name="Default Changelist" comment="scene graph">
|
||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/math/mod.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/math/mod.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/math/triangulator.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/math/triangulator.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/engine/mod.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/engine/mod.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/game/mod.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/game/mod.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/main.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/main.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/math/vec2.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/math/vec2.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/renderer/renderer.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/renderer/renderer.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/resource/fbx/mod.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/resource/fbx/mod.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/resource/ttf.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/resource/ttf.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/utils/pool.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/utils/pool.rs" afterDir="false" />
|
||||
</list>
|
||||
<ignored path="$PROJECT_DIR$/target/" />
|
||||
<ignored path="$PROJECT_DIR$/out/" />
|
||||
@@ -22,91 +25,91 @@
|
||||
<component name="FileEditorManager">
|
||||
<leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/src/resource/texture.rs">
|
||||
<entry file="file://$PROJECT_DIR$/src/resource/ttf.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="306">
|
||||
<caret line="18" column="59" selection-start-line="18" selection-start-column="59" selection-end-line="18" selection-end-column="59" />
|
||||
<state relative-caret-position="497">
|
||||
<caret line="951" column="11" selection-start-line="951" selection-start-column="11" selection-end-line="951" selection-end-column="11" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/src/resource/fbx/mod.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="883">
|
||||
<caret line="1228" column="39" selection-start-line="1228" selection-start-column="39" selection-end-line="1228" selection-end-column="39" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/src/gui/mod.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="830">
|
||||
<caret line="148" column="63" selection-start-line="148" selection-start-column="63" selection-end-line="148" selection-end-column="63" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/src/gui/draw.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="850">
|
||||
<caret line="335" column="67" selection-start-line="335" selection-start-column="67" selection-end-line="335" selection-end-column="67" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/src/renderer/gl.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="752">
|
||||
<caret line="1033" column="54" selection-start-line="1033" selection-start-column="54" selection-end-line="1033" selection-end-column="54" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/src/renderer/renderer.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="694">
|
||||
<caret line="403" column="31" selection-start-line="403" selection-start-column="31" selection-end-line="403" selection-end-column="31" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/src/renderer/surface.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="5817">
|
||||
<caret line="367" column="5" selection-start-line="367" selection-start-column="5" selection-end-line="367" selection-end-column="5" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/src/engine/mod.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="1969">
|
||||
<caret line="284" column="62" selection-start-line="284" selection-start-column="62" selection-end-line="284" selection-end-column="62" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/src/main.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="357">
|
||||
<caret line="21" column="8" selection-start-line="21" selection-start-column="8" selection-end-line="21" selection-end-column="8" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="true">
|
||||
<entry file="file://$PROJECT_DIR$/src/resource/ttf.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="539">
|
||||
<caret line="133" column="31" lean-forward="true" selection-start-line="133" selection-start-column="31" selection-end-line="133" selection-end-column="31" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/src/game/mod.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="68">
|
||||
<caret line="4" column="4" selection-start-line="4" selection-start-column="4" selection-end-line="4" selection-end-column="4" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/src/utils/pool.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="-935">
|
||||
<caret line="45" column="34" lean-forward="true" selection-start-line="45" selection-start-column="34" selection-end-line="45" selection-end-column="34" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/src/math/mod.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="221">
|
||||
<caret line="13" column="51" selection-start-line="13" selection-start-column="51" selection-end-line="13" selection-end-column="51" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/image-0.21.0/src/png.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="581">
|
||||
<caret line="106" selection-start-line="106" selection-end-line="106" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$USER_HOME$/.rustup/toolchains/stable-x86_64-pc-windows-gnu/lib/rustlib/src/rust/src/libstd/path.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="335">
|
||||
<caret line="2207" column="11" selection-start-line="2207" selection-start-column="11" selection-end-line="2207" selection-end-column="11" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/image-0.21.0/src/dynimage.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="327">
|
||||
<caret line="763" column="7" selection-start-line="763" selection-start-column="7" selection-end-line="763" selection-end-column="7" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/image-0.21.0/src/ico/encoder.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="335">
|
||||
<caret line="28" column="11" selection-start-line="28" selection-start-column="11" selection-end-line="28" selection-end-column="11" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/image-0.21.0/src/color.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="153">
|
||||
<caret line="9" column="9" selection-start-line="9" selection-start-column="9" selection-end-line="9" selection-end-column="9" />
|
||||
<state relative-caret-position="446">
|
||||
<caret line="59" column="101" selection-start-line="59" selection-start-column="101" selection-end-line="59" selection-end-column="101" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
@@ -144,8 +147,14 @@
|
||||
<find>ttf_glyph-></find>
|
||||
<find>bitmap-></find>
|
||||
<find>node-></find>
|
||||
<find>-></find>
|
||||
<find>glyph.bitmap_height</find>
|
||||
<find>size->y</find>
|
||||
<find>f;</find>
|
||||
<find>-></find>
|
||||
<find>cmd -></find>
|
||||
<find>r -></find>
|
||||
<find>gui_render_buffers</find>
|
||||
<find>check_gl_error</find>
|
||||
</findStrings>
|
||||
<replaceStrings>
|
||||
<replace>b.</replace>
|
||||
@@ -153,8 +162,12 @@
|
||||
<replace>RcPool</replace>
|
||||
<replace>RcPoolRecord</replace>
|
||||
<replace>glyph.</replace>
|
||||
<replace>self.</replace>
|
||||
<replace>rect->h</replace>
|
||||
<replace>;</replace>
|
||||
<replace>.</replace>
|
||||
<replace>cmd.</replace>
|
||||
<replace>self.</replace>
|
||||
<replace>ui_render_buffers</replace>
|
||||
</replaceStrings>
|
||||
</component>
|
||||
<component name="Git.Settings">
|
||||
@@ -172,7 +185,6 @@
|
||||
<option value="$PROJECT_DIR$/src/renderer/mod.rs" />
|
||||
<option value="$PROJECT_DIR$/src/resource/texture.rs" />
|
||||
<option value="$PROJECT_DIR$/src/utils/persistent_pool.rs" />
|
||||
<option value="$PROJECT_DIR$/src/math/vec2.rs" />
|
||||
<option value="$PROJECT_DIR$/src/math/vec4.rs" />
|
||||
<option value="$PROJECT_DIR$/src/scene/animation.rs" />
|
||||
<option value="$PROJECT_DIR$/src/utils/serialization.rs" />
|
||||
@@ -184,23 +196,26 @@
|
||||
<option value="$PROJECT_DIR$/src/math/quat.rs" />
|
||||
<option value="$PROJECT_DIR$/src/physics/mod.rs" />
|
||||
<option value="$PROJECT_DIR$/src/resource/model.rs" />
|
||||
<option value="$PROJECT_DIR$/src/engine/mod.rs" />
|
||||
<option value="$PROJECT_DIR$/src/renderer/surface.rs" />
|
||||
<option value="$PROJECT_DIR$/src/utils/rcpool.rs" />
|
||||
<option value="$PROJECT_DIR$/src/game/level.rs" />
|
||||
<option value="$PROJECT_DIR$/src/game/weapon.rs" />
|
||||
<option value="$PROJECT_DIR$/src/scene/node.rs" />
|
||||
<option value="$PROJECT_DIR$/src/scene/mod.rs" />
|
||||
<option value="$PROJECT_DIR$/src/renderer/renderer.rs" />
|
||||
<option value="$PROJECT_DIR$/src/game/player.rs" />
|
||||
<option value="$PROJECT_DIR$/src/main.rs" />
|
||||
<option value="$PROJECT_DIR$/src/resource/mod.rs" />
|
||||
<option value="$PROJECT_DIR$/src/game/mod.rs" />
|
||||
<option value="$PROJECT_DIR$/src/resource/fbx/mod.rs" />
|
||||
<option value="$PROJECT_DIR$/src/math/triangulator.rs" />
|
||||
<option value="$PROJECT_DIR$/src/math/mod.rs" />
|
||||
<option value="$PROJECT_DIR$/src/utils/pool.rs" />
|
||||
<option value="$PROJECT_DIR$/src/resource/mod.rs" />
|
||||
<option value="$PROJECT_DIR$/src/main.rs" />
|
||||
<option value="$PROJECT_DIR$/src/math/vec2.rs" />
|
||||
<option value="$PROJECT_DIR$/src/math/mod.rs" />
|
||||
<option value="$PROJECT_DIR$/src/resource/fbx/mod.rs" />
|
||||
<option value="$PROJECT_DIR$/src/gui/mod.rs" />
|
||||
<option value="$PROJECT_DIR$/src/engine/mod.rs" />
|
||||
<option value="$PROJECT_DIR$/src/resource/ttf.rs" />
|
||||
<option value="$PROJECT_DIR$/src/gui/draw.rs" />
|
||||
<option value="$PROJECT_DIR$/src/renderer/renderer.rs" />
|
||||
<option value="$PROJECT_DIR$/src/game/mod.rs" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
@@ -214,7 +229,7 @@
|
||||
</treeState>
|
||||
</component>
|
||||
<component name="ProjectFrameBounds">
|
||||
<option name="width" value="1515" />
|
||||
<option name="width" value="1280" />
|
||||
<option name="height" value="1400" />
|
||||
</component>
|
||||
<component name="ProjectView">
|
||||
@@ -222,7 +237,6 @@
|
||||
<foldersAlwaysOnTop value="true" />
|
||||
</navigator>
|
||||
<panes>
|
||||
<pane id="Scope" />
|
||||
<pane id="PackagesPane" />
|
||||
<pane id="ProjectPane">
|
||||
<subPane>
|
||||
@@ -248,6 +262,12 @@
|
||||
<item name="src" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="game" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
<path>
|
||||
<item name="rg3d" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="rg3d" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="src" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="gui" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
<path>
|
||||
<item name="rg3d" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="rg3d" type="462c0819:PsiDirectoryNode" />
|
||||
@@ -300,10 +320,11 @@
|
||||
<select />
|
||||
</subPane>
|
||||
</pane>
|
||||
<pane id="Scope" />
|
||||
</panes>
|
||||
</component>
|
||||
<component name="PropertiesComponent">
|
||||
<property name="com.android.tools.idea.instantapp.provision.ProvisionBeforeRunTaskProvider.myTimeStamp" value="1562500347805" />
|
||||
<property name="com.android.tools.idea.instantapp.provision.ProvisionBeforeRunTaskProvider.myTimeStamp" value="1562523886968" />
|
||||
<property name="last_opened_file_path" value="$PROJECT_DIR$/../Program Files/Git/bin/git.exe" />
|
||||
<property name="org.rust.cargo.project.model.PROJECT_DISCOVERY" value="true" />
|
||||
<property name="project.structure.last.edited" value="Project" />
|
||||
@@ -325,7 +346,7 @@
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="RunManager" selected="Cargo Command.Test">
|
||||
<component name="RunManager" selected="Cargo Command.Release">
|
||||
<configuration name="Debug" type="CargoCommandRunConfiguration" factoryName="Cargo Command" temporary="true">
|
||||
<option name="channel" value="DEFAULT" />
|
||||
<option name="command" value="run --package rg3d --bin rg3d" />
|
||||
@@ -427,10 +448,10 @@
|
||||
</todo-panel>
|
||||
</component>
|
||||
<component name="ToolWindowManager">
|
||||
<frame x="0" y="0" width="1515" height="1400" extended-state="0" />
|
||||
<frame x="0" y="0" width="1280" height="1400" extended-state="0" />
|
||||
<editor active="true" />
|
||||
<layout>
|
||||
<window_info content_ui="combo" id="Project" order="0" visible="true" weight="0.1766323" />
|
||||
<window_info content_ui="combo" id="Project" order="0" visible="true" weight="0.21393442" />
|
||||
<window_info id="Structure" order="1" side_tool="true" weight="0.25" />
|
||||
<window_info id="Image Layers" order="2" />
|
||||
<window_info id="Designer" order="3" />
|
||||
@@ -469,52 +490,9 @@
|
||||
<option name="FILTER_TARGETS" value="false" />
|
||||
</component>
|
||||
<component name="editorHistoryManager">
|
||||
<entry file="file://$USER_HOME$/.rustup/toolchains/stable-x86_64-pc-windows-gnu/lib/rustlib/src/rust/src/libcore/ops/arith.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="8755">
|
||||
<caret line="515" column="7" selection-start-line="515" selection-start-column="7" selection-end-line="515" selection-end-column="7" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$USER_HOME$/.rustup/toolchains/stable-x86_64-pc-windows-gnu/lib/rustlib/src/rust/src/libcore/time.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="-7939">
|
||||
<caret line="326" column="17" selection-start-line="326" selection-start-column="17" selection-end-line="326" selection-end-column="17" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/utils/serialization.rs" />
|
||||
<entry file="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.92/src/ser/mod.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="327">
|
||||
<caret line="1192" column="7" selection-start-line="1192" selection-start-column="7" selection-end-line="1192" selection-end-column="7" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$USER_HOME$/.rustup/toolchains/stable-x86_64-pc-windows-gnu/lib/rustlib/src/rust/src/libcore/default.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="335">
|
||||
<caret line="83" column="10" selection-start-line="83" selection-start-column="10" selection-end-line="83" selection-end-column="10" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/math/mat4.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="867">
|
||||
<caret line="225" selection-start-line="225" selection-end-line="225" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/test.json">
|
||||
<provider selected="true" editor-type-id="text-editor" />
|
||||
</entry>
|
||||
<entry file="file://$USER_HOME$/.rustup/toolchains/stable-x86_64-pc-windows-gnu/lib/rustlib/src/rust/src/liballoc/vec.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="30260">
|
||||
<caret line="1780" column="37" selection-start-line="1780" selection-start-column="37" selection-end-line="1780" selection-end-column="37" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$USER_HOME$/.rustup/toolchains/stable-x86_64-pc-windows-gnu/lib/rustlib/src/rust/src/libcore/slice/mod.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="54910">
|
||||
@@ -550,13 +528,6 @@
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/math/vec3.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="170">
|
||||
<caret line="10" selection-start-line="10" selection-end-line="18" selection-end-column="1" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/math/ray.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state>
|
||||
@@ -620,13 +591,6 @@
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/renderer/surface.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="6239">
|
||||
<caret line="367" column="5" selection-start-line="367" selection-start-column="5" selection-end-line="367" selection-end-column="5" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$USER_HOME$/.rustup/toolchains/stable-x86_64-pc-windows-gnu/lib/rustlib/src/rust/src/libcore/option.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="14416">
|
||||
@@ -634,20 +598,6 @@
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/engine/mod.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="327">
|
||||
<caret line="73" column="99" selection-start-line="73" selection-start-column="99" selection-end-line="73" selection-end-column="99" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/scene/node.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="310">
|
||||
<caret line="171" column="15" selection-start-line="171" selection-start-column="15" selection-end-line="171" selection-end-column="15" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/scene/mod.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="711">
|
||||
@@ -655,13 +605,6 @@
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/renderer/renderer.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="663">
|
||||
<caret line="355" column="45" selection-start-line="355" selection-start-column="45" selection-end-line="355" selection-end-column="45" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/game/weapon.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="391">
|
||||
@@ -669,13 +612,6 @@
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/main.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="442">
|
||||
<caret line="26" column="1" selection-start-line="26" selection-start-column="1" selection-end-line="26" selection-end-column="1" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/game/level.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="1632">
|
||||
@@ -683,13 +619,6 @@
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/resource/mod.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="51">
|
||||
<caret line="3" column="12" selection-start-line="3" selection-start-column="12" selection-end-line="3" selection-end-column="12" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/game/player.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="3366">
|
||||
@@ -697,13 +626,6 @@
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/winit-0.19.0/src/events.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="4301">
|
||||
<caret line="253" column="4" selection-start-line="253" selection-start-column="4" selection-end-line="253" selection-end-column="4" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$USER_HOME$/.rustup/toolchains/stable-x86_64-pc-windows-gnu/lib/rustlib/src/rust/src/libcore/cmp.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="335">
|
||||
@@ -711,13 +633,6 @@
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/resource/fbx/mod.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="668">
|
||||
<caret line="716" selection-start-line="716" selection-end-line="716" selection-end-column="48" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$USER_HOME$/.rustup/toolchains/stable-x86_64-pc-windows-gnu/lib/rustlib/src/rust/src/liballoc/slice.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="344">
|
||||
@@ -788,31 +703,143 @@
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/math/mod.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="221">
|
||||
<caret line="13" column="51" selection-start-line="13" selection-start-column="51" selection-end-line="13" selection-end-column="51" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/utils/pool.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="-935">
|
||||
<caret line="45" column="34" lean-forward="true" selection-start-line="45" selection-start-column="34" selection-end-line="45" selection-end-column="34" />
|
||||
<caret line="45" column="34" selection-start-line="45" selection-start-column="34" selection-end-line="45" selection-end-column="34" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/game/mod.rs">
|
||||
<entry file="file://$PROJECT_DIR$/src/resource/mod.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="68">
|
||||
<caret line="4" column="4" selection-start-line="4" selection-start-column="4" selection-end-line="4" selection-end-column="4" />
|
||||
<state relative-caret-position="204">
|
||||
<caret line="12" column="17" selection-start-line="12" selection-start-column="17" selection-end-line="12" selection-end-column="17" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/scene/node.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="255">
|
||||
<caret line="15" column="4" selection-start-line="15" selection-start-column="4" selection-end-line="15" selection-end-column="4" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$USER_HOME$/.rustup/toolchains/stable-x86_64-pc-windows-gnu/lib/rustlib/src/rust/src/liballoc/vec.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="12172">
|
||||
<caret line="716" column="11" selection-start-line="716" selection-start-column="11" selection-end-line="716" selection-end-column="11" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/math/mod.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="561">
|
||||
<caret line="33" column="5" selection-start-line="33" selection-start-column="5" selection-end-line="33" selection-end-column="5" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/math/vec2.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="238">
|
||||
<caret line="14" column="9" selection-start-line="14" selection-start-column="9" selection-end-line="14" selection-end-column="9" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/math/vec3.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="1768">
|
||||
<caret line="104" column="5" selection-start-line="92" selection-start-column="3" selection-end-line="104" selection-end-column="5" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/winit-0.19.0/src/events.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="4539">
|
||||
<caret line="267" column="9" selection-start-line="267" selection-start-column="9" selection-end-line="267" selection-end-column="9" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$USER_HOME$/.rustup/toolchains/stable-x86_64-pc-windows-gnu/lib/rustlib/src/rust/src/libcore/mem.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="414">
|
||||
<caret line="234" column="13" selection-start-line="234" selection-start-column="13" selection-end-line="234" selection-end-column="13" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/resource/fbx/mod.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="883">
|
||||
<caret line="1228" column="39" selection-start-line="1228" selection-start-column="39" selection-end-line="1228" selection-end-column="39" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$USER_HOME$/.rustup/toolchains/stable-x86_64-pc-windows-gnu/lib/rustlib/src/rust/src/libcore/intrinsics.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="839">
|
||||
<caret line="667" column="11" selection-start-line="667" selection-start-column="11" selection-end-line="667" selection-end-column="11" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/renderer/surface.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="5817">
|
||||
<caret line="367" column="5" selection-start-line="367" selection-start-column="5" selection-end-line="367" selection-end-column="5" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/gui/draw.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="850">
|
||||
<caret line="335" column="67" selection-start-line="335" selection-start-column="67" selection-end-line="335" selection-end-column="67" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/engine/mod.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="1969">
|
||||
<caret line="284" column="62" selection-start-line="284" selection-start-column="62" selection-end-line="284" selection-end-column="62" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/resource/ttf.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="539">
|
||||
<caret line="133" column="31" lean-forward="true" selection-start-line="133" selection-start-column="31" selection-end-line="133" selection-end-column="31" />
|
||||
<state relative-caret-position="497">
|
||||
<caret line="951" column="11" selection-start-line="951" selection-start-column="11" selection-end-line="951" selection-end-column="11" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/renderer/gl.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="752">
|
||||
<caret line="1033" column="54" selection-start-line="1033" selection-start-column="54" selection-end-line="1033" selection-end-column="54" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/renderer/renderer.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="694">
|
||||
<caret line="403" column="31" selection-start-line="403" selection-start-column="31" selection-end-line="403" selection-end-column="31" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/main.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="357">
|
||||
<caret line="21" column="8" selection-start-line="21" selection-start-column="8" selection-end-line="21" selection-end-column="8" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/gui/mod.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="830">
|
||||
<caret line="148" column="63" selection-start-line="148" selection-start-column="63" selection-end-line="148" selection-end-column="63" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/game/mod.rs">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="446">
|
||||
<caret line="59" column="101" selection-start-line="59" selection-start-column="101" selection-end-line="59" selection-end-column="101" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
|
||||
+33
-1
@@ -9,6 +9,8 @@ use crate::utils::rcpool::{RcPool, RcHandle};
|
||||
use std::collections::VecDeque;
|
||||
use crate::renderer::surface::SurfaceSharedData;
|
||||
use crate::resource::model::Model;
|
||||
use crate::resource::ttf::Font;
|
||||
use crate::gui::UserInterface;
|
||||
|
||||
pub struct ResourceManager {
|
||||
resources: RcPool<Resource>,
|
||||
@@ -202,16 +204,24 @@ pub struct Engine {
|
||||
state: State,
|
||||
events: VecDeque<glutin::Event>,
|
||||
running: bool,
|
||||
font_cache: Pool<Font>,
|
||||
default_font: Handle<Font>,
|
||||
user_interface: UserInterface,
|
||||
}
|
||||
|
||||
impl Engine {
|
||||
#[inline]
|
||||
pub fn new() -> Engine {
|
||||
let mut font_cache = Pool::new();
|
||||
Engine {
|
||||
state: State::new(),
|
||||
renderer: Renderer::new(),
|
||||
events: VecDeque::new(),
|
||||
running: true,
|
||||
default_font: font_cache.spawn(Font::load(
|
||||
Path::new("data/fonts/font.ttf"), 18.0, (0..255).collect()).unwrap()),
|
||||
font_cache,
|
||||
user_interface: UserInterface::new()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,9 +258,31 @@ impl Engine {
|
||||
});
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_font(&self, font_handle: &Handle<Font>) -> Option<&Font> {
|
||||
self.font_cache.borrow(font_handle)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_default_font(&self) -> &Font {
|
||||
self.font_cache.borrow(&self.default_font).unwrap()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_ui(&self) -> &UserInterface {
|
||||
&self.user_interface
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_ui_mut(&mut self) -> &mut UserInterface {
|
||||
&mut self.user_interface
|
||||
}
|
||||
|
||||
pub fn render(&mut self) {
|
||||
self.renderer.upload_font_cache(&mut self.font_cache);
|
||||
self.renderer.upload_resources(&mut self.state);
|
||||
self.renderer.render(&self.state);
|
||||
self.renderer.render(&self.state, &self.user_interface.get_drawing_context());
|
||||
self.user_interface.get_drawing_context_mut().clear();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
||||
+15
-3
@@ -3,12 +3,14 @@ pub mod player;
|
||||
pub mod weapon;
|
||||
|
||||
use std::fs::File;
|
||||
use std::path::{Path};
|
||||
use std::path::Path;
|
||||
|
||||
use crate::game::level::{Level};
|
||||
use crate::game::level::Level;
|
||||
|
||||
use crate::engine::Engine;
|
||||
use std::time::{Duration, Instant};
|
||||
use crate::math::vec2::Vec2;
|
||||
use crate::gui::draw::{Color, CommandKind, FormattedText};
|
||||
|
||||
pub struct Game {
|
||||
engine: Engine,
|
||||
@@ -17,7 +19,7 @@ pub struct Game {
|
||||
|
||||
pub struct GameTime {
|
||||
elapsed: f64,
|
||||
delta: f64
|
||||
delta: f64,
|
||||
}
|
||||
|
||||
fn duration_to_seconds_f64(duration: Duration) -> f64 {
|
||||
@@ -52,7 +54,17 @@ impl Game {
|
||||
let fixed_timestep = 1.0 / fixed_fps;
|
||||
let clock = Instant::now();
|
||||
let mut game_time = GameTime { elapsed: 0.0, delta: fixed_timestep };
|
||||
let mut test_text = FormattedText::new();
|
||||
while self.engine.is_running() {
|
||||
{
|
||||
test_text.set_text("The quick brown fox jumps over a lazy dog. 1234567890!@#$%^&*()_+",
|
||||
self.engine.get_default_font(),
|
||||
&Vec2::new(),
|
||||
Color::white());
|
||||
|
||||
let dc = self.engine.get_ui_mut().get_drawing_context_mut();
|
||||
dc.draw_text(&test_text);
|
||||
}
|
||||
let mut dt = duration_to_seconds_f64(clock.elapsed()) - game_time.elapsed;
|
||||
while dt >= fixed_timestep {
|
||||
dt -= fixed_timestep;
|
||||
|
||||
+338
@@ -0,0 +1,338 @@
|
||||
use crate::math::vec2::Vec2;
|
||||
use crate::math::Rect;
|
||||
use crate::gui::Thickness;
|
||||
use crate::resource::ttf::Font;
|
||||
use std::os::raw::c_void;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Color {
|
||||
pub r: u8,
|
||||
pub g: u8,
|
||||
pub b: u8,
|
||||
pub a: u8,
|
||||
}
|
||||
|
||||
impl Color {
|
||||
pub fn white() -> Color {
|
||||
Color { r: 255, g: 255, b: 255, a: 255 }
|
||||
}
|
||||
|
||||
pub fn black() -> Color {
|
||||
Color { r: 0, g: 0, b: 0, a: 255 }
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct Vertex {
|
||||
pos: Vec2,
|
||||
tex_coord: Vec2,
|
||||
color: Color,
|
||||
}
|
||||
|
||||
impl Vertex {
|
||||
fn new(pos: Vec2, tex_coord: Vec2, color: Color) -> Vertex {
|
||||
Vertex {
|
||||
pos,
|
||||
tex_coord,
|
||||
color,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum CommandKind {
|
||||
Geometry,
|
||||
Clip,
|
||||
}
|
||||
|
||||
pub struct Command {
|
||||
kind: CommandKind,
|
||||
texture: u32,
|
||||
index_offset: usize,
|
||||
triangle_count: usize,
|
||||
nesting: u8,
|
||||
}
|
||||
|
||||
impl Command {
|
||||
#[inline]
|
||||
pub fn get_kind(&self) -> &CommandKind {
|
||||
&self.kind
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_texture(&self) -> u32 {
|
||||
self.texture
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_index_offset(&self) -> usize {
|
||||
self.index_offset
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_triangle_count(&self) -> usize {
|
||||
self.triangle_count
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_nesting(&self) -> u8 {
|
||||
self.nesting
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DrawingContext {
|
||||
vertex_buffer: Vec<Vertex>,
|
||||
index_buffer: Vec<i32>,
|
||||
command_buffer: Vec<Command>,
|
||||
clip_cmd_stack: Vec<i32>,
|
||||
opacity_stack: Vec<f32>,
|
||||
triangles_to_commit: usize,
|
||||
current_nesting: u8,
|
||||
}
|
||||
|
||||
struct TextElement {
|
||||
bounds: Rect<f32>,
|
||||
tex_coords: [Vec2; 4],
|
||||
color: Color,
|
||||
}
|
||||
|
||||
pub struct FormattedText {
|
||||
texture: u32,
|
||||
elements: Vec<TextElement>
|
||||
}
|
||||
|
||||
impl FormattedText {
|
||||
pub fn new() -> FormattedText {
|
||||
FormattedText {
|
||||
texture: 0,
|
||||
elements: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_text(&mut self, text: &str, font: &Font, pos: &Vec2, color: Color) {
|
||||
self.elements.clear();
|
||||
self.texture = font.get_texture_id();
|
||||
let mut cursor = *pos;
|
||||
for code in text.chars() {
|
||||
match font.get_glyph(code) {
|
||||
Some(glyph) => {
|
||||
if glyph.has_outline() {
|
||||
let rect = Rect {
|
||||
x: cursor.x + glyph.get_bitmap_left(),
|
||||
y: cursor.y + font.get_ascender() - glyph.get_bitmap_top() - glyph.get_bitmap_height(),
|
||||
w: glyph.get_bitmap_width(),
|
||||
h: glyph.get_bitmap_height(),
|
||||
};
|
||||
self.elements.push(TextElement {
|
||||
bounds: rect,
|
||||
tex_coords: glyph.get_tex_coords().clone(),
|
||||
color
|
||||
});
|
||||
}
|
||||
cursor.x += glyph.get_advance();
|
||||
}
|
||||
None => {
|
||||
let rect = Rect {
|
||||
x: cursor.x,
|
||||
y: cursor.y + font.get_ascender(),
|
||||
w: font.get_height(),
|
||||
h: font.get_height(),
|
||||
};
|
||||
self.elements.push(TextElement {
|
||||
bounds: rect,
|
||||
tex_coords: [Vec2::new(); 4],
|
||||
color
|
||||
});
|
||||
cursor.x += rect.w;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_line_thickness_vector(a: &Vec2, b: &Vec2, thickness: f32) -> Vec2 {
|
||||
if let Some(dir) = (*b - *a).normalized() {
|
||||
dir.perpendicular().scale(thickness * 0.5)
|
||||
} else {
|
||||
Vec2::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl DrawingContext {
|
||||
pub fn new() -> DrawingContext {
|
||||
DrawingContext {
|
||||
vertex_buffer: Vec::new(),
|
||||
index_buffer: Vec::new(),
|
||||
command_buffer: Vec::new(),
|
||||
clip_cmd_stack: Vec::new(),
|
||||
opacity_stack: Vec::new(),
|
||||
triangles_to_commit: 0,
|
||||
current_nesting: 0,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn clear(&mut self) {
|
||||
self.vertex_buffer.clear();
|
||||
self.index_buffer.clear();
|
||||
self.command_buffer.clear();
|
||||
self.clip_cmd_stack.clear();
|
||||
self.opacity_stack.clear();
|
||||
self.triangles_to_commit = 0;
|
||||
self.current_nesting = 0;
|
||||
}
|
||||
|
||||
|
||||
#[inline]
|
||||
pub fn get_command_buffer(&self) -> &[Command] {
|
||||
self.command_buffer.as_slice()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_vertices(&self) -> &[Vertex] {
|
||||
self.vertex_buffer.as_slice()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_indices(&self) -> &[i32] {
|
||||
self.index_buffer.as_slice()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_vertices_ptr(&self) -> *const c_void {
|
||||
self.vertex_buffer.as_ptr() as *const c_void
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_indices_ptr(&self) -> *const c_void {
|
||||
self.index_buffer.as_ptr() as *const c_void
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_vertices_bytes(&self) -> isize {
|
||||
(self.vertex_buffer.len() * std::mem::size_of::<Vertex>()) as isize
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_vertex_size(&self) -> i32 {
|
||||
std::mem::size_of::<Vertex>() as i32
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_index_size(&self) -> i32 {
|
||||
std::mem::size_of::<i32>() as i32
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_indices_bytes(&self) -> isize {
|
||||
(self.index_buffer.len() * std::mem::size_of::<i32>()) as isize
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn push_vertex(&mut self, pos: Vec2, tex_coord: Vec2, color: Color) {
|
||||
self.vertex_buffer.push(Vertex::new(pos, tex_coord, color));
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn push_triangle(&mut self, a: i32, b: i32, c: i32) {
|
||||
self.index_buffer.push(a);
|
||||
self.index_buffer.push(b);
|
||||
self.index_buffer.push(c);
|
||||
self.triangles_to_commit += 1;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_index_origin(&self) -> i32 {
|
||||
if self.index_buffer.len() > 0 {
|
||||
self.index_buffer.last().unwrap() + 1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn push_line(&mut self, a: &Vec2, b: &Vec2, thickness: f32, color: Color) {
|
||||
let perp = get_line_thickness_vector(a, b, thickness);
|
||||
self.push_vertex(*a - perp, Vec2::make(0.0, 0.0), color);
|
||||
self.push_vertex(*b - perp, Vec2::make(1.0, 0.0), color);
|
||||
self.push_vertex(*a + perp, Vec2::make(1.0, 1.0), color);
|
||||
self.push_vertex(*b + perp, Vec2::make(0.0, 1.0), color);
|
||||
|
||||
let index = self.get_index_origin();
|
||||
self.push_triangle(index, index + 1, index + 2);
|
||||
self.push_triangle(index, index + 2, index + 3);
|
||||
}
|
||||
|
||||
pub fn push_rect(&mut self, rect: &Rect<f32>, thickness: f32, color: Color) {
|
||||
let offset = thickness * 0.5;
|
||||
|
||||
let left_top = Vec2::make(rect.x + offset, rect.y + thickness);
|
||||
let right_top = Vec2::make(rect.x + rect.w - offset, rect.y + thickness);
|
||||
let right_bottom = Vec2::make(rect.x + rect.w - offset, rect.y + rect.h - thickness);
|
||||
let left_bottom = Vec2::make(rect.x + offset, rect.y + rect.h - thickness);
|
||||
let left_top_off = Vec2::make(rect.x, rect.y + offset);
|
||||
let right_top_off = Vec2::make(rect.x + rect.w, rect.y + offset);
|
||||
let right_bottom_off = Vec2::make(rect.x + rect.w, rect.y + rect.h - offset);
|
||||
let left_bottom_off = Vec2::make(rect.x, rect.y + rect.h - offset);
|
||||
|
||||
// Horizontal lines
|
||||
self.push_line(&left_top_off, &right_top_off, thickness, color);
|
||||
self.push_line(&right_bottom_off, &left_bottom_off, thickness, color);
|
||||
|
||||
// Vertical lines
|
||||
self.push_line(&right_top, &right_bottom, thickness, color);
|
||||
self.push_line(&left_bottom, &left_top, thickness, color);
|
||||
}
|
||||
|
||||
pub fn push_rect_vary(&mut self, rect: &Rect<f32>, thickness: Thickness, color: Color) {
|
||||
let left_top = Vec2::make(rect.x + thickness.left * 0.5, rect.y + thickness.top);
|
||||
let right_top = Vec2::make(rect.x + rect.w - thickness.right * 0.5, rect.y + thickness.top);
|
||||
let right_bottom = Vec2::make(rect.x + rect.w - thickness.right * 0.5, rect.y + rect.h - thickness.bottom);
|
||||
let left_bottom = Vec2::make(rect.x + thickness.left * 0.5, rect.y + rect.h - thickness.bottom);
|
||||
let left_top_off = Vec2::make(rect.x, rect.y + thickness.top * 0.5);
|
||||
let right_top_off = Vec2::make(rect.x + rect.w, rect.y + thickness.top * 0.5);
|
||||
let right_bottom_off = Vec2::make(rect.x + rect.w, rect.y + rect.h - thickness.bottom * 0.5);
|
||||
let left_bottom_off = Vec2::make(rect.x, rect.y + rect.h - thickness.bottom * 0.5);
|
||||
|
||||
// Horizontal lines
|
||||
self.push_line(&left_top_off, &right_top_off, thickness.top, color);
|
||||
self.push_line(&right_bottom_off, &left_bottom_off, thickness.bottom, color);
|
||||
|
||||
// Vertical lines
|
||||
self.push_line(&right_top, &right_bottom, thickness.right, color);
|
||||
self.push_line(&left_bottom, &left_top, thickness.left, color);
|
||||
}
|
||||
|
||||
pub fn push_rect_filled(&mut self, rect: &Rect<f32>, tex_coords: Option<&[Vec2; 4]>, color: Color) {
|
||||
self.push_vertex(Vec2::make(rect.x, rect.y), tex_coords.map_or(Vec2::make(0.0, 0.0), |t| t[0]), color);
|
||||
self.push_vertex(Vec2::make(rect.x + rect.w, rect.y), tex_coords.map_or(Vec2::make(1.0, 0.0), |t| t[1]), color);
|
||||
self.push_vertex(Vec2::make(rect.x + rect.w, rect.y + rect.h), tex_coords.map_or(Vec2::make(1.0, 1.0), |t| t[2]), color);
|
||||
self.push_vertex(Vec2::make(rect.x, rect.y + rect.h), tex_coords.map_or(Vec2::make(0.0, 1.0), |t| t[3]), color);
|
||||
|
||||
let index = self.get_index_origin();
|
||||
self.push_triangle(index, index + 1, index + 2);
|
||||
self.push_triangle(index, index + 2, index + 3);
|
||||
}
|
||||
|
||||
pub fn commit(&mut self, kind: CommandKind, texture: u32) {
|
||||
if self.triangles_to_commit > 0 {
|
||||
self.command_buffer.push(Command {
|
||||
kind,
|
||||
texture,
|
||||
nesting: self.current_nesting,
|
||||
index_offset: if self.index_buffer.len() > 0 {
|
||||
self.index_buffer.len() - self.triangles_to_commit * 3
|
||||
} else {
|
||||
0
|
||||
},
|
||||
triangle_count: self.triangles_to_commit,
|
||||
});
|
||||
self.triangles_to_commit = 0;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_text(&mut self, formatted_text: &FormattedText) {
|
||||
for element in formatted_text.elements.iter() {
|
||||
self.push_rect_filled(&element.bounds, Some(&element.tex_coords), element.color);
|
||||
}
|
||||
self.commit(CommandKind::Geometry, formatted_text.texture);
|
||||
}
|
||||
}
|
||||
+152
@@ -0,0 +1,152 @@
|
||||
pub mod draw;
|
||||
|
||||
use crate::utils::pool::Pool;
|
||||
use crate::math::vec2::Vec2;
|
||||
use glutin::{VirtualKeyCode, MouseButton};
|
||||
use crate::gui::draw::{Color, DrawingContext};
|
||||
|
||||
pub struct UserInterface {
|
||||
nodes: Pool<UINode>,
|
||||
drawing_context: DrawingContext
|
||||
}
|
||||
|
||||
pub enum HorizontalAlignment {
|
||||
Stretch,
|
||||
Left,
|
||||
Center,
|
||||
Right,
|
||||
}
|
||||
|
||||
pub enum VerticalAlignment {
|
||||
Stretch,
|
||||
Top,
|
||||
Center,
|
||||
Bottom,
|
||||
}
|
||||
|
||||
pub struct Thickness {
|
||||
left: f32,
|
||||
top: f32,
|
||||
right: f32,
|
||||
bottom: f32,
|
||||
}
|
||||
|
||||
pub enum Visibility {
|
||||
Visible,
|
||||
Collapsed,
|
||||
Hidden,
|
||||
}
|
||||
|
||||
pub enum UINodeKind {
|
||||
Base,
|
||||
/// TODO
|
||||
Text,
|
||||
/// TODO
|
||||
Border,
|
||||
/// TODO
|
||||
Window,
|
||||
/// TODO
|
||||
Button,
|
||||
/// TODO
|
||||
ScrollBar,
|
||||
/// TODO
|
||||
ScrollViewer,
|
||||
/// TODO
|
||||
TextBox,
|
||||
/// TODO
|
||||
Image,
|
||||
/// TODO Automatically arranges children by rows and columns */
|
||||
Grid,
|
||||
/// TODO Allows user to directly set position and size of a node */
|
||||
Canvas,
|
||||
/// TODO Allows user to scroll content */
|
||||
ScrollContentPresenter,
|
||||
/// TODO
|
||||
SlideSelector,
|
||||
/// TODO
|
||||
CheckBox,
|
||||
}
|
||||
|
||||
pub struct UINode {
|
||||
/// Desired position relative to parent node
|
||||
desired_local_position: Vec2,
|
||||
/// Explicit width for node or automatic if NaN (means value is undefined). Default is NaN
|
||||
width: f32,
|
||||
/// Explicit height for node or automatic if NaN (means value is undefined). Default is NaN
|
||||
height: f32,
|
||||
/// Screen position of the node
|
||||
screen_position: Vec2,
|
||||
/// Desired size of the node after Measure pass.
|
||||
desired_size: Vec2,
|
||||
/// Actual node local position after Arrange pass.
|
||||
actual_local_position: Vec2,
|
||||
/// Actual size of the node after Arrange pass.
|
||||
actual_size: Vec2,
|
||||
/// Minimum width and height
|
||||
min_size: Vec2,
|
||||
/// Maximum width and height
|
||||
max_size: Vec2,
|
||||
/// Overlay color of the node
|
||||
color: Color,
|
||||
/// Index of row to which this node belongs
|
||||
row: usize,
|
||||
/// Index of column to which this node belongs
|
||||
column: usize,
|
||||
/// Vertical alignment
|
||||
vertical_alignment: VerticalAlignment,
|
||||
/// Horizontal alignment
|
||||
horizontal_alignment: HorizontalAlignment,
|
||||
/// Margin (four sides)
|
||||
margin: Thickness,
|
||||
/// Current visibility state
|
||||
visibility: Visibility,
|
||||
}
|
||||
|
||||
pub enum RoutedEventKind {
|
||||
MouseDown {
|
||||
pos: Vec2,
|
||||
button: MouseButton,
|
||||
},
|
||||
MouseMove {
|
||||
pos: Vec2
|
||||
},
|
||||
MouseUp {
|
||||
pos: Vec2,
|
||||
button: MouseButton
|
||||
},
|
||||
Text {
|
||||
symbol: char
|
||||
},
|
||||
KeyDown {
|
||||
code: VirtualKeyCode
|
||||
},
|
||||
KeyUp {
|
||||
code: VirtualKeyCode
|
||||
},
|
||||
MouseWheel {
|
||||
pos: Vec2,
|
||||
amount: u32
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RoutedEvent {
|
||||
kind: RoutedEventKind,
|
||||
handled: bool,
|
||||
}
|
||||
|
||||
impl UserInterface {
|
||||
pub fn new() -> UserInterface {
|
||||
UserInterface {
|
||||
nodes: Pool::new(),
|
||||
drawing_context: DrawingContext::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_drawing_context(&self) -> &DrawingContext {
|
||||
&self.drawing_context
|
||||
}
|
||||
|
||||
pub fn get_drawing_context_mut(&mut self) -> &mut DrawingContext {
|
||||
&mut self.drawing_context
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ mod engine;
|
||||
mod resource;
|
||||
mod physics;
|
||||
mod game;
|
||||
mod gui;
|
||||
|
||||
use crate::game::{Game};
|
||||
|
||||
|
||||
+31
-3
@@ -7,28 +7,56 @@ pub struct Vec2 {
|
||||
}
|
||||
|
||||
impl Vec2 {
|
||||
#[inline]
|
||||
pub fn new() -> Self {
|
||||
Vec2 {
|
||||
x: 0.0,
|
||||
y:0.0
|
||||
y: 0.0,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn make(x: f32, y: f32) -> Self {
|
||||
Vec2 { x, y }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn dot(&self, other: Self) -> f32 {
|
||||
self.x * other.x + self.y * other.y
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn len(&self) -> f32 {
|
||||
self.dot(*self).sqrt()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn angle(&self, other: Self) -> f32 {
|
||||
(self.dot(other) / (self.len() * other.len())).acos()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn perpendicular(&self) -> Vec2 {
|
||||
Vec2 { x: self.y, y: -self.x }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn scale(&self, scalar: f32) -> Vec2 {
|
||||
Vec2 { x: self.x * scalar, y: self.y * scalar }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn normalized(&self) -> Option<Vec2> {
|
||||
let len = self.len();
|
||||
if len >= std::f32::EPSILON {
|
||||
let inv_len = 1.0 / len;
|
||||
return Some(Vec2 {
|
||||
x: self.x * inv_len,
|
||||
y: self.y * inv_len,
|
||||
});
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Add<Self> for Vec2 {
|
||||
@@ -36,7 +64,7 @@ impl ops::Add<Self> for Vec2 {
|
||||
fn add(self, b: Self) -> Self {
|
||||
Self {
|
||||
x: self.x + b.x,
|
||||
y: self.y + b.y
|
||||
y: self.y + b.y,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -53,7 +81,7 @@ impl ops::Sub<Self> for Vec2 {
|
||||
fn sub(self, b: Self) -> Self {
|
||||
Self {
|
||||
x: self.x - b.x,
|
||||
y: self.y - b.y
|
||||
y: self.y - b.y,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+394
-115
@@ -10,6 +10,11 @@ use crate::engine::{ResourceManager, State};
|
||||
use crate::math::{vec3::*};
|
||||
use crate::resource::ResourceKind;
|
||||
use std::mem::size_of;
|
||||
use crate::resource::ttf::Font;
|
||||
use crate::gui::draw::{DrawingContext, CommandKind, Color};
|
||||
use crate::math::mat4::Mat4;
|
||||
use image::ColorType;
|
||||
use std::path::PathBuf;
|
||||
|
||||
// Welcome to the kingdom of Unsafe Code
|
||||
|
||||
@@ -96,10 +101,30 @@ impl Drop for GpuProgram {
|
||||
}
|
||||
}
|
||||
|
||||
struct UIShader {
|
||||
program: GpuProgram,
|
||||
wvp_matrix: GLint,
|
||||
diffuse_texture: GLint,
|
||||
}
|
||||
|
||||
struct FlatShader {
|
||||
program: GpuProgram,
|
||||
wvp_matrix: GLint,
|
||||
diffuse_texture: GLint,
|
||||
}
|
||||
|
||||
struct UIRenderBuffers {
|
||||
vbo: GLuint,
|
||||
vao: GLuint,
|
||||
ebo: GLuint,
|
||||
}
|
||||
|
||||
pub struct Renderer {
|
||||
pub(crate) events_loop: glutin::EventsLoop,
|
||||
pub(crate) context: glutin::WindowedContext,
|
||||
flat_shader: GpuProgram,
|
||||
flat_shader: FlatShader,
|
||||
ui_shader: UIShader,
|
||||
white_dummy: GLuint,
|
||||
|
||||
/// Separate lists of handles to nodes of specified kinds
|
||||
/// Used reduce tree traversal count, it will performed once.
|
||||
@@ -110,89 +135,197 @@ pub struct Renderer {
|
||||
|
||||
/// Scene graph traversal stack
|
||||
traversal_stack: Vec<Handle<Node>>,
|
||||
|
||||
ui_render_buffers: UIRenderBuffers,
|
||||
}
|
||||
|
||||
fn create_flat_shader() -> FlatShader {
|
||||
let fragment_source = CString::new(r#"
|
||||
#version 330 core
|
||||
|
||||
uniform sampler2D diffuseTexture;
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
in vec2 texCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
FragColor = texture(diffuseTexture, texCoord);
|
||||
}
|
||||
"#).unwrap();
|
||||
|
||||
let vertex_source = CString::new(r#"
|
||||
#version 330 core
|
||||
|
||||
layout(location = 0) in vec3 vertexPosition;
|
||||
layout(location = 1) in vec2 vertexTexCoord;
|
||||
|
||||
uniform mat4 worldViewProjection;
|
||||
|
||||
out vec2 texCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
texCoord = vertexTexCoord;
|
||||
gl_Position = worldViewProjection * vec4(vertexPosition, 1.0);
|
||||
}
|
||||
"#).unwrap();
|
||||
|
||||
let mut program = GpuProgram::from_source(&vertex_source, &fragment_source).unwrap();
|
||||
FlatShader {
|
||||
wvp_matrix: program.get_uniform_location("worldViewProjection"),
|
||||
diffuse_texture: program.get_uniform_location("diffuseTexture"),
|
||||
program,
|
||||
}
|
||||
}
|
||||
|
||||
fn create_ui_shader() -> UIShader {
|
||||
let fragment_source = CString::new(r#"
|
||||
#version 330 core
|
||||
|
||||
uniform sampler2D diffuseTexture;
|
||||
|
||||
out vec4 FragColor;
|
||||
in vec2 texCoord;
|
||||
in vec4 color;
|
||||
|
||||
void main()
|
||||
{
|
||||
FragColor = color;
|
||||
FragColor.a *= texture(diffuseTexture, texCoord).r;
|
||||
};"#).unwrap();
|
||||
|
||||
|
||||
let vertex_source = CString::new(r#"
|
||||
#version 330 core
|
||||
|
||||
layout(location = 0) in vec3 vertexPosition;
|
||||
layout(location = 1) in vec2 vertexTexCoord;
|
||||
layout(location = 2) in vec4 vertexColor;
|
||||
|
||||
uniform mat4 worldViewProjection;
|
||||
|
||||
out vec2 texCoord;
|
||||
out vec4 color;
|
||||
|
||||
void main()
|
||||
{
|
||||
texCoord = vertexTexCoord;
|
||||
color = vertexColor;
|
||||
gl_Position = worldViewProjection * vec4(vertexPosition, 1.0);
|
||||
};"#).unwrap();
|
||||
|
||||
let mut program = GpuProgram::from_source(&vertex_source, &fragment_source).unwrap();
|
||||
UIShader {
|
||||
wvp_matrix: program.get_uniform_location("worldViewProjection"),
|
||||
diffuse_texture: program.get_uniform_location("diffuseTexture"),
|
||||
program,
|
||||
}
|
||||
}
|
||||
|
||||
fn create_ui_render_buffers() -> UIRenderBuffers {
|
||||
unsafe {
|
||||
let mut ui_render_buffers = UIRenderBuffers {
|
||||
vbo: 0,
|
||||
ebo: 0,
|
||||
vao: 0,
|
||||
};
|
||||
|
||||
gl::GenVertexArrays(1, &mut ui_render_buffers.vao);
|
||||
gl::GenBuffers(1, &mut ui_render_buffers.vbo);
|
||||
gl::GenBuffers(1, &mut ui_render_buffers.ebo);
|
||||
|
||||
ui_render_buffers
|
||||
}
|
||||
}
|
||||
|
||||
fn create_white_dummy() -> GLuint {
|
||||
unsafe {
|
||||
let mut texture: GLuint = 0;
|
||||
let white_pixel: [Color; 1] = [Color { r: 255, g: 255, b: 255, a: 255 }; 1];
|
||||
gl::GenTextures(1, &mut texture);
|
||||
|
||||
gl::BindTexture(gl::TEXTURE_2D, texture);
|
||||
gl::TexImage2D(
|
||||
gl::TEXTURE_2D,
|
||||
0,
|
||||
gl::RGBA as i32,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
gl::RGBA,
|
||||
gl::UNSIGNED_BYTE,
|
||||
white_pixel.as_ptr() as *const c_void,
|
||||
);
|
||||
gl::TexParameteri(
|
||||
gl::TEXTURE_2D,
|
||||
gl::TEXTURE_MAG_FILTER,
|
||||
gl::LINEAR as i32,
|
||||
);
|
||||
gl::TexParameteri(
|
||||
gl::TEXTURE_2D,
|
||||
gl::TEXTURE_MIN_FILTER,
|
||||
gl::LINEAR as i32,
|
||||
);
|
||||
gl::BindTexture(gl::TEXTURE_2D, 0);
|
||||
|
||||
texture
|
||||
}
|
||||
}
|
||||
|
||||
impl Renderer {
|
||||
pub fn new() -> Self {
|
||||
let events_loop = glutin::EventsLoop::new();
|
||||
|
||||
let primary_monitor = events_loop.get_primary_monitor();
|
||||
let mut monitor_dimensions = primary_monitor.get_dimensions();
|
||||
monitor_dimensions.height = monitor_dimensions.height * 0.5;
|
||||
monitor_dimensions.width = monitor_dimensions.width * 0.5;
|
||||
let window_size = monitor_dimensions.to_logical(primary_monitor.get_hidpi_factor());
|
||||
|
||||
let window_builder = glutin::WindowBuilder::new()
|
||||
.with_title("RG3D")
|
||||
.with_dimensions(window_size)
|
||||
.with_resizable(false);
|
||||
|
||||
let context = glutin::ContextBuilder::new()
|
||||
.with_vsync(true)
|
||||
.build_windowed(window_builder, &events_loop)
|
||||
.unwrap();
|
||||
|
||||
unsafe {
|
||||
let events_loop = glutin::EventsLoop::new();
|
||||
|
||||
let primary_monitor = events_loop.get_primary_monitor();
|
||||
let mut monitor_dimensions = primary_monitor.get_dimensions();
|
||||
monitor_dimensions.height = monitor_dimensions.height * 0.5;
|
||||
monitor_dimensions.width = monitor_dimensions.width * 0.5;
|
||||
let window_size = monitor_dimensions.to_logical(primary_monitor.get_hidpi_factor());
|
||||
|
||||
let window_builder = glutin::WindowBuilder::new()
|
||||
.with_title("RG3D")
|
||||
.with_dimensions(window_size)
|
||||
.with_resizable(false);
|
||||
|
||||
let context = glutin::ContextBuilder::new()
|
||||
.with_vsync(true)
|
||||
.build_windowed(window_builder, &events_loop)
|
||||
.unwrap();
|
||||
|
||||
context.make_current().unwrap();
|
||||
}
|
||||
gl::load_with(|symbol| context.get_proc_address(symbol) as *const _);
|
||||
|
||||
gl::load_with(|symbol| context.get_proc_address(symbol) as *const _);
|
||||
|
||||
unsafe {
|
||||
gl::Enable(gl::DEPTH_TEST);
|
||||
}
|
||||
|
||||
println!("creating shaders...");
|
||||
|
||||
let fragment_source = CString::new(r#"
|
||||
#version 330 core
|
||||
uniform sampler2D diffuseTexture;
|
||||
out vec4 FragColor;
|
||||
in vec2 texCoord;
|
||||
void main()
|
||||
{
|
||||
FragColor = texture(diffuseTexture, texCoord);
|
||||
}"#
|
||||
).unwrap();
|
||||
|
||||
let vertex_source = CString::new(r#"
|
||||
#version 330 core
|
||||
|
||||
layout(location = 0) in vec3 vertexPosition;
|
||||
layout(location = 1) in vec2 vertexTexCoord;
|
||||
|
||||
uniform mat4 worldViewProjection;
|
||||
|
||||
out vec2 texCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
texCoord = vertexTexCoord;
|
||||
gl_Position = worldViewProjection * vec4(vertexPosition, 1.0);
|
||||
}"#
|
||||
).unwrap();
|
||||
|
||||
Self {
|
||||
context,
|
||||
events_loop,
|
||||
flat_shader: GpuProgram::from_source(&vertex_source, &fragment_source).unwrap(),
|
||||
traversal_stack: Vec::new(),
|
||||
cameras: Vec::new(),
|
||||
lights: Vec::new(),
|
||||
meshes: Vec::new(),
|
||||
Self {
|
||||
context,
|
||||
events_loop,
|
||||
flat_shader: create_flat_shader(),
|
||||
ui_shader: create_ui_shader(),
|
||||
traversal_stack: Vec::new(),
|
||||
cameras: Vec::new(),
|
||||
lights: Vec::new(),
|
||||
meshes: Vec::new(),
|
||||
white_dummy: create_white_dummy(),
|
||||
ui_render_buffers: create_ui_render_buffers(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn draw_surface(&self, surf: &Surface, data: &SurfaceSharedData, resource_manager: &ResourceManager) {
|
||||
unsafe {
|
||||
if let Some(resource) = resource_manager.borrow_resource(surf.get_texture_resource_handle()) {
|
||||
if let ResourceKind::Texture(texture) = resource.borrow_kind() {
|
||||
gl::BindTexture(gl::TEXTURE_2D, texture.gpu_tex);
|
||||
} else {
|
||||
gl::BindTexture(gl::TEXTURE_2D, 0);
|
||||
gl::BindTexture(gl::TEXTURE_2D, self.white_dummy);
|
||||
}
|
||||
} else {
|
||||
gl::BindTexture(gl::TEXTURE_2D, 0);
|
||||
gl::BindTexture(gl::TEXTURE_2D, self.white_dummy);
|
||||
}
|
||||
gl::BindVertexArray(data.get_vertex_array_object());
|
||||
gl::DrawElements(gl::TRIANGLES,
|
||||
@@ -253,6 +386,51 @@ impl Renderer {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn upload_font_cache(&mut self, font_cache: &mut Pool<Font>) {
|
||||
unsafe {
|
||||
for font in font_cache.iter_mut() {
|
||||
if font.get_texture_id() == 0 {
|
||||
let mut texture: GLuint = 0;
|
||||
gl::GenTextures(1, &mut texture);
|
||||
|
||||
gl::BindTexture(gl::TEXTURE_2D, texture);
|
||||
|
||||
let rgba_pixels: Vec<Color> = font.get_atlas_pixels().
|
||||
iter().map(|p| Color { r: *p, g: *p, b: *p, a: *p }).collect();
|
||||
|
||||
gl::TexImage2D(
|
||||
gl::TEXTURE_2D,
|
||||
0,
|
||||
gl::RGBA as i32,
|
||||
font.get_atlas_size(),
|
||||
font.get_atlas_size(),
|
||||
0,
|
||||
gl::RGBA,
|
||||
gl::UNSIGNED_BYTE,
|
||||
rgba_pixels.as_ptr() as *const c_void,
|
||||
);
|
||||
gl::TexParameteri(
|
||||
gl::TEXTURE_2D,
|
||||
gl::TEXTURE_MAG_FILTER,
|
||||
gl::LINEAR as i32,
|
||||
);
|
||||
gl::TexParameteri(
|
||||
gl::TEXTURE_2D,
|
||||
gl::TEXTURE_MIN_FILTER,
|
||||
gl::LINEAR as i32,
|
||||
);
|
||||
gl::BindTexture(gl::TEXTURE_2D, 0);
|
||||
|
||||
println!("font cache loaded! {}", texture);
|
||||
|
||||
font.set_texture_id(texture);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
check_gl_error();
|
||||
}
|
||||
|
||||
pub fn upload_resources(&mut self, state: &mut State) {
|
||||
state.get_resource_manager_mut().for_each_texture_mut(|texture| {
|
||||
if texture.need_upload {
|
||||
@@ -296,77 +474,72 @@ impl Renderer {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render(&mut self, state: &State) {
|
||||
let client_size = self.context.get_inner_size().unwrap();
|
||||
|
||||
pub fn render(&mut self, state: &State, drawing_context: &DrawingContext) {
|
||||
unsafe {
|
||||
let client_size = self.context.get_inner_size().unwrap();
|
||||
|
||||
|
||||
gl::ClearColor(0.0, 0.63, 0.91, 1.0);
|
||||
gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
for scene in state.get_scenes().iter() {
|
||||
// Prepare for render - fill lists of nodes participating in rendering
|
||||
// by traversing scene graph
|
||||
self.meshes.clear();
|
||||
self.lights.clear();
|
||||
self.cameras.clear();
|
||||
self.traversal_stack.clear();
|
||||
self.traversal_stack.push(scene.root.clone());
|
||||
while let Some(node_handle) = self.traversal_stack.pop() {
|
||||
if let Some(node) = scene.get_node(&node_handle) {
|
||||
match node.borrow_kind() {
|
||||
NodeKind::Mesh(_) => self.meshes.push(node_handle),
|
||||
NodeKind::Light(_) => self.lights.push(node_handle),
|
||||
NodeKind::Camera(_) => self.cameras.push(node_handle),
|
||||
_ => ()
|
||||
}
|
||||
// Queue children for render
|
||||
for child_handle in node.children.iter() {
|
||||
self.traversal_stack.push(child_handle.clone());
|
||||
|
||||
for scene in state.get_scenes().iter() {
|
||||
// Prepare for render - fill lists of nodes participating in rendering
|
||||
// by traversing scene graph
|
||||
self.meshes.clear();
|
||||
self.lights.clear();
|
||||
self.cameras.clear();
|
||||
self.traversal_stack.clear();
|
||||
self.traversal_stack.push(scene.root.clone());
|
||||
while let Some(node_handle) = self.traversal_stack.pop() {
|
||||
if let Some(node) = scene.get_node(&node_handle) {
|
||||
match node.borrow_kind() {
|
||||
NodeKind::Mesh(_) => self.meshes.push(node_handle),
|
||||
NodeKind::Light(_) => self.lights.push(node_handle),
|
||||
NodeKind::Camera(_) => self.cameras.push(node_handle),
|
||||
_ => ()
|
||||
}
|
||||
// Queue children for render
|
||||
for child_handle in node.children.iter() {
|
||||
self.traversal_stack.push(child_handle.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe {
|
||||
gl::UseProgram(self.flat_shader.id);
|
||||
}
|
||||
gl::UseProgram(self.flat_shader.program.id);
|
||||
|
||||
let u_wvp = self.flat_shader.get_uniform_location("worldViewProjection");
|
||||
// Render scene from each camera
|
||||
for camera_handle in self.cameras.iter() {
|
||||
if let Some(camera_node) = scene.get_node(&camera_handle) {
|
||||
if let NodeKind::Camera(camera) = camera_node.borrow_kind() {
|
||||
|
||||
// Render scene from each camera
|
||||
for camera_handle in self.cameras.iter() {
|
||||
if let Some(camera_node) = scene.get_node(&camera_handle) {
|
||||
if let NodeKind::Camera(camera) = camera_node.borrow_kind() {
|
||||
|
||||
// Setup viewport
|
||||
unsafe {
|
||||
// Setup viewport
|
||||
let viewport = camera.get_viewport_pixels(
|
||||
Vec2 {
|
||||
x: client_size.width as f32,
|
||||
y: client_size.height as f32,
|
||||
});
|
||||
gl::Viewport(viewport.x, viewport.y, viewport.w, viewport.h);
|
||||
}
|
||||
|
||||
let view_projection = camera.get_view_projection_matrix();
|
||||
|
||||
for mesh_handle in self.meshes.iter() {
|
||||
if let Some(node) = scene.get_node(&mesh_handle) {
|
||||
if !node.get_global_visibility() {
|
||||
continue;
|
||||
}
|
||||
let view_projection = camera.get_view_projection_matrix();
|
||||
|
||||
let mvp = view_projection * node.global_transform;
|
||||
for mesh_handle in self.meshes.iter() {
|
||||
if let Some(node) = scene.get_node(&mesh_handle) {
|
||||
if !node.get_global_visibility() {
|
||||
continue;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
gl::UseProgram(self.flat_shader.id);
|
||||
gl::UniformMatrix4fv(u_wvp, 1, gl::FALSE, &mvp.f as *const GLfloat);
|
||||
}
|
||||
let mvp = view_projection * node.global_transform;
|
||||
|
||||
if let NodeKind::Mesh(mesh) = node.borrow_kind() {
|
||||
for surface in mesh.get_surfaces().iter() {
|
||||
if let Some(data) = state.get_surface_data_storage().borrow(surface.get_data_handle()) {
|
||||
self.draw_surface(surface, data, state.get_resource_manager());
|
||||
gl::UseProgram(self.flat_shader.program.id);
|
||||
gl::UniformMatrix4fv(self.flat_shader.wvp_matrix, 1, gl::FALSE, &mvp.f as *const GLfloat);
|
||||
|
||||
if let NodeKind::Mesh(mesh) = node.borrow_kind() {
|
||||
for surface in mesh.get_surfaces().iter() {
|
||||
if let Some(data) = state.get_surface_data_storage().borrow(surface.get_data_handle()) {
|
||||
self.draw_surface(surface, data, state.get_resource_manager());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -375,8 +548,114 @@ impl Renderer {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Render UI on top of everything
|
||||
gl::Disable(gl::DEPTH_TEST);
|
||||
gl::Enable(gl::BLEND);
|
||||
gl::BlendFunc(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA);
|
||||
gl::Enable(gl::STENCIL_TEST);
|
||||
gl::Disable(gl::CULL_FACE);
|
||||
|
||||
gl::UseProgram(self.ui_shader.program.id);
|
||||
gl::ActiveTexture(gl::TEXTURE0);
|
||||
|
||||
let index_bytes = drawing_context.get_indices_bytes();
|
||||
let vertex_bytes = drawing_context.get_vertices_bytes();
|
||||
|
||||
/* upload to gpu */
|
||||
gl::BindVertexArray(self.ui_render_buffers.vao);
|
||||
|
||||
gl::BindBuffer(gl::ARRAY_BUFFER, self.ui_render_buffers.vbo);
|
||||
gl::BufferData(gl::ARRAY_BUFFER, vertex_bytes, drawing_context.get_vertices_ptr(), gl::DYNAMIC_DRAW);
|
||||
|
||||
gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, self.ui_render_buffers.ebo);
|
||||
gl::BufferData(gl::ELEMENT_ARRAY_BUFFER, index_bytes, drawing_context.get_indices_ptr(), gl::DYNAMIC_DRAW);
|
||||
|
||||
let mut offset = 0;
|
||||
gl::VertexAttribPointer(0,
|
||||
2,
|
||||
gl::FLOAT,
|
||||
gl::FALSE,
|
||||
drawing_context.get_vertex_size(),
|
||||
offset as *const c_void);
|
||||
gl::EnableVertexAttribArray(0);
|
||||
offset += std::mem::size_of::<Vec2>();
|
||||
|
||||
gl::VertexAttribPointer(1,
|
||||
2,
|
||||
gl::FLOAT,
|
||||
gl::FALSE,
|
||||
drawing_context.get_vertex_size(),
|
||||
offset as *const c_void);
|
||||
gl::EnableVertexAttribArray(1);
|
||||
offset += std::mem::size_of::<Vec2>();
|
||||
|
||||
gl::VertexAttribPointer(2,
|
||||
4,
|
||||
gl::UNSIGNED_BYTE,
|
||||
gl::TRUE,
|
||||
drawing_context.get_vertex_size(),
|
||||
offset as *const c_void);
|
||||
gl::EnableVertexAttribArray(2);
|
||||
|
||||
let ortho = Mat4::ortho(0.0,
|
||||
client_size.width as f32,
|
||||
client_size.height as f32,
|
||||
0.0,
|
||||
-1.0,
|
||||
1.0);
|
||||
gl::UniformMatrix4fv(self.ui_shader.wvp_matrix, 1, gl::FALSE, ortho.f.as_ptr() as *const f32);
|
||||
|
||||
for cmd in drawing_context.get_command_buffer() {
|
||||
let index_count = cmd.get_triangle_count() * 3;
|
||||
match cmd.get_kind() {
|
||||
CommandKind::Clip => {
|
||||
let is_root_nesting = cmd.get_nesting() == 1;
|
||||
if is_root_nesting {
|
||||
gl::Clear(gl::STENCIL_BUFFER_BIT);
|
||||
}
|
||||
if cmd.get_nesting() != 0 {
|
||||
gl::Enable(gl::STENCIL_TEST);
|
||||
} else {
|
||||
gl::Disable(gl::STENCIL_TEST);
|
||||
}
|
||||
gl::StencilOp(gl::KEEP, gl::KEEP, gl::INCR);
|
||||
// Make sure that clipping rect will be drawn at previous nesting level only (clip to parent)
|
||||
gl::StencilFunc(gl::EQUAL, (cmd.get_nesting() - 1) as i32, 0xFF);
|
||||
gl::BindTexture(gl::TEXTURE_2D, self.white_dummy);
|
||||
// Draw clipping geometry to stencil buffer
|
||||
gl::StencilMask(0xFF);
|
||||
}
|
||||
CommandKind::Geometry => {
|
||||
// Make sure to draw geometry only on clipping geometry with current nesting level
|
||||
gl::StencilFunc(gl::EQUAL, cmd.get_nesting() as i32, 0xFF);
|
||||
|
||||
if cmd.get_texture() != 0 {
|
||||
gl::ActiveTexture(gl::TEXTURE0);
|
||||
gl::Uniform1i(self.ui_shader.diffuse_texture, 0);
|
||||
gl::BindTexture(gl::TEXTURE_2D, cmd.get_texture());
|
||||
} else {
|
||||
gl::BindTexture(gl::TEXTURE_2D, self.white_dummy);
|
||||
}
|
||||
|
||||
// Do not draw geometry to stencil buffer
|
||||
gl::StencilMask(0x00);
|
||||
}
|
||||
}
|
||||
gl::DrawElements(gl::TRIANGLES,
|
||||
index_count as i32,
|
||||
gl::UNSIGNED_INT,
|
||||
(cmd.get_index_offset() * std::mem::size_of::<GLuint>()) as *const c_void);
|
||||
|
||||
gl::BindVertexArray(0);
|
||||
}
|
||||
gl::Disable(gl::STENCIL_TEST);
|
||||
gl::Disable(gl::BLEND);
|
||||
gl::Enable(gl::DEPTH_TEST);
|
||||
}
|
||||
|
||||
check_gl_error();
|
||||
|
||||
self.context.swap_buffers().unwrap();
|
||||
}
|
||||
}
|
||||
@@ -1222,7 +1222,7 @@ pub fn load_to_scene(scene: &mut Scene, state: &mut State, path: &Path)
|
||||
-> Result<Handle<Node>, String> {
|
||||
let start_time = Instant::now();
|
||||
|
||||
println!("FBX;Trying to load {:?}", path);
|
||||
println!("FBX: Trying to load {:?}", path);
|
||||
|
||||
let now = Instant::now();
|
||||
let ref mut fbx = read_ascii(path)?;
|
||||
@@ -1236,7 +1236,7 @@ pub fn load_to_scene(scene: &mut Scene, state: &mut State, path: &Path)
|
||||
let result = fbx.convert(state, scene);
|
||||
println!("\tFBX: Conversion - {} ms", now.elapsed().as_millis());
|
||||
|
||||
println!("FBX: {:?} loaded in {} ms", path, start_time.elapsed().as_millis());
|
||||
println!("\tFBX: {:?} loaded in {} ms", path, start_time.elapsed().as_millis());
|
||||
|
||||
result
|
||||
}
|
||||
+127
-45
@@ -2,7 +2,7 @@
|
||||
|
||||
use crate::math::vec2::Vec2;
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::{HashMap};
|
||||
use std::collections::HashMap;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
@@ -25,7 +25,7 @@ struct Polygon {
|
||||
points: Vec<Point>
|
||||
}
|
||||
|
||||
struct FontGlyph {
|
||||
pub struct FontGlyph {
|
||||
bitmap_top: f32,
|
||||
bitmap_left: f32,
|
||||
bitmap_width: f32,
|
||||
@@ -76,7 +76,7 @@ struct Bitmap {
|
||||
height: usize,
|
||||
}
|
||||
|
||||
struct Font {
|
||||
pub struct Font {
|
||||
height: f32,
|
||||
glyphs: Vec<FontGlyph>,
|
||||
ascender: f32,
|
||||
@@ -84,6 +84,7 @@ struct Font {
|
||||
line_gap: f32,
|
||||
char_map: HashMap<u32, usize>,
|
||||
atlas: Vec<u8>,
|
||||
atlas_size: i32,
|
||||
texture_id: u32,
|
||||
}
|
||||
|
||||
@@ -243,7 +244,7 @@ fn fourcc(d: u8, c: u8, b: u8, a: u8) -> u32 {
|
||||
((d as u32) << 24) | ((c as u32) << 16) | ((b as u32) << 8) | (a as u32)
|
||||
}
|
||||
|
||||
fn segmented_mapping(subtable: *const u8, unicode: u32) -> u32 {
|
||||
fn segmented_mapping(subtable: *const u8, unicode: u32) -> usize {
|
||||
unsafe {
|
||||
let segment_count = (get_u16(subtable.offset(6)) / 2) as u32;
|
||||
let end_codes = subtable.offset(14);
|
||||
@@ -264,10 +265,10 @@ fn segmented_mapping(subtable: *const u8, unicode: u32) -> u32 {
|
||||
if start_code <= unicode {
|
||||
let range_offset = (get_u16(id_range_offset.offset(2 * segment as isize)) / 2) as u32;
|
||||
if range_offset == 0 {
|
||||
return (unicode + get_u16(id_delta.offset(2 * segment as isize)) as u32) & 0xFFFF;
|
||||
return ((unicode + get_u16(id_delta.offset(2 * segment as isize)) as u32) & 0xFFFF) as usize;
|
||||
} else {
|
||||
let offset = 2 * (segment + range_offset + (unicode - start_code));
|
||||
return get_u16(id_range_offset.offset(offset as isize)) as u32;
|
||||
return get_u16(id_range_offset.offset(offset as isize)) as usize;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -276,25 +277,25 @@ fn segmented_mapping(subtable: *const u8, unicode: u32) -> u32 {
|
||||
}
|
||||
}
|
||||
|
||||
fn direct_mapping(subtable: *const u8, unicode: u32) -> u32 {
|
||||
fn direct_mapping(subtable: *const u8, unicode: u32) -> usize {
|
||||
unsafe {
|
||||
if unicode < 256 {
|
||||
let indices = subtable.offset(6);
|
||||
return indices.offset(unicode as isize).read() as u32;
|
||||
return indices.offset(unicode as isize).read() as usize;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
fn dense_mapping(subtable: *const u8, unicode: u32) -> u32 {
|
||||
fn dense_mapping(subtable: *const u8, unicode: u32) -> usize {
|
||||
unsafe {
|
||||
let first = get_u16(subtable.offset(6)) as u32;
|
||||
let entry_count = get_u16(subtable.offset(8)) as u32;
|
||||
let indices = subtable.offset(10);
|
||||
|
||||
if unicode > first && unicode < first + entry_count {
|
||||
return get_u16(indices.offset(2 * (unicode - first) as isize)) as u32;
|
||||
return get_u16(indices.offset(2 * (unicode - first) as isize)) as usize;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -497,7 +498,7 @@ impl TrueType {
|
||||
}
|
||||
}
|
||||
|
||||
fn unicode_to_glyph_index(&self, unicode: u32) -> u32 {
|
||||
fn unicode_to_glyph_index(&self, unicode: u32) -> usize {
|
||||
unsafe {
|
||||
let subtable_count = get_u16(self.cmap_table.offset(2));
|
||||
for i in 0..subtable_count {
|
||||
@@ -889,6 +890,7 @@ impl Font {
|
||||
char_map: HashMap::new(),
|
||||
texture_id: 0,
|
||||
atlas: Vec::new(),
|
||||
atlas_size: 0,
|
||||
};
|
||||
|
||||
for ttf_glyph in ttf.glyphs.iter() {
|
||||
@@ -897,12 +899,61 @@ impl Font {
|
||||
|
||||
font.pack();
|
||||
|
||||
for unicode in char_set {
|
||||
let index = ttf.unicode_to_glyph_index(unicode);
|
||||
font.char_map.insert(unicode, index);
|
||||
}
|
||||
|
||||
Some(font)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_glyph(&self, unicode: char) -> Option<&FontGlyph> {
|
||||
match self.char_map.get(&(unicode as u32)) {
|
||||
Some(glyph_index) => self.glyphs.get(*glyph_index),
|
||||
None => None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_height(&self) -> f32 {
|
||||
self.height
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_ascender(&self) -> f32 {
|
||||
self.ascender
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_descender(&self) -> f32 {
|
||||
self.descender
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_texture_id(&mut self, id: u32) {
|
||||
self.texture_id = id;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_texture_id(&self) -> u32 {
|
||||
self.texture_id
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_atlas_pixels(&self) -> &[u8] {
|
||||
self.atlas.as_slice()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_atlas_size(&self) -> i32 {
|
||||
self.atlas_size
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn compute_atlas_size(&self) -> i32 {
|
||||
let mut area = 0.0;
|
||||
for glyph in self.glyphs.iter() {
|
||||
@@ -912,34 +963,26 @@ impl Font {
|
||||
}
|
||||
|
||||
fn pack(&mut self) {
|
||||
let atlas_size = self.compute_atlas_size();
|
||||
self.atlas_size = self.compute_atlas_size();
|
||||
|
||||
self.atlas = vec![0; (atlas_size * atlas_size) as usize];
|
||||
self.atlas = vec![0; (self.atlas_size * self.atlas_size) as usize];
|
||||
|
||||
let mut rect_packer = RectPacker::new(atlas_size, atlas_size);
|
||||
let mut rect_packer = RectPacker::new(self.atlas_size, self.atlas_size);
|
||||
for glyph in self.glyphs.iter_mut() {
|
||||
|
||||
if let Some(bounds) = rect_packer.find_free(glyph.bitmap_width as i32, glyph.bitmap_height as i32) {
|
||||
let w = bounds.w as f32 / atlas_size as f32;
|
||||
let h = bounds.h as f32 / atlas_size as f32;
|
||||
let x = bounds.x as f32 / atlas_size as f32;
|
||||
let y = bounds.y as f32 / atlas_size as f32;
|
||||
|
||||
glyph.tex_coords[0].x = x;
|
||||
glyph.tex_coords[0].y = y;
|
||||
|
||||
glyph.tex_coords[1].x = x + w;
|
||||
glyph.tex_coords[1].y = y;
|
||||
|
||||
glyph.tex_coords[2].x = x + w;
|
||||
glyph.tex_coords[2].y = y + h;
|
||||
|
||||
glyph.tex_coords[3].x = x;
|
||||
glyph.tex_coords[3].y = y + h;
|
||||
|
||||
if let Some(bounds) = rect_packer.find_free(glyph.bitmap_width as i32, glyph.bitmap_height as i32) {
|
||||
let w = bounds.w as f32 / self.atlas_size as f32;
|
||||
let h = bounds.h as f32 / self.atlas_size as f32;
|
||||
let x = bounds.x as f32 / self.atlas_size as f32;
|
||||
let y = bounds.y as f32 / self.atlas_size as f32;
|
||||
|
||||
glyph.tex_coords[0] = Vec2 { x, y };
|
||||
glyph.tex_coords[1] = Vec2 { x: x + w, y };
|
||||
glyph.tex_coords[2] = Vec2 { x: x + w, y: y + h };
|
||||
glyph.tex_coords[3] = Vec2 { x, y: y + h };
|
||||
|
||||
let row_end = bounds.y + bounds.h;
|
||||
let col_end = bounds.x + bounds.w;
|
||||
|
||||
|
||||
// Copy glyph pixels to atlas pixels
|
||||
let mut row = bounds.y;
|
||||
let mut src_row = 0;
|
||||
@@ -947,7 +990,7 @@ impl Font {
|
||||
let mut col = bounds.x;
|
||||
let mut src_col = 0;
|
||||
while col < col_end {
|
||||
self.atlas[(row * atlas_size + col) as usize] = glyph.pixels[(src_row * bounds.w + src_col) as usize];
|
||||
self.atlas[(row * self.atlas_size + col) as usize] = glyph.pixels[(src_row * bounds.w + src_col) as usize];
|
||||
col += 1;
|
||||
src_col += 1;
|
||||
}
|
||||
@@ -959,22 +1002,61 @@ impl Font {
|
||||
println!("Insufficient atlas size!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FontGlyph {
|
||||
#[inline]
|
||||
pub fn get_bitmap_top(&self) -> f32 {
|
||||
self.bitmap_top
|
||||
}
|
||||
|
||||
let mut path = PathBuf::from("data/raster/_atlas.png");
|
||||
image::save_buffer(path, self.atlas.as_slice(),
|
||||
atlas_size as u32,
|
||||
atlas_size as u32,
|
||||
ColorType::Gray(8));
|
||||
#[inline]
|
||||
pub fn get_bitmap_left(&self) -> f32 {
|
||||
self.bitmap_left
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_bitmap_width(&self) -> f32 {
|
||||
self.bitmap_width
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_bitmap_height(&self) -> f32 {
|
||||
self.bitmap_height
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_pixels(&self) -> &[u8] {
|
||||
self.pixels.as_slice()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_advance(&self) -> f32 {
|
||||
self.advance
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn has_outline(&self) -> bool {
|
||||
self.has_outline
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_tex_coords(&self) -> &[Vec2; 4] {
|
||||
&self.tex_coords
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn font_test() {
|
||||
let mut char_set: Vec<u32> = Vec::new();
|
||||
for i in 0..255 {
|
||||
char_set.push(i);
|
||||
let font = Font::load(Path::new("data/fonts/font.ttf"), 40.0, (0..255).collect()).unwrap();
|
||||
let raster_path = Path::new("data/raster");
|
||||
if !raster_path.exists() {
|
||||
std::fs::create_dir(raster_path).unwrap();
|
||||
}
|
||||
let f = Font::load(Path::new("data/fonts/font.ttf"), 40.0, char_set);
|
||||
assert!(f.is_some());
|
||||
let path = PathBuf::from("data/raster/_atlas.png");
|
||||
image::save_buffer(path, font.atlas.as_slice(),
|
||||
font.atlas_size as u32,
|
||||
font.atlas_size as u32,
|
||||
ColorType::Gray(8)).unwrap();
|
||||
}
|
||||
Reference in New Issue
Block a user