first 'full' layout draft impl done.

found a memory bug...
This commit is contained in:
Edward R. Gonzalez 2024-03-14 02:02:09 -04:00
parent 180c296556
commit cf7660e385
10 changed files with 336 additions and 411 deletions

View File

@ -3,8 +3,8 @@ package sectr
import "core:math/linalg"
pos_within_range2 :: proc( pos : Vec2, range : Range2 ) -> b32 {
within_x := pos.x > range.p0.x && pos.x < range.p1.x
within_y := pos.y < range.p0.y && pos.y > range.p1.y
within_x := pos.x > range.min.x && pos.x < range.max.x
within_y := pos.y > range.min.y && pos.y < range.max.y
return b32(within_x && within_y)
}

View File

@ -70,4 +70,4 @@ equal_range2 :: #force_inline proc "contextless" ( a, b : Range2 ) -> b32 {
size_range2 :: #force_inline proc "contextless" ( value : Range2 ) -> Vec2 {
return { value.p1.x - value.p0.x, value.p0.y - value.p1.y }
}
}

View File

@ -150,16 +150,16 @@ render_mode_2d :: proc()
computed_size := computed.bounds.p1 - computed.bounds.p0
if ! within_range2( view_bounds, computed.bounds ) {
continue
// continue
}
// TODO(Ed) : Render Borders
// profile_begin("Calculating Raylib rectangles")
render_bounds := Range2 { pts = {
render_bounds := range2(
world_to_screen_pos(computed.bounds.min),
world_to_screen_pos(computed.bounds.max),
}}
)
render_padding := range2(
world_to_screen_pos(computed.padding.min),
@ -172,21 +172,21 @@ render_mode_2d :: proc()
rect_bounds := rl.Rectangle {
render_bounds.min.x,
render_bounds.min.y,
render_bounds.max.x - render_bounds.min.x,
render_bounds.max.y - render_bounds.min.y,
render_bounds.max.y,
abs(render_bounds.max.x - render_bounds.min.x),
abs(render_bounds.max.y - render_bounds.min.y),
}
rect_padding := rl.Rectangle {
render_padding.min.x,
render_padding.min.y,
render_padding.max.x - render_padding.min.x,
render_padding.max.y - render_padding.min.y,
render_padding.max.y,
abs(render_padding.max.x - render_padding.min.x),
abs(render_padding.max.y - render_padding.min.y),
}
rect_content := rl.Rectangle {
render_content.min.x,
render_content.min.y,
render_content.max.x - render_content.min.x,
render_content.max.y - render_content.min.y,
render_content.max.y,
abs(render_content.max.x - render_content.min.x),
abs(render_content.max.y - render_content.min.y),
}
// profile_end()
@ -222,7 +222,7 @@ render_mode_2d :: proc()
draw_rectangle_lines( rect_padding, style, Color_Debug_UI_Padding_Bounds, line_thickness )
}
else {
draw_rectangle_lines( rect_padding, style, Color_Debug_UI_Content_Bounds, line_thickness )
draw_rectangle_lines( rect_content, style, Color_Debug_UI_Content_Bounds, line_thickness )
}
// profile_end()

View File

