add asset packer
This commit is contained in:
parent
59b778012f
commit
d290e3131c
248
assets.d
248
assets.d
@ -1,5 +1,6 @@
|
|||||||
module dlib.assets;
|
module dlib.assets;
|
||||||
|
|
||||||
|
import includes;
|
||||||
import dlib.aliases;
|
import dlib.aliases;
|
||||||
import dlib.util;
|
import dlib.util;
|
||||||
import dlib.alloc;
|
import dlib.alloc;
|
||||||
@ -16,8 +17,8 @@ AssetInfo[] Asset_Info;
|
|||||||
|
|
||||||
u8[][] Asset_Data;
|
u8[][] Asset_Data;
|
||||||
|
|
||||||
const u32 FILE_VERSION = 2;
|
const u32 FILE_VERSION = 3;
|
||||||
const u32 MODEL_VERSION = 1;
|
const u32 MODEL_VERSION = 2;
|
||||||
|
|
||||||
enum AssetType : u32
|
enum AssetType : u32
|
||||||
{
|
{
|
||||||
@ -64,25 +65,77 @@ struct ModelData
|
|||||||
{
|
{
|
||||||
Vertex[] vertices;
|
Vertex[] vertices;
|
||||||
u32[] indices;
|
u32[] indices;
|
||||||
Material[] materials;
|
MaterialData[] materials;
|
||||||
TextureInfo[] textures;
|
TextureInfo[] textures;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Material
|
enum IllumModel : u32
|
||||||
{
|
{
|
||||||
Vec4 ambient;
|
Color = 0,
|
||||||
Vec4 albedo;
|
ColorAmbient,
|
||||||
Vec4 specular;
|
Highlight,
|
||||||
u32 albedo_texture;
|
ReflectionRayTrace,
|
||||||
u32 ambient_texture;
|
GlassRayTrace,
|
||||||
u32 specular_texture;
|
FresnelRayTrace,
|
||||||
u32 alpha_texture;
|
RefractionRayTrace,
|
||||||
b32 albedo_has_texture;
|
RefractionFresnelRayTrace,
|
||||||
b32 ambient_has_texture;
|
Reflection,
|
||||||
b32 specular_has_texture;
|
Glass,
|
||||||
b32 alpha_has_texture;
|
ShadowsInvis,
|
||||||
f32 shininess = 0.0;
|
}
|
||||||
f32 alpha = 0.0;
|
|
||||||
|
enum MatColor : u32
|
||||||
|
{
|
||||||
|
Ambient,
|
||||||
|
Albedo,
|
||||||
|
Specular,
|
||||||
|
Transmission,
|
||||||
|
Emissive,
|
||||||
|
|
||||||
|
Max,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum MatFloat : u32
|
||||||
|
{
|
||||||
|
SpecularExp,
|
||||||
|
Alpha,
|
||||||
|
OpticalDensity,
|
||||||
|
Roughness,
|
||||||
|
Metallic,
|
||||||
|
ClearcoatThickness,
|
||||||
|
ClearcoatRoughness,
|
||||||
|
Anisotropy,
|
||||||
|
Bump,
|
||||||
|
FaceThickness,
|
||||||
|
Sheen,
|
||||||
|
|
||||||
|
Max,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum MatMap : u32
|
||||||
|
{
|
||||||
|
Ambient,
|
||||||
|
Albedo,
|
||||||
|
Specular,
|
||||||
|
SpecularHighlight,
|
||||||
|
Alpha,
|
||||||
|
Bump,
|
||||||
|
Displacement,
|
||||||
|
Roughness,
|
||||||
|
Metallic,
|
||||||
|
Emissive,
|
||||||
|
Anisotropy,
|
||||||
|
Normal,
|
||||||
|
|
||||||
|
Max,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MaterialData
|
||||||
|
{
|
||||||
|
Vec4[MatColor.max] colors;
|
||||||
|
string[MatMap.max] maps;
|
||||||
|
f32[MatFloat.max] props = 0.0;
|
||||||
|
IllumModel illum;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TextureInfo
|
struct TextureInfo
|
||||||
@ -200,38 +253,91 @@ GetMapProp(u8[] str)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
debug
|
bool
|
||||||
|
M3DColor(u32 type)
|
||||||
{
|
{
|
||||||
|
return type == m3dp_Kd ||
|
||||||
bool g_DIR_SET = false;
|
type == m3dp_Ka ||
|
||||||
|
type == m3dp_Ks ||
|
||||||
void
|
type == m3dp_Ke ||
|
||||||
SetDir()
|
type == m3dp_Tf;
|
||||||
{
|
|
||||||
if(exists("assets"))
|
|
||||||
{
|
|
||||||
chdir("./assets");
|
|
||||||
}
|
|
||||||
else if(exists("Gears") || exists("Gears.exe"))
|
|
||||||
{
|
|
||||||
chdir("../assets");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
assert(false, "Unable to set directory");
|
|
||||||
}
|
|
||||||
|
|
||||||
g_DIR_SET = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u8[]
|
|
||||||
LoadAssetData(Arena* arena, string name)
|
MatColor
|
||||||
|
M3DMatColor(u32 type)
|
||||||
{
|
{
|
||||||
if(!g_DIR_SET)
|
switch(type) with(MatColor)
|
||||||
{
|
{
|
||||||
SetDir();
|
case m3dp_Kd: return Albedo;
|
||||||
|
case m3dp_Ka: return Ambient;
|
||||||
|
case m3dp_Ks: return Specular;
|
||||||
|
case m3dp_Ke: return Emissive;
|
||||||
|
case m3dp_Tf: return Transmission;
|
||||||
|
default: assert(false, "Unknown M3D MatColor");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
M3DFloat(u32 type)
|
||||||
|
{
|
||||||
|
return type == m3dp_Ns ||
|
||||||
|
type == m3dp_Km ||
|
||||||
|
type == m3dp_d ||
|
||||||
|
type == m3dp_Pr ||
|
||||||
|
type == m3dp_Pm ||
|
||||||
|
type == m3dp_Ps ||
|
||||||
|
type == m3dp_Ni ||
|
||||||
|
type == m3dp_Nt;
|
||||||
|
}
|
||||||
|
|
||||||
|
MatFloat
|
||||||
|
M3DMatFloat(u32 type)
|
||||||
|
{
|
||||||
|
switch(type) with(MatFloat)
|
||||||
|
{
|
||||||
|
case m3dp_Ns: return SpecularExp;
|
||||||
|
case m3dp_Km: return Bump;
|
||||||
|
case m3dp_d: return Alpha;
|
||||||
|
case m3dp_Pr: return Roughness;
|
||||||
|
case m3dp_Pm: return Metallic;
|
||||||
|
case m3dp_Ps: return Sheen;
|
||||||
|
case m3dp_Ni: return OpticalDensity;
|
||||||
|
case m3dp_Nt: return FaceThickness;
|
||||||
|
default: assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
M3DMap(u32 type)
|
||||||
|
{
|
||||||
|
return type == m3dp_map_Kd ||
|
||||||
|
type == m3dp_map_Ka ||
|
||||||
|
type == m3dp_map_Ks ||
|
||||||
|
type == m3dp_map_Ns ||
|
||||||
|
type == m3dp_map_Ke ||
|
||||||
|
type == m3dp_map_Tf ||
|
||||||
|
type == m3dp_map_Km ||
|
||||||
|
type == m3dp_map_D ||
|
||||||
|
type == m3dp_map_N ||
|
||||||
|
type == m3dp_map_Pr ||
|
||||||
|
type == m3dp_map_Pm ||
|
||||||
|
type == m3dp_map_Ps ||
|
||||||
|
type == m3dp_map_Ni ||
|
||||||
|
type == m3dp_map_Nt;
|
||||||
|
}
|
||||||
|
|
||||||
|
debug
|
||||||
|
{
|
||||||
|
void
|
||||||
|
SetAssetsDir(string dir)
|
||||||
|
{
|
||||||
|
assert(ChDir(dir));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u8[]
|
||||||
|
LoadAssetData(Arena* arena, string name)
|
||||||
|
{
|
||||||
File f;
|
File f;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -244,19 +350,17 @@ LoadAssetData(Arena* arena, string name)
|
|||||||
|
|
||||||
u8[] mem = Alloc!(u8)(arena, f.size());
|
u8[] mem = Alloc!(u8)(arena, f.size());
|
||||||
return f.rawRead(mem);
|
return f.rawRead(mem);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
void
|
||||||
void
|
OpenAssetPack(string file_path)
|
||||||
OpenAssetPack()
|
{
|
||||||
{
|
|
||||||
if(!Asset_Pack_Opened)
|
if(!Asset_Pack_Opened)
|
||||||
{
|
{
|
||||||
bool success = true;
|
bool success = true;
|
||||||
string file_path = exists("build/assets.sgp") ? "build/assets.sgp" : "assets.sgp";
|
|
||||||
|
|
||||||
// TODO: replace this with something that doesn't throw an exception and figure out if this is the best way to handle thing (probably isnt)
|
// TODO: replace this with something that doesn't throw an exception and figure out if this is the best way to handle thing (probably isnt)
|
||||||
try
|
try
|
||||||
@ -284,20 +388,17 @@ OpenAssetPack()
|
|||||||
|
|
||||||
Asset_File.rawRead(Asset_Info);
|
Asset_File.rawRead(Asset_Info);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pragma(inline) void
|
|
||||||
CheckAssetPack()
|
|
||||||
{
|
|
||||||
if(!Asset_Pack_Opened)
|
|
||||||
{
|
|
||||||
OpenAssetPack();
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
AssetInfo
|
pragma(inline) void
|
||||||
GetAssetInfo(string name)
|
CheckAssetPack()
|
||||||
{
|
{
|
||||||
|
assert(Asset_Pack_Opened);
|
||||||
|
}
|
||||||
|
|
||||||
|
AssetInfo
|
||||||
|
GetAssetInfo(string name)
|
||||||
|
{
|
||||||
CheckAssetPack();
|
CheckAssetPack();
|
||||||
|
|
||||||
u64 hash = Hash(name);
|
u64 hash = Hash(name);
|
||||||
@ -315,11 +416,11 @@ GetAssetInfo(string name)
|
|||||||
assert(asset_info.hash != 0, "GetAssetInfo failure: unable to find matching asset");
|
assert(asset_info.hash != 0, "GetAssetInfo failure: unable to find matching asset");
|
||||||
|
|
||||||
return asset_info;
|
return asset_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8[]
|
u8[]
|
||||||
LoadAssetData(Arena* arena, string name)
|
LoadAssetData(Arena* arena, string name)
|
||||||
{
|
{
|
||||||
CheckAssetPack();
|
CheckAssetPack();
|
||||||
|
|
||||||
u64 hash = Hash(name);
|
u64 hash = Hash(name);
|
||||||
@ -339,11 +440,11 @@ LoadAssetData(Arena* arena, string name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8[]
|
u8[]
|
||||||
LoadAssetData(string name)
|
LoadAssetData(string name)
|
||||||
{
|
{
|
||||||
CheckAssetPack();
|
CheckAssetPack();
|
||||||
|
|
||||||
u64 hash = Hash(name);
|
u64 hash = Hash(name);
|
||||||
@ -367,11 +468,11 @@ LoadAssetData(string name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
UnloadAssetData(string name)
|
UnloadAssetData(string name)
|
||||||
{
|
{
|
||||||
u64 hash = Hash(name);
|
u64 hash = Hash(name);
|
||||||
|
|
||||||
foreach(i, info; Asset_Info)
|
foreach(i, info; Asset_Info)
|
||||||
@ -385,9 +486,10 @@ UnloadAssetData(string name)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
|
|||||||
250
packer.d
Normal file
250
packer.d
Normal file
@ -0,0 +1,250 @@
|
|||||||
|
import dlib;
|
||||||
|
import std.stdio;
|
||||||
|
import std.string;
|
||||||
|
import std.file;
|
||||||
|
import std.path;
|
||||||
|
import std.traits;
|
||||||
|
import std.algorithm.comparison;
|
||||||
|
import core.memory;
|
||||||
|
import std.json;
|
||||||
|
|
||||||
|
AssetType[string] Lookup = [
|
||||||
|
".m3d": AT.ModelM3D,
|
||||||
|
".obj": AT.ModelObj,
|
||||||
|
".png": AT.Texture,
|
||||||
|
".jpg": AT.Texture,
|
||||||
|
".spv": AT.Shader,
|
||||||
|
];
|
||||||
|
|
||||||
|
struct Texture
|
||||||
|
{
|
||||||
|
string name;
|
||||||
|
u8[] data;
|
||||||
|
u32 w;
|
||||||
|
u32 h;
|
||||||
|
u32 ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Model
|
||||||
|
{
|
||||||
|
MaterialData[] mats;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 g_asset_count = 0;
|
||||||
|
string[] g_file_names = [];
|
||||||
|
Texture[] g_model_textures = [];
|
||||||
|
|
||||||
|
/**************************************************
|
||||||
|
****** UPDATE FILE_VERSION AFTER CHANGES !! ******
|
||||||
|
**************************************************/
|
||||||
|
|
||||||
|
void main(string[] argv)
|
||||||
|
{
|
||||||
|
Log("running");
|
||||||
|
if(isDir("build"))
|
||||||
|
{
|
||||||
|
chdir("build");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool pack = false;
|
||||||
|
bool font = false;
|
||||||
|
string font_file;
|
||||||
|
|
||||||
|
for(u64 i = 0; i < argv.length; i += 1)
|
||||||
|
{
|
||||||
|
if(argv[i] == "-pack")
|
||||||
|
{
|
||||||
|
pack = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pack)
|
||||||
|
{
|
||||||
|
PackFile();
|
||||||
|
TestFile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PackFile()
|
||||||
|
{
|
||||||
|
File ap = File("./assets.sgp", "wb");
|
||||||
|
scope(exit)
|
||||||
|
{
|
||||||
|
ap.flush();
|
||||||
|
ap.close();
|
||||||
|
chdir("../build");
|
||||||
|
}
|
||||||
|
|
||||||
|
chdir("../assets");
|
||||||
|
|
||||||
|
foreach(string file; dirEntries(".", SpanMode.depth))
|
||||||
|
{
|
||||||
|
if (isDir(file)) continue;
|
||||||
|
|
||||||
|
g_file_names ~= file;
|
||||||
|
g_asset_count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileHeader h = InitHeader(g_asset_count);
|
||||||
|
ap.rawWrite([h]);
|
||||||
|
|
||||||
|
u64 offset = FileHeader.sizeof + (AssetInfo.sizeof * g_asset_count);
|
||||||
|
AssetInfo[] asset_info;
|
||||||
|
foreach(file; g_file_names)
|
||||||
|
{
|
||||||
|
AssetType type = AT.None;
|
||||||
|
foreach(extension, t; Lookup)
|
||||||
|
{
|
||||||
|
if (file.endsWith(extension))
|
||||||
|
{
|
||||||
|
type = t;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(type != AT.None, "Asset Type is none, offending file " ~ file);
|
||||||
|
|
||||||
|
auto f = File(file, "rb");
|
||||||
|
|
||||||
|
u64 length = cast(u64)f.size();
|
||||||
|
|
||||||
|
string base_name = chompPrefix(file, "./");
|
||||||
|
AssetInfo info = {
|
||||||
|
hash: Hash(base_name),
|
||||||
|
offset: offset,
|
||||||
|
length: length,
|
||||||
|
type: type,
|
||||||
|
};
|
||||||
|
|
||||||
|
auto data = f.rawRead(new u8[length]);
|
||||||
|
|
||||||
|
assert(length == data.length, "rawRead failure: data length returned doesn't match");
|
||||||
|
|
||||||
|
ap.seek(offset);
|
||||||
|
ap.rawWrite(data);
|
||||||
|
|
||||||
|
offset += length;
|
||||||
|
|
||||||
|
asset_info ~= info;
|
||||||
|
|
||||||
|
f.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
ap.seek(FileHeader.sizeof);
|
||||||
|
ap.rawWrite(asset_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
TexMeta
|
||||||
|
GetTexMeta(u8[] data)
|
||||||
|
{
|
||||||
|
int ch = 4;
|
||||||
|
int width, height, has_ch;
|
||||||
|
auto img = stbi_load_from_memory(data.ptr, cast(int)data.length, &width, &height, &has_ch, ch);
|
||||||
|
|
||||||
|
assert(img != null, "stbi_load_from_image failure: image is NULL");
|
||||||
|
assert(width > 0 && height > 0 && has_ch > 0, "stbi_load_from_image failure: dimensions are invalid");
|
||||||
|
|
||||||
|
stbi_image_free(img);
|
||||||
|
|
||||||
|
return TexMeta(w: width, h: height, ch: has_ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TestFile()
|
||||||
|
{
|
||||||
|
File ap = File("assets.sgp", "rb");
|
||||||
|
scope(exit)
|
||||||
|
{
|
||||||
|
ap.flush();
|
||||||
|
ap.close();
|
||||||
|
chdir("../build");
|
||||||
|
}
|
||||||
|
|
||||||
|
FileHeader file_header = ap.rawRead(new FileHeader[1])[0];
|
||||||
|
FileHeader test_header = InitHeader(g_asset_count);
|
||||||
|
assert(file_header == test_header, "TestFile failure: Header is incorrect");
|
||||||
|
|
||||||
|
AssetInfo[] file_info = ap.rawRead(new AssetInfo[g_asset_count]);
|
||||||
|
assert(file_info.length == file_header.asset_count, "TestFile failure: Incorrect AssetInfo length returned");
|
||||||
|
|
||||||
|
chdir("../assets");
|
||||||
|
|
||||||
|
u64 asset_index = 0;
|
||||||
|
foreach(i, file; g_file_names)
|
||||||
|
{
|
||||||
|
scope(exit) asset_index += 1;
|
||||||
|
|
||||||
|
AssetInfo* info = file_info.ptr + asset_index;
|
||||||
|
File asset = File(file, "rb");
|
||||||
|
|
||||||
|
u8[] data = asset.rawRead(new u8[asset.size()]);
|
||||||
|
assert(data.length == info.length, "TestFile failure: File length read is incorrect");
|
||||||
|
|
||||||
|
string base_name = chompPrefix(file, "./");
|
||||||
|
assert(Hash(base_name) == info.hash, "TestFile failure: File hash is incorrect");
|
||||||
|
|
||||||
|
ap.seek(info.offset);
|
||||||
|
u8[] pack_data = ap.rawRead(new u8[info.length]);
|
||||||
|
assert(equal!((a, b) => a == b)(data[], pack_data[]), "TestFile failure: Asset data does not match file data");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32
|
||||||
|
MagicValue(string str)
|
||||||
|
{
|
||||||
|
assert(str.length == 4, "Magic value must 4 characters");
|
||||||
|
return cast(u32)(cast(u32)(str[0] << 24) | cast(u32)(str[1] << 16) | cast(u32)(str[2] << 8) | cast(u32)(str[3] << 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
static FileHeader
|
||||||
|
InitHeader(u64 asset_count)
|
||||||
|
{
|
||||||
|
FileHeader header = {
|
||||||
|
magic: MagicValue("steg"),
|
||||||
|
file_version: FILE_VERSION,
|
||||||
|
asset_count: asset_count,
|
||||||
|
asset_info_offset: FileHeader.sizeof,
|
||||||
|
};
|
||||||
|
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ModelHeader
|
||||||
|
InitModelHeader()
|
||||||
|
{
|
||||||
|
ModelHeader header = {
|
||||||
|
magic: MagicValue("stgm"),
|
||||||
|
model_version: MODEL_VERSION,
|
||||||
|
};
|
||||||
|
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
|
Model
|
||||||
|
ConvertM3D(u8[] data)
|
||||||
|
{
|
||||||
|
Model model;
|
||||||
|
|
||||||
|
m3d_t* m3d = m3d_load(data.ptr, null, null, null);
|
||||||
|
|
||||||
|
m3dm_t[] mats = m3d.material[0 .. m3d.nummaterial];
|
||||||
|
foreach(mat; mats)
|
||||||
|
{
|
||||||
|
MaterialData matd;
|
||||||
|
m3dp_t[] props = mat.prop[0 .. mat.numprop];
|
||||||
|
|
||||||
|
foreach(prop; props)
|
||||||
|
{
|
||||||
|
switch(prop.type)
|
||||||
|
{
|
||||||
|
case m3dp_Kd:
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
69
platform.d
69
platform.d
@ -438,6 +438,64 @@ const char[][] ATOM_STRS = [
|
|||||||
|
|
||||||
alias PThreadProc = extern (C) void* function(void*);
|
alias PThreadProc = extern (C) void* function(void*);
|
||||||
|
|
||||||
|
auto
|
||||||
|
ExecLocation(T)()
|
||||||
|
{
|
||||||
|
static char[512] buf;
|
||||||
|
|
||||||
|
u64 size = readlink("/proc/self/exe", buf.ptr, buf.length);
|
||||||
|
|
||||||
|
char[] str;
|
||||||
|
for(u64 i = size-1; i64(i) >= 0; i -= 1)
|
||||||
|
{
|
||||||
|
if(buf[i] == '/')
|
||||||
|
{
|
||||||
|
str = buf[0 .. i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static if(is(T: u8) || is(T: char) || is(T: i8))
|
||||||
|
{
|
||||||
|
return (cast(T[])str);
|
||||||
|
}
|
||||||
|
else static if(is(T: string))
|
||||||
|
{
|
||||||
|
string s = (cast(immutable(char)*)str.ptr)[0 .. str.length];
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
else static assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto
|
||||||
|
Cwd(T)()
|
||||||
|
{
|
||||||
|
static char[512] buf;
|
||||||
|
|
||||||
|
getcwd(buf.ptr, buf.length);
|
||||||
|
|
||||||
|
static if(is(T: u8) || is(T: i8) || is(T: char))
|
||||||
|
{
|
||||||
|
return (cast(T*)buf.ptr)[0 .. strlen(buf.ptr)];
|
||||||
|
}
|
||||||
|
else static if(is(T: string))
|
||||||
|
{
|
||||||
|
string s = (cast(immutable(char)*)buf.ptr)[0 .. strlen(buf.ptr)];
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ChDir(u8[] dir)
|
||||||
|
{
|
||||||
|
char[512] buf;
|
||||||
|
|
||||||
|
buf[0 .. dir.length] = (cast(char*)dir)[0 .. dir.length];
|
||||||
|
buf[dir.length] = '\0';
|
||||||
|
|
||||||
|
return chdir(buf.ptr) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
SysThread
|
SysThread
|
||||||
CreateThread(void* proc, void* param)
|
CreateThread(void* proc, void* param)
|
||||||
{
|
{
|
||||||
@ -1843,5 +1901,16 @@ unittest
|
|||||||
assert(ch == '`');
|
assert(ch == '`');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
string s = ExecLocation!(string)();
|
||||||
|
u8[] b = ExecLocation!(u8)();
|
||||||
|
|
||||||
|
assert(ChDir(b));
|
||||||
|
|
||||||
|
string wd = Cwd!(string)();
|
||||||
|
|
||||||
|
assert(wd == s);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user