mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 07:08:48 +00:00
Add package core:encoding/hxa
This commit is contained in:
@@ -0,0 +1,193 @@
|
||||
package encoding_hxa
|
||||
|
||||
import "core:os"
|
||||
import "core:mem"
|
||||
|
||||
Write_Error :: enum {
|
||||
None,
|
||||
Buffer_Too_Small,
|
||||
Failed_File_Write,
|
||||
}
|
||||
|
||||
write_to_file :: proc(filepath: string, file: File) -> (err: Write_Error) {
|
||||
required := required_write_size(file);
|
||||
buf, alloc_err := make([]byte, required);
|
||||
if alloc_err == .Out_Of_Memory {
|
||||
return .Failed_File_Write;
|
||||
}
|
||||
defer delete(buf);
|
||||
|
||||
write_internal(&Writer{data = buf}, file);
|
||||
if !os.write_entire_file(filepath, buf) {
|
||||
err =.Failed_File_Write;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
write :: proc(buf: []byte, file: File) -> (n: int, err: Write_Error) {
|
||||
required := required_write_size(file);
|
||||
if len(buf) < required {
|
||||
err = .Buffer_Too_Small;
|
||||
return;
|
||||
}
|
||||
n = required;
|
||||
write_internal(&Writer{data = buf}, file);
|
||||
return;
|
||||
}
|
||||
|
||||
required_write_size :: proc(file: File) -> (n: int) {
|
||||
writer := &Writer{dummy_pass = true};
|
||||
write_internal(writer, file);
|
||||
n = writer.offset;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@(private)
|
||||
Writer :: struct {
|
||||
data: []byte,
|
||||
offset: int,
|
||||
dummy_pass: bool,
|
||||
};
|
||||
|
||||
@(private)
|
||||
write_internal :: proc(w: ^Writer, file: File) {
|
||||
write_value :: proc(w: ^Writer, value: $T) {
|
||||
if !w.dummy_pass {
|
||||
remaining := len(w.data) - w.offset;
|
||||
assert(size_of(T) <= remaining);
|
||||
ptr := raw_data(w.data[w.offset:]);
|
||||
(^T)(ptr)^ = value;
|
||||
}
|
||||
w.offset += size_of(T);
|
||||
}
|
||||
write_array :: proc(w: ^Writer, array: []$T) {
|
||||
if !w.dummy_pass {
|
||||
remaining := len(w.data) - w.offset;
|
||||
assert(size_of(T)*len(array) <= remaining);
|
||||
ptr := raw_data(w.data[w.offset:]);
|
||||
dst := mem.slice_ptr((^T)(ptr), len(array));
|
||||
copy(dst, array);
|
||||
}
|
||||
w.offset += size_of(T)*len(array);
|
||||
}
|
||||
write_string :: proc(w: ^Writer, str: string) {
|
||||
if !w.dummy_pass {
|
||||
remaining := len(w.data) - w.offset;
|
||||
assert(size_of(byte)*len(str) <= remaining);
|
||||
ptr := raw_data(w.data[w.offset:]);
|
||||
dst := mem.slice_ptr((^byte)(ptr), len(str));
|
||||
copy(dst, str);
|
||||
}
|
||||
w.offset += size_of(byte)*len(str);
|
||||
}
|
||||
|
||||
write_metadata :: proc(w: ^Writer, meta_data: []Meta) {
|
||||
for m in meta_data {
|
||||
name_len := max(len(m.name), 255);
|
||||
write_value(w, u8(name_len));
|
||||
write_string(w, m.name[:name_len]);
|
||||
|
||||
meta_data_type: Meta_Value_Type;
|
||||
length: u32le = 0;
|
||||
switch v in m.value {
|
||||
case []i64le:
|
||||
meta_data_type = .Int64;
|
||||
length = u32le(len(v));
|
||||
case []f64le:
|
||||
meta_data_type = .Double;
|
||||
length = u32le(len(v));
|
||||
case []Node_Index:
|
||||
meta_data_type = .Node;
|
||||
length = u32le(len(v));
|
||||
case string:
|
||||
meta_data_type = .Text;
|
||||
length = u32le(len(v));
|
||||
case []byte:
|
||||
meta_data_type = .Binary;
|
||||
length = u32le(len(v));
|
||||
case []Meta:
|
||||
meta_data_type = .Meta;
|
||||
length = u32le(len(v));
|
||||
}
|
||||
write_value(w, meta_data_type);
|
||||
write_value(w, length);
|
||||
|
||||
switch v in m.value {
|
||||
case []i64le: write_array(w, v);
|
||||
case []f64le: write_array(w, v);
|
||||
case []Node_Index: write_array(w, v);
|
||||
case string: write_string(w, v);
|
||||
case []byte: write_array(w, v);
|
||||
case []Meta: write_metadata(w, v);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
write_layer_stack :: proc(w: ^Writer, layers: Layer_Stack) {
|
||||
write_value(w, u32(len(layers)));
|
||||
for layer in layers {
|
||||
name_len := max(len(layer.name), 255);
|
||||
write_value(w, u8(name_len));
|
||||
write_string(w, layer .name[:name_len]);
|
||||
|
||||
write_value(w, layer.components);
|
||||
|
||||
layer_data_type: Layer_Data_Type;
|
||||
switch v in layer.data {
|
||||
case []u8: layer_data_type = .Uint8;
|
||||
case []i32le: layer_data_type = .Int32;
|
||||
case []f32le: layer_data_type = .Float;
|
||||
case []f64le: layer_data_type = .Double;
|
||||
}
|
||||
write_value(w, layer_data_type);
|
||||
|
||||
switch v in layer.data {
|
||||
case []u8: write_array(w, v);
|
||||
case []i32le: write_array(w, v);
|
||||
case []f32le: write_array(w, v);
|
||||
case []f64le: write_array(w, v);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
write_value(w, &Header{
|
||||
magic_number = MAGIC_NUMBER,
|
||||
version = LATEST_VERSION,
|
||||
internal_node_count = u32le(len(file.nodes)),
|
||||
});
|
||||
|
||||
for node in file.nodes {
|
||||
node_type: Node_Type;
|
||||
switch content in node.content {
|
||||
case Node_Geometry: node_type = .Geometry;
|
||||
case Node_Image: node_type = .Image;
|
||||
}
|
||||
write_value(w, node_type);
|
||||
|
||||
write_value(w, u32(len(node.meta_data)));
|
||||
write_metadata(w, node.meta_data);
|
||||
|
||||
switch content in node.content {
|
||||
case Node_Geometry:
|
||||
write_value(w, content.vertex_count);
|
||||
write_layer_stack(w, content.vertex_stack);
|
||||
write_value(w, content.edge_corner_count);
|
||||
write_layer_stack(w, content.corner_stack);
|
||||
write_layer_stack(w, content.edge_stack);
|
||||
write_value(w, content.face_count);
|
||||
write_layer_stack(w, content.face_stack);
|
||||
case Node_Image:
|
||||
write_value(w, content.type);
|
||||
dimensions := int(content.type);
|
||||
if content.type == .Image_Cube {
|
||||
dimensions = 2;
|
||||
}
|
||||
for d in 0..<dimensions {
|
||||
write_value(w, content.resolution[d]);
|
||||
}
|
||||
write_layer_stack(w, content.image_stack);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user