@ -231,7 +231,7 @@ update :: proc( delta_time : f64 ) -> b32
frame_style_default,
}}
frame_theme.disabled.bg_color = Color_Frame_Disabled
// frame_theme.hot.bg_color = Color_Frame_Hover
frame_theme.hot.bg_color = Color_Frame_Hover
frame_theme.active.bg_color = Color_Frame_Select
ui_style_theme( frame_theme )
@ -240,20 +240,22 @@ update :: proc( delta_time : f64 ) -> b32
// test_text_box()
// test_parenting()
if true
if false
{
frame := ui_widget( "Frame", {} )
ui_parent(frame)
parent_layout := default_layout
parent_layout.size = range2( { 300, 300 }, {} )
parent_layout.alignment = { 0.0, 0.0 }
parent_layout.alignment = { 0.5, 0.5 }
parent_layout.margins = { 100, 100, 100, 100 }
parent_layout.padding = {}
parent_layout.pos = { 0, 0 }
parent_theme := frame_style_default
parent_theme.layout = parent_layout
parent_theme.flags = {
// .Fixed_Position_X, .Fixed_Position_Y,
.Fixed_Width, .Fixed_Height,
}
ui_theme_via_style(parent_theme)
@ -262,7 +264,7 @@ update :: proc( delta_time : f64 ) -> b32
ui_parent(parent)
{
if parent.first_frame {
debug.draggable_box_pos = parent.style.layout.pos + { 0, 0 }
debug.draggable_box_pos = parent.style.layout.pos
debug.draggable_box_size = parent.style.layout.size.min
}
@ -285,19 +287,20 @@ update :: proc( delta_time : f64 ) -> b32
parent.style.bg_color = Color_Blue
}
parent.style.layout.pos = debug.draggable_box_pos
parent.style.layout.pos = debug.draggable_box_pos
parent.style.layout.size.min = debug.draggable_box_size
}
child_layout := default_layout
child_layout.size = range2({ 50, 50 }, { 200, 200 })
child_layout.alignment = { 0.0, 0.0 }
child_layout.margins = { 00, 00, 00, 00 }
child_layout.size = range2({ 75, 75 }, { 0, 0 })
child_layout.alignment = { 0.5, 0.0 }
child_layout.margins = { 20, 20, 20, 20 }
child_layout.padding = {}
child_layout.anchor = range2({ 0.0, 0.0 }, { 0.0, 0.0 })
child_layout.anchor = range2({ 0.0, 0.0 }, { 0.0, 1.0 })
child_layout.pos = { 0, 0 }
child_theme := frame_style_default
child_theme.bg_color = Color_GreyRed
child_theme.flags = {
// .Fixed_Width, .Fixed_Height,
}
@ -307,7 +310,7 @@ update :: proc( delta_time : f64 ) -> b32
}
// Whitespace AST test
if false
if true
{
profile("Whitespace AST test")

View File

@ -77,11 +77,13 @@ UI_BoxFlag_Scroll :: UI_BoxFlags { .Scroll_X, .Scroll_Y }
// The UI_Box's actual positioning and sizing
// There is an excess of rectangles here for debug puproses.
UI_Computed :: struct {
bounds : Range2,
padding : Range2,
content : Range2,
text_pos : Vec2,
text_size : Vec2,
anchors : Range2, // Bounds for anchors within parent
margins : Range2, // Bounds for margins within parent
bounds : Range2, // Bounds for box itself
padding : Range2, // Bounds for padding's starting bounds (will be offset by border if there is one)
content : Range2, // Bounds for content (text or children)
text_pos : Vec2, // Position of text within content
text_size : Vec2, // Size of text within content
}
UI_LayoutSide :: struct {
@ -111,12 +113,6 @@ UI_Key :: distinct u64
UI_Scalar :: f32
// TODO(Ed): I'm not sure if Percentage is needed or if this would over complicate things...
// UI_Scalar :: struct {
// VPixels : f32,
// Percentage : f32,
// }
UI_ScalarConstraint :: struct {
min, max : UI_Scalar,
}
@ -125,10 +121,6 @@ UI_Scalar2 :: [Axis2.Count]UI_Scalar
// Desiered constraints on the UI_Box.
UI_Layout :: struct {
// TODO(Ed) : Should layout have its own flags (separate from the style flags)
// flags : UI_LayoutFlags
// TODO(Ed) : Make sure this is all we need to represent an anchor.
anchor : Range2,
alignment : Vec2,
text_alignment : Vec2,
@ -145,7 +137,6 @@ UI_Layout :: struct {
// If the box's flags has Fixed_Position, then this will be its aboslute position in the relative coordinate space
pos : Vec2,
// TODO(Ed): Support a min/max range for the size of a box
size : Range2,
// TODO(Ed) : Should thsi just always be WS_Pos for workspace UI?
@ -178,16 +169,21 @@ UI_StyleFlag :: enum u32 {
// (Specified in the parent)
Clip_Children_To_Bounds,
// Enforces the widget will always remain in a specific position relative to the parent.
// Enforces the box will always remain in a specific position relative to the parent.
// Overriding the anchors and margins.
Fixed_Position_X,
Fixed_Position_Y,
// Enforces box will always be within the bounds of the parent box.
Clamp_Position_X,
Clamp_Position_Y,
// Enroces the widget will maintain its size reguardless of any constraints
// Will override parent constraints
Fixed_Width,
Fixed_Height,
// Will size the box to its text. (Padding & Margins will thicken )
Size_To_Text,
Text_Wrap,
@ -266,8 +262,8 @@ UI_Box :: struct {
// prev_computed : UI_Computed,
// prev_style : UI_Style,v
mouse : UI_InteractState,
keyboard : UI_InteractState,
// mouse : UI_InteractState,
// keyboard : UI_InteractState,
}
// UI_BoxFlags_Stack_Size :: 512

View File

@ -11,28 +11,18 @@ ui_compute_layout :: proc()
root := state.project.workspace.ui.root
{
computed := & root.computed
bounds := & computed.bounds
style := root.style
layout := & style.layout
bounds.min = layout.pos
bounds.max = layout.size.min
computed.content = bounds^
computed.padding = {}
computed.bounds.min = layout.pos
computed.bounds.max = layout.size.min
computed.content = computed.bounds
}
current := root.first
for ; current != nil;
{
profile("Layout Box")
parent := current.parent
parent_content := parent.computed.content
computed := & current.computed
style := current.style
layout := & style.layout
// These are used to choose via multiplication weather to apply
// position & size constraints of the parent.
@ -46,51 +36,23 @@ ui_compute_layout :: proc()
size_to_text : bool = .Size_To_Text in style.flags
parent := current.parent
computed := & current.computed
margins := range2(
{ layout.margins.left, -layout.margins.top },
{ -layout.margins.right, layout.margins.bottom },
)
margined_bounds := range2(
parent_content.p0 + margins.p0,
parent_content.p1 + margins.p1,
)
margined_size := linalg.abs(margined_bounds.p1 - margined_bounds.p0)
anchor := & layout.anchor
// Margins + Anchors Applied
adjusted_bounds := range2(
{ margined_bounds.p0.x + margined_size.x * anchor.p0.x, margined_bounds.p0.y + margined_size.y * anchor.p0.y },
{ margined_bounds.p1.x + margined_size.x * anchor.p1.x, margined_bounds.p1.y + margined_size.y * anchor.p1.y },
)
adjusted_bounds_size := linalg.abs(adjusted_bounds.p1 - adjusted_bounds.p0)
// Resolves final constrained bounds of the parent for the child box
// Will be applied to the box after the child's positon is resolved.
fixed_pos := Vec2 { fixed_pos_x, fixed_pos_y }
constraint_min := adjusted_bounds.min //* (1 - fixed_pos) + parent_content.min * fixed_pos
constraint_max := adjusted_bounds.max //* (1 - fixed_pos) + parent_content.max * fixed_pos
// constraint_min_x := adjusted_bounds.min.x //* (1 - fixed_pos_x) + parent_content.min.x * fixed_pos_x
// constraint_min_y := adjusted_bounds.min.y //* (1 - fixed_pos_y) + parent_content.min.y * fixed_pos_y
// constraint_max_x := adjusted_bounds.max.x //* (1 - fixed_pos_x) + parent_content.max.x * fixed_pos_x
// constraint_max_y := adjusted_bounds.max.y //* (1 - fixed_pos_y) + parent_content.max.y * fixed_pos_y
constrained_bounds := range2(
constraint_min,
constraint_max,
// { constraint_min_x, constraint_min_y },
// { constraint_max_x, constraint_max_y },
)
constrained_size := linalg.abs(constrained_bounds.p1 - constrained_bounds.p0)
parent_content := parent.computed.content
parent_content_size := parent_content.max - parent_content.min
parent_center := parent_content.min + parent_content_size * 0.5
layout := & style.layout
/*
If fixed position (X or Y):
* Ignore Margins
* Ignore Anchors
If clampped position (X or Y):
* Positon cannot exceed the anchors/margins bounds.
If fixed size (X or Y):
* Ignore Parent constraints (can only be clipped)
@ -102,118 +64,53 @@ ui_compute_layout :: proc()
If size.min is not 0:
* Ignore parent constraints if the bounds go below that value.
If size.max is not 0:
* Allow the child box to spread to entire adjusted content bounds.
If size.max is 0:
* Allow the child box to spread to entire adjusted content bounds, otherwise clampped to max size.
*/
size_unit_bounds := range2(
{ 0.0, 0.0 },
{ 1.0, -1.0 },
// 1. Anchors
anchor := & layout.anchor
// anchored_pos := parent_content.min + parent_content_size * anchor.min
// anchored_size := parent_content_size * linalg.abs( anchor.p1 - anchor.p0 )
anchored_bounds := range2(
{
parent_content.min.x + parent_content_size.x * anchor.min.x,
parent_content.min.y + parent_content_size.y * anchor.min.y,
},
{
parent_content.max.x - parent_content_size.x * anchor.max.x,
parent_content.max.y - parent_content_size.y * anchor.max.y,
}
)
anchored_bounds_origin := (anchored_bounds.min + anchored_bounds.max) * 0.5
alignment := layout.alignment
aligned_unit_bounds := range2(
size_unit_bounds.p0 + { -alignment.x, alignment.y },
size_unit_bounds.p1 - { alignment.x, -alignment.y },
// 2. Apply Margins
margins := range2(
{ layout.margins.left, layout.margins.bottom },
{ layout.margins.right, layout.margins.top },
)
wtf := range2(
{ constrained_bounds.p0.x, constrained_bounds.p0.y },
{ constrained_bounds.p1.x, constrained_bounds.p1.y },
margined_bounds := range2(
anchored_bounds.min + margins.min,
anchored_bounds.max - margins.max,
)
margined_bounds_origin := (margined_bounds.min + margined_bounds.max) * 0.5
margined_size := margined_bounds.max - margined_bounds.min
// projected_bounds := range2(
// aligned_unit_bounds.p0 * wtf.p0,
// aligned_unit_bounds.p1 * wtf.p1,
// )
// 3. Enforce Min/Max Size Constraints
adjusted_max_size_x := layout.size.max.x > 0 ? min( margined_size.x, layout.size.max.x ) : margined_size.x
adjusted_max_size_y := layout.size.max.y > 0 ? min( margined_size.y, layout.size.max.y ) : margined_size.y
adjusted_size : Vec2
adjusted_size.x = max( adjusted_max_size_x, layout.size.min.x)
adjusted_size.y = max( adjusted_max_size_y, layout.size.min.y)
constrained_half_size := constrained_size * 0.5
min_half_size := layout.size.min * 0.5
max_half_size := layout.size.max * 0.5
half_size := linalg.max( constrained_half_size, min_half_size )
half_size = linalg.min( half_size, max_half_size )
projected_bounds := range2(
aligned_unit_bounds.p0 * half_size,
aligned_unit_bounds.p1 * half_size,
)
rel_projected_bounds := range2(
layout.pos + projected_bounds.p0,
layout.pos + projected_bounds.p1,
)
bounds : Range2
// Resolve and apply the size constraint based off of positon of box and the constrained bounds
// Check to see if left or right side is over
if ! (.Fixed_Width in style.flags)
{
bounds.p0.x = rel_projected_bounds.p0.x < constrained_bounds.p0.x ? constrained_bounds.p0.x : rel_projected_bounds.p0.x
bounds.p1.x = rel_projected_bounds.p1.x > constrained_bounds.p1.x ? constrained_bounds.p1.x : rel_projected_bounds.p1.x
if .Fixed_Width in style.flags {
adjusted_size.x = layout.size.min.x
}
else {
size_unit_bounds := range2(
{ 0.0, 0.0 },
{ 1.0, -1.0 },
)
alignment := layout.alignment
aligned_unit_bounds := range2(
size_unit_bounds.p0 + { -alignment.x, alignment.y },
size_unit_bounds.p1 - { alignment.x, -alignment.y },
)
// Apply size.p0.x directly
bounds.p0.x = aligned_unit_bounds.p0.x * layout.size.min.x
bounds.p1.x = aligned_unit_bounds.p1.x * layout.size.min.x
bounds.p0.x += constrained_bounds.p0.x
bounds.p1.x += constrained_bounds.p0.x
bounds.p0.x += layout.pos.x
bounds.p1.x += layout.pos.x
if .Fixed_Height in style.flags {
adjusted_size.y = layout.size.min.y
}
if ! (.Fixed_Height in style.flags)
{
bounds.p0.y = rel_projected_bounds.p0.y > constrained_bounds.p0.y ? constrained_bounds.p0.y : rel_projected_bounds.p0.y
bounds.p1.y = rel_projected_bounds.p1.y < constrained_bounds.p1.y ? constrained_bounds.p1.y : rel_projected_bounds.p1.y
}
else {
size_unit_bounds := range2(
{ 0.0, 0.0 },
{ 1.0, -1.0 },
)
alignment := layout.alignment
aligned_unit_bounds := range2(
size_unit_bounds.p0 + { -alignment.x, alignment.y },
size_unit_bounds.p1 - { alignment.x, -alignment.y },
)
// Apply size.p0.y directly
bounds.p0.y = aligned_unit_bounds.p0.y * layout.size.min.y
bounds.p1.y = aligned_unit_bounds.p1.y * layout.size.min.y
bounds.p0.y += constrained_bounds.p0.y //+ aligned_unit_bounds
bounds.p1.y += constrained_bounds.p0.y //+ aligned_unit_bounds
bounds.p0.y += layout.pos.y
bounds.p1.y += layout.pos.y
}
// Enforce the min/max size
bounds_size := bounds.p1 - bounds.p0
// if bounds_size > layout.size.max {
// Enforce max
// }
text_size : Vec2
// If the computed matches, we already have the size, don't bother.
if current.first_frame || ! size_to_text || computed.text_size.y != size_range2(computed.bounds).y {
@ -222,36 +119,65 @@ ui_compute_layout :: proc()
else {
text_size = computed.text_size
}
if size_to_text {
// size = text_size
// 4. Adjust Alignment of pivot position
alignment := layout.alignment
alignment_offset := Vec2 {
// adjusted_size.x * (alignment.x - 0.5),
// adjusted_size.y * (alignment.y - 0.5),
}
// 5. Determine relative position
computed.bounds = bounds
// TODO(Ed): Let the user determine the coordinate space origin?
// rel_pos := margined_bounds_origin + alignment_offset + layout.pos
rel_pos := margined_bounds_origin + layout.pos
border_offset := Vec2 { layout.border_width, layout.border_width }
padding := & computed.padding
(padding^) = range2(
bounds.p0 + border_offset,
bounds.p1 + border_offset,
if .Fixed_Position_X in style.flags {
rel_pos.x = parent_center.x + layout.pos.x
}
if .Fixed_Position_Y in style.flags {
rel_pos.y = parent_center.y + layout.pos.y
}
vec2_one := Vec2 { 1, 1 }
// Determine the box bounds
bounds := range2(
rel_pos - adjusted_size * alignment,
rel_pos + adjusted_size * (vec2_one - alignment),
)
content := & computed.content
(content^) = range2(
bounds.p0 + { layout.padding.left, -layout.padding.top },
bounds.p1 + { -layout.padding.right, layout.padding.bottom },
// Determine Padding's outer bounds
border_offset := Vec2 { layout.border_width, layout.border_width }
padding_bounds := range2(
bounds.min + border_offset,
bounds.min - border_offset,
)
// Text
// Determine Content Bounds
content_bounds := range2(
bounds.min + { layout.padding.left, layout.padding.bottom },
bounds.max - { layout.padding.right, layout.padding.top },
)
computed.anchors = anchored_bounds
computed.margins = margined_bounds
computed.bounds = bounds
computed.padding = padding_bounds
computed.content = content_bounds
// TODO(Ed): Needs a rework based on changes to rest of layout above being changed
// Text
if len(current.text.str) > 0
{
// profile("Text")
top_left := content.p0
bottom_right := content.p1
bottom_left := content_bounds.min
top_right := content_bounds.max
content_size := Vec2 { top_left.x - bottom_right.x, top_left.y - bottom_right.y }
content_size := Vec2 { top_right.x - bottom_left.x, top_right.y - bottom_left.y }
text_pos : Vec2
text_pos = top_left
text_pos = top_right
text_pos.x += (-content_size.x - text_size.x) * layout.text_alignment.x
text_pos.y += (-content_size.y + text_size.y) * layout.text_alignment.y

View File

@ -89,4 +89,4 @@ test_text_box :: proc()
}
text_box.style.layout.pos = pos
}
}

View File

@ -60,199 +60,3 @@ Curabitur egestas laoreet mauris sed cursus.
Duis nec purus vel nibh venenatis dignissim.
Nam eget aliquam eros, vitae pellentesque neque.
Praesent mollis augue risus, ut commodo arcu auctor vel.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi laoreet bibendum finibus.
Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.
Aenean ut elementum leo, eu luctus lorem.
Sed sit amet dapibus odio, at porttitor magna.
Cras id justo et risus porta eleifend.
Donec fringilla porta faucibus. Maecenas metus dolor, ornare eu justo sed, mattis porta ante.
Maecenas faucibus odio nisl, non posuere felis laoreet et.
Nullam tincidunt varius lacus sit amet laoreet.
Proin sodales vestibulum dolor, non condimentum arcu sodales nec.
Sed a tortor pharetra ante vehicula porta.
Maecenas congue venenatis euismod.
Suspendisse dapibus id lorem efficitur faucibus.
Aliquam consectetur urna in turpis consectetur, eu vehicula diam egestas.
Cras a semper metus, et porttitor tortor.
Aenean ac nisi consectetur, fermentum leo et, elementum odio.
Etiam imperdiet quam tellus, non suscipit lectus mattis ut. Nulla egestas urna vitae ex consectetur aliquam.
Maecenas vel luctus nibh. Morbi eget nisl justo.
Donec condimentum dolor id quam lacinia, vel ullamcorper mauris gravida.
Aliquam erat volutpat. Aliquam vitae neque venenatis, ultrices dui non, ornare velit.
Vivamus mollis ligula a ligula commodo ultrices.
Pellentesque ante felis, ultrices in risus eu, faucibus tincidunt ante.
Suspendisse potenti. Sed eget ligula mauris. Donec lorem est, porttitor auctor varius sed, lobortis nec eros.
Integer urna ligula, auctor ac sapien et, volutpat elementum leo.
Ut commodo arcu a turpis tempor, id semper justo egestas.
Aliquam erat volutpat.
Sed placerat malesuada eros.
Suspendisse egestas auctor magna a aliquam.
Pellentesque interdum pretium hendrerit.
Sed eget libero massa.
Nam egestas viverra odio, et ultrices risus scelerisque vel.
Nunc sodales laoreet elementum.
Mauris et risus nec erat placerat lobortis.
Donec ultrices eleifend mi.
Nullam tempus, felis at sodales finibus, libero mauris luctus sem, vehicula dictum lectus quam et lectus.
Phasellus et ligula nisl.
Sed dui enim, efficitur quis viverra nec, facilisis sed est.
Proin eget lectus diam.
Nullam in purus elementum, pharetra eros sed, volutpat metus.
Vestibulum pellentesque efficitur mauris, ut iaculis purus vehicula imperdiet.
Aliquam sit amet dolor id justo aliquam cursus.
Etiam mollis, tellus ut iaculis molestie, nunc libero feugiat arcu, vitae mattis neque leo a erat.
Pellentesque non ex interdum nulla faucibus tincidunt in vel magna.
Nam nec condimentum lacus, at pellentesque sem.
Pellentesque tristique pulvinar aliquet.
Sed varius dolor in sapien varius, sed blandit ipsum viverra.
Duis consectetur lacus dolor, non pellentesque enim pulvinar a.
Proin id leo vel ligula hendrerit facilisis.
Sed fringilla tellus est, non pretium sem consectetur fermentum.
Nam a tellus augue.
Suspendisse quis odio nibh.
Cras pellentesque turpis a mauris euismod, vel posuere enim eleifend.
Phasellus purus ex, mollis at ante at, convallis interdum tellus.
Proin at porttitor mauris, ut egestas ligula.
Suspendisse ultricies commodo lorem, quis auctor turpis efficitur ut.
Curabitur egestas laoreet mauris sed cursus.
Duis nec purus vel nibh venenatis dignissim.
Nam eget aliquam eros, vitae pellentesque neque.
Praesent mollis augue risus, ut commodo arcu auctor vel.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi laoreet bibendum finibus.
Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.
Aenean ut elementum leo, eu luctus lorem.
Sed sit amet dapibus odio, at porttitor magna.
Cras id justo et risus porta eleifend.
Donec fringilla porta faucibus. Maecenas metus dolor, ornare eu justo sed, mattis porta ante.
Maecenas faucibus odio nisl, non posuere felis laoreet et.
Nullam tincidunt varius lacus sit amet laoreet.
Proin sodales vestibulum dolor, non condimentum arcu sodales nec.
Sed a tortor pharetra ante vehicula porta.
Maecenas congue venenatis euismod.
Suspendisse dapibus id lorem efficitur faucibus.
Aliquam consectetur urna in turpis consectetur, eu vehicula diam egestas.
Cras a semper metus, et porttitor tortor.
Aenean ac nisi consectetur, fermentum leo et, elementum odio.
Etiam imperdiet quam tellus, non suscipit lectus mattis ut. Nulla egestas urna vitae ex consectetur aliquam.
Maecenas vel luctus nibh. Morbi eget nisl justo.
Donec condimentum dolor id quam lacinia, vel ullamcorper mauris gravida.
Aliquam erat volutpat. Aliquam vitae neque venenatis, ultrices dui non, ornare velit.
Vivamus mollis ligula a ligula commodo ultrices.
Pellentesque ante felis, ultrices in risus eu, faucibus tincidunt ante.
Suspendisse potenti. Sed eget ligula mauris. Donec lorem est, porttitor auctor varius sed, lobortis nec eros.
Integer urna ligula, auctor ac sapien et, volutpat elementum leo.
Ut commodo arcu a turpis tempor, id semper justo egestas.
Aliquam erat volutpat.
Sed placerat malesuada eros.
Suspendisse egestas auctor magna a aliquam.
Pellentesque interdum pretium hendrerit.
Sed eget libero massa.
Nam egestas viverra odio, et ultrices risus scelerisque vel.
Nunc sodales laoreet elementum.
Mauris et risus nec erat placerat lobortis.
Donec ultrices eleifend mi.
Nullam tempus, felis at sodales finibus, libero mauris luctus sem, vehicula dictum lectus quam et lectus.
Phasellus et ligula nisl.
Sed dui enim, efficitur quis viverra nec, facilisis sed est.
Proin eget lectus diam.
Nullam in purus elementum, pharetra eros sed, volutpat metus.
Vestibulum pellentesque efficitur mauris, ut iaculis purus vehicula imperdiet.
Aliquam sit amet dolor id justo aliquam cursus.
Etiam mollis, tellus ut iaculis molestie, nunc libero feugiat arcu, vitae mattis neque leo a erat.
Pellentesque non ex interdum nulla faucibus tincidunt in vel magna.
Nam nec condimentum lacus, at pellentesque sem.
Pellentesque tristique pulvinar aliquet.
Sed varius dolor in sapien varius, sed blandit ipsum viverra.
Duis consectetur lacus dolor, non pellentesque enim pulvinar a.
Proin id leo vel ligula hendrerit facilisis.
Sed fringilla tellus est, non pretium sem consectetur fermentum.
Nam a tellus augue.
Suspendisse quis odio nibh.
Cras pellentesque turpis a mauris euismod, vel posuere enim eleifend.
Phasellus purus ex, mollis at ante at, convallis interdum tellus.
Proin at porttitor mauris, ut egestas ligula.
Suspendisse ultricies commodo lorem, quis auctor turpis efficitur ut.
Curabitur egestas laoreet mauris sed cursus.
Duis nec purus vel nibh venenatis dignissim.
Nam eget aliquam eros, vitae pellentesque neque.
Praesent mollis augue risus, ut commodo arcu auctor vel.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi laoreet bibendum finibus.
Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.
Aenean ut elementum leo, eu luctus lorem.
Sed sit amet dapibus odio, at porttitor magna.
Cras id justo et risus porta eleifend.
Donec fringilla porta faucibus. Maecenas metus dolor, ornare eu justo sed, mattis porta ante.
Maecenas faucibus odio nisl, non posuere felis laoreet et.
Nullam tincidunt varius lacus sit amet laoreet.
Proin sodales vestibulum dolor, non condimentum arcu sodales nec.
Sed a tortor pharetra ante vehicula porta.
Maecenas congue venenatis euismod.
Suspendisse dapibus id lorem efficitur faucibus.
Aliquam consectetur urna in turpis consectetur, eu vehicula diam egestas.
Cras a semper metus, et porttitor tortor.
Aenean ac nisi consectetur, fermentum leo et, elementum odio.
Etiam imperdiet quam tellus, non suscipit lectus mattis ut. Nulla egestas urna vitae ex consectetur aliquam.
Maecenas vel luctus nibh. Morbi eget nisl justo.
Donec condimentum dolor id quam lacinia, vel ullamcorper mauris gravida.
Aliquam erat volutpat. Aliquam vitae neque venenatis, ultrices dui non, ornare velit.
Vivamus mollis ligula a ligula commodo ultrices.
Pellentesque ante felis, ultrices in risus eu, faucibus tincidunt ante.
Suspendisse potenti. Sed eget ligula mauris. Donec lorem est, porttitor auctor varius sed, lobortis nec eros.
Integer urna ligula, auctor ac sapien et, volutpat elementum leo.
Ut commodo arcu a turpis tempor, id semper justo egestas.
Aliquam erat volutpat.
Sed placerat malesuada eros.
Suspendisse egestas auctor magna a aliquam.
Pellentesque interdum pretium hendrerit.
Sed eget libero massa.
Nam egestas viverra odio, et ultrices risus scelerisque vel.
Nunc sodales laoreet elementum.
Mauris et risus nec erat placerat lobortis.
Donec ultrices eleifend mi.
Nullam tempus, felis at sodales finibus, libero mauris luctus sem, vehicula dictum lectus quam et lectus.
Phasellus et ligula nisl.
Sed dui enim, efficitur quis viverra nec, facilisis sed est.
Proin eget lectus diam.
Nullam in purus elementum, pharetra eros sed, volutpat metus.
Vestibulum pellentesque efficitur mauris, ut iaculis purus vehicula imperdiet.
Aliquam sit amet dolor id justo aliquam cursus.
Etiam mollis, tellus ut iaculis molestie, nunc libero feugiat arcu, vitae mattis neque leo a erat.
Pellentesque non ex interdum nulla faucibus tincidunt in vel magna.
Nam nec condimentum lacus, at pellentesque sem.
Pellentesque tristique pulvinar aliquet.
Sed varius dolor in sapien varius, sed blandit ipsum viverra.
Duis consectetur lacus dolor, non pellentesque enim pulvinar a.
Proin id leo vel ligula hendrerit facilisis.
Sed fringilla tellus est, non pretium sem consectetur fermentum.
Nam a tellus augue.
Suspendisse quis odio nibh.
Cras pellentesque turpis a mauris euismod, vel posuere enim eleifend.
Phasellus purus ex, mollis at ante at, convallis interdum tellus.
Proin at porttitor mauris, ut egestas ligula.
Suspendisse ultricies commodo lorem, quis auctor turpis efficitur ut.
Curabitur egestas laoreet mauris sed cursus.
Duis nec purus vel nibh venenatis dignissim.
Nam eget aliquam eros, vitae pellentesque neque.
Praesent mollis augue risus, ut commodo arcu auctor vel.

196
examples/temp.txt Normal file
View File

@ -0,0 +1,196 @@
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi laoreet bibendum finibus.
Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.
Aenean ut elementum leo, eu luctus lorem.
Sed sit amet dapibus odio, at porttitor magna.
Cras id justo et risus porta eleifend.
Donec fringilla porta faucibus. Maecenas metus dolor, ornare eu justo sed, mattis porta ante.
Maecenas faucibus odio nisl, non posuere felis laoreet et.
Nullam tincidunt varius lacus sit amet laoreet.
Proin sodales vestibulum dolor, non condimentum arcu sodales nec.
Sed a tortor pharetra ante vehicula porta.
Maecenas congue venenatis euismod.
Suspendisse dapibus id lorem efficitur faucibus.
Aliquam consectetur urna in turpis consectetur, eu vehicula diam egestas.
Cras a semper metus, et porttitor tortor.
Aenean ac nisi consectetur, fermentum leo et, elementum odio.
Etiam imperdiet quam tellus, non suscipit lectus mattis ut. Nulla egestas urna vitae ex consectetur aliquam.
Maecenas vel luctus nibh. Morbi eget nisl justo.
Donec condimentum dolor id quam lacinia, vel ullamcorper mauris gravida.
Aliquam erat volutpat. Aliquam vitae neque venenatis, ultrices dui non, ornare velit.
Vivamus mollis ligula a ligula commodo ultrices.
Pellentesque ante felis, ultrices in risus eu, faucibus tincidunt ante.
Suspendisse potenti. Sed eget ligula mauris. Donec lorem est, porttitor auctor varius sed, lobortis nec eros.
Integer urna ligula, auctor ac sapien et, volutpat elementum leo.
Ut commodo arcu a turpis tempor, id semper justo egestas.
Aliquam erat volutpat.
Sed placerat malesuada eros.
Suspendisse egestas auctor magna a aliquam.
Pellentesque interdum pretium hendrerit.
Sed eget libero massa.
Nam egestas viverra odio, et ultrices risus scelerisque vel.
Nunc sodales laoreet elementum.
Mauris et risus nec erat placerat lobortis.
Donec ultrices eleifend mi.
Nullam tempus, felis at sodales finibus, libero mauris luctus sem, vehicula dictum lectus quam et lectus.
Phasellus et ligula nisl.
Sed dui enim, efficitur quis viverra nec, facilisis sed est.
Proin eget lectus diam.
Nullam in purus elementum, pharetra eros sed, volutpat metus.
Vestibulum pellentesque efficitur mauris, ut iaculis purus vehicula imperdiet.
Aliquam sit amet dolor id justo aliquam cursus.
Etiam mollis, tellus ut iaculis molestie, nunc libero feugiat arcu, vitae mattis neque leo a erat.
Pellentesque non ex interdum nulla faucibus tincidunt in vel magna.
Nam nec condimentum lacus, at pellentesque sem.
Pellentesque tristique pulvinar aliquet.
Sed varius dolor in sapien varius, sed blandit ipsum viverra.
Duis consectetur lacus dolor, non pellentesque enim pulvinar a.
Proin id leo vel ligula hendrerit facilisis.
Sed fringilla tellus est, non pretium sem consectetur fermentum.
Nam a tellus augue.
Suspendisse quis odio nibh.
Cras pellentesque turpis a mauris euismod, vel posuere enim eleifend.
Phasellus purus ex, mollis at ante at, convallis interdum tellus.
Proin at porttitor mauris, ut egestas ligula.
Suspendisse ultricies commodo lorem, quis auctor turpis efficitur ut.
Curabitur egestas laoreet mauris sed cursus.
Duis nec purus vel nibh venenatis dignissim.
Nam eget aliquam eros, vitae pellentesque neque.
Praesent mollis augue risus, ut commodo arcu auctor vel.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi laoreet bibendum finibus.
Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.
Aenean ut elementum leo, eu luctus lorem.
Sed sit amet dapibus odio, at porttitor magna.
Cras id justo et risus porta eleifend.
Donec fringilla porta faucibus. Maecenas metus dolor, ornare eu justo sed, mattis porta ante.
Maecenas faucibus odio nisl, non posuere felis laoreet et.
Nullam tincidunt varius lacus sit amet laoreet.
Proin sodales vestibulum dolor, non condimentum arcu sodales nec.
Sed a tortor pharetra ante vehicula porta.
Maecenas congue venenatis euismod.
Suspendisse dapibus id lorem efficitur faucibus.
Aliquam consectetur urna in turpis consectetur, eu vehicula diam egestas.
Cras a semper metus, et porttitor tortor.
Aenean ac nisi consectetur, fermentum leo et, elementum odio.
Etiam imperdiet quam tellus, non suscipit lectus mattis ut. Nulla egestas urna vitae ex consectetur aliquam.
Maecenas vel luctus nibh. Morbi eget nisl justo.
Donec condimentum dolor id quam lacinia, vel ullamcorper mauris gravida.
Aliquam erat volutpat. Aliquam vitae neque venenatis, ultrices dui non, ornare velit.
Vivamus mollis ligula a ligula commodo ultrices.
Pellentesque ante felis, ultrices in risus eu, faucibus tincidunt ante.
Suspendisse potenti. Sed eget ligula mauris. Donec lorem est, porttitor auctor varius sed, lobortis nec eros.
Integer urna ligula, auctor ac sapien et, volutpat elementum leo.
Ut commodo arcu a turpis tempor, id semper justo egestas.
Aliquam erat volutpat.
Sed placerat malesuada eros.
Suspendisse egestas auctor magna a aliquam.
Pellentesque interdum pretium hendrerit.
Sed eget libero massa.
Nam egestas viverra odio, et ultrices risus scelerisque vel.
Nunc sodales laoreet elementum.
Mauris et risus nec erat placerat lobortis.
Donec ultrices eleifend mi.
Nullam tempus, felis at sodales finibus, libero mauris luctus sem, vehicula dictum lectus quam et lectus.
Phasellus et ligula nisl.
Sed dui enim, efficitur quis viverra nec, facilisis sed est.
Proin eget lectus diam.
Nullam in purus elementum, pharetra eros sed, volutpat metus.
Vestibulum pellentesque efficitur mauris, ut iaculis purus vehicula imperdiet.
Aliquam sit amet dolor id justo aliquam cursus.
Etiam mollis, tellus ut iaculis molestie, nunc libero feugiat arcu, vitae mattis neque leo a erat.
Pellentesque non ex interdum nulla faucibus tincidunt in vel magna.
Nam nec condimentum lacus, at pellentesque sem.
Pellentesque tristique pulvinar aliquet.
Sed varius dolor in sapien varius, sed blandit ipsum viverra.
Duis consectetur lacus dolor, non pellentesque enim pulvinar a.
Proin id leo vel ligula hendrerit facilisis.
Sed fringilla tellus est, non pretium sem consectetur fermentum.
Nam a tellus augue.
Suspendisse quis odio nibh.
Cras pellentesque turpis a mauris euismod, vel posuere enim eleifend.
Phasellus purus ex, mollis at ante at, convallis interdum tellus.
Proin at porttitor mauris, ut egestas ligula.
Suspendisse ultricies commodo lorem, quis auctor turpis efficitur ut.
Curabitur egestas laoreet mauris sed cursus.
Duis nec purus vel nibh venenatis dignissim.
Nam eget aliquam eros, vitae pellentesque neque.
Praesent mollis augue risus, ut commodo arcu auctor vel.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi laoreet bibendum finibus.
Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.
Aenean ut elementum leo, eu luctus lorem.
Sed sit amet dapibus odio, at porttitor magna.
Cras id justo et risus porta eleifend.
Donec fringilla porta faucibus. Maecenas metus dolor, ornare eu justo sed, mattis porta ante.
Maecenas faucibus odio nisl, non posuere felis laoreet et.
Nullam tincidunt varius lacus sit amet laoreet.
Proin sodales vestibulum dolor, non condimentum arcu sodales nec.
Sed a tortor pharetra ante vehicula porta.
Maecenas congue venenatis euismod.
Suspendisse dapibus id lorem efficitur faucibus.
Aliquam consectetur urna in turpis consectetur, eu vehicula diam egestas.
Cras a semper metus, et porttitor tortor.
Aenean ac nisi consectetur, fermentum leo et, elementum odio.
Etiam imperdiet quam tellus, non suscipit lectus mattis ut. Nulla egestas urna vitae ex consectetur aliquam.
Maecenas vel luctus nibh. Morbi eget nisl justo.
Donec condimentum dolor id quam lacinia, vel ullamcorper mauris gravida.
Aliquam erat volutpat. Aliquam vitae neque venenatis, ultrices dui non, ornare velit.
Vivamus mollis ligula a ligula commodo ultrices.
Pellentesque ante felis, ultrices in risus eu, faucibus tincidunt ante.
Suspendisse potenti. Sed eget ligula mauris. Donec lorem est, porttitor auctor varius sed, lobortis nec eros.
Integer urna ligula, auctor ac sapien et, volutpat elementum leo.
Ut commodo arcu a turpis tempor, id semper justo egestas.
Aliquam erat volutpat.
Sed placerat malesuada eros.
Suspendisse egestas auctor magna a aliquam.
Pellentesque interdum pretium hendrerit.
Sed eget libero massa.
Nam egestas viverra odio, et ultrices risus scelerisque vel.
Nunc sodales laoreet elementum.
Mauris et risus nec erat placerat lobortis.
Donec ultrices eleifend mi.
Nullam tempus, felis at sodales finibus, libero mauris luctus sem, vehicula dictum lectus quam et lectus.
Phasellus et ligula nisl.
Sed dui enim, efficitur quis viverra nec, facilisis sed est.
Proin eget lectus diam.
Nullam in purus elementum, pharetra eros sed, volutpat metus.
Vestibulum pellentesque efficitur mauris, ut iaculis purus vehicula imperdiet.
Aliquam sit amet dolor id justo aliquam cursus.
Etiam mollis, tellus ut iaculis molestie, nunc libero feugiat arcu, vitae mattis neque leo a erat.
Pellentesque non ex interdum nulla faucibus tincidunt in vel magna.
Nam nec condimentum lacus, at pellentesque sem.
Pellentesque tristique pulvinar aliquet.
Sed varius dolor in sapien varius, sed blandit ipsum viverra.
Duis consectetur lacus dolor, non pellentesque enim pulvinar a.
Proin id leo vel ligula hendrerit facilisis.
Sed fringilla tellus est, non pretium sem consectetur fermentum.
Nam a tellus augue.
Suspendisse quis odio nibh.
Cras pellentesque turpis a mauris euismod, vel posuere enim eleifend.
Phasellus purus ex, mollis at ante at, convallis interdum tellus.
Proin at porttitor mauris, ut egestas ligula.
Suspendisse ultricies commodo lorem, quis auctor turpis efficitur ut.
Curabitur egestas laoreet mauris sed cursus.
Duis nec purus vel nibh venenatis dignissim.
Nam eget aliquam eros, vitae pellentesque neque.
Praesent mollis augue risus, ut commodo arcu auctor vel.

2
thirdparty/Odin vendored

@ -1 +1 @@
Subproject commit f1179108350444082586504328ae55b989062c45
Subproject commit 2949802070036a5971fa6d286a3f1f280d9eaa4b