625 lines
16 KiB
Haxe
625 lines
16 KiB
Haxe
|
package iron.data;
|
||
|
|
||
|
import haxe.Json;
|
||
|
import iron.data.SceneFormat;
|
||
|
import iron.system.LnxPack;
|
||
|
import iron.system.Lz4;
|
||
|
using StringTools;
|
||
|
|
||
|
// Global data list and asynchronous data loading
|
||
|
class Data {
|
||
|
|
||
|
public static var cachedSceneRaws: Map<String, TSceneFormat> = new Map();
|
||
|
public static var cachedMeshes: Map<String, MeshData> = new Map();
|
||
|
public static var cachedLights: Map<String, LightData> = new Map();
|
||
|
public static var cachedCameras: Map<String, CameraData> = new Map();
|
||
|
public static var cachedMaterials: Map<String, MaterialData> = new Map();
|
||
|
public static var cachedParticles: Map<String, ParticleData> = new Map();
|
||
|
public static var cachedWorlds: Map<String, WorldData> = new Map();
|
||
|
public static var cachedShaders: Map<String, ShaderData> = new Map();
|
||
|
#if rp_probes
|
||
|
public static var cachedProbes: Map<String, ProbeData> = new Map();
|
||
|
#end
|
||
|
|
||
|
public static var cachedBlobs: Map<String, kha.Blob> = new Map();
|
||
|
public static var cachedImages: Map<String, kha.Image> = new Map();
|
||
|
#if lnx_audio
|
||
|
public static var cachedSounds: Map<String, kha.Sound> = new Map();
|
||
|
#end
|
||
|
public static var cachedVideos: Map<String, kha.Video> = new Map();
|
||
|
public static var cachedFonts: Map<String, kha.Font> = new Map();
|
||
|
|
||
|
public static var assetsLoaded = 0;
|
||
|
static var loadingMeshes: Map<String, Array<MeshData->Void>> = new Map();
|
||
|
static var loadingLights: Map<String, Array<LightData->Void>> = new Map();
|
||
|
static var loadingCameras: Map<String, Array<CameraData->Void>> = new Map();
|
||
|
static var loadingMaterials: Map<String, Array<MaterialData->Void>> = new Map();
|
||
|
static var loadingParticles: Map<String, Array<ParticleData->Void>> = new Map();
|
||
|
static var loadingWorlds: Map<String, Array<WorldData->Void>> = new Map();
|
||
|
static var loadingShaders: Map<String, Array<ShaderData->Void>> = new Map();
|
||
|
static var loadingSceneRaws: Map<String, Array<TSceneFormat->Void>> = new Map();
|
||
|
#if rp_probes
|
||
|
static var loadingProbes: Map<String, Array<ProbeData->Void>> = new Map();
|
||
|
#end
|
||
|
static var loadingBlobs: Map<String, Array<kha.Blob->Void>> = new Map();
|
||
|
static var loadingImages: Map<String, Array<kha.Image->Void>> = new Map();
|
||
|
#if lnx_audio
|
||
|
static var loadingSounds: Map<String, Array<kha.Sound->Void>> = new Map();
|
||
|
#end
|
||
|
static var loadingVideos: Map<String, Array<kha.Video->Void>> = new Map();
|
||
|
static var loadingFonts: Map<String, Array<kha.Font->Void>> = new Map();
|
||
|
|
||
|
#if krom_windows
|
||
|
public static inline var sep = "\\";
|
||
|
#else
|
||
|
public static inline var sep = "/";
|
||
|
#end
|
||
|
|
||
|
#if lnx_data_dir
|
||
|
#if krom_android
|
||
|
public static var dataPath = "data" + sep;
|
||
|
#else
|
||
|
public static var dataPath = "." + sep + "data" + sep;
|
||
|
#end
|
||
|
#else
|
||
|
public static var dataPath = "";
|
||
|
#end
|
||
|
|
||
|
public function new() {}
|
||
|
|
||
|
public static function deleteAll() {
|
||
|
for (c in cachedMeshes) c.delete();
|
||
|
cachedMeshes = new Map();
|
||
|
for (c in cachedShaders) c.delete();
|
||
|
cachedShaders = new Map();
|
||
|
cachedSceneRaws = new Map();
|
||
|
cachedLights = new Map();
|
||
|
cachedCameras = new Map();
|
||
|
cachedMaterials = new Map();
|
||
|
cachedParticles = new Map();
|
||
|
cachedWorlds = new Map();
|
||
|
if (RenderPath.active != null) RenderPath.active.unload();
|
||
|
|
||
|
for (c in cachedBlobs) c.unload();
|
||
|
cachedBlobs = new Map();
|
||
|
for (c in cachedImages) c.unload();
|
||
|
cachedImages = new Map();
|
||
|
#if lnx_audio
|
||
|
for (c in cachedSounds) c.unload();
|
||
|
cachedSounds = new Map();
|
||
|
#end
|
||
|
for (c in cachedVideos) c.unload();
|
||
|
cachedVideos = new Map();
|
||
|
for (c in cachedFonts) c.unload();
|
||
|
cachedFonts = new Map();
|
||
|
}
|
||
|
|
||
|
public static function getMesh(file: String, name: String, done: MeshData->Void) {
|
||
|
var handle = file + name;
|
||
|
var cached = cachedMeshes.get(handle);
|
||
|
if (cached != null) {
|
||
|
done(cached);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var loading = loadingMeshes.get(handle);
|
||
|
if (loading != null) {
|
||
|
loading.push(done);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
loadingMeshes.set(handle, [done]);
|
||
|
|
||
|
MeshData.parse(file, name, function(b: MeshData) {
|
||
|
cachedMeshes.set(handle, b);
|
||
|
b.handle = handle;
|
||
|
for (f in loadingMeshes.get(handle)) f(b);
|
||
|
loadingMeshes.remove(handle);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
public static function deleteMesh(handle: String) {
|
||
|
// Remove cached mesh
|
||
|
var mesh = cachedMeshes.get(handle);
|
||
|
if (mesh == null) return;
|
||
|
mesh.delete();
|
||
|
cachedMeshes.remove(handle);
|
||
|
}
|
||
|
|
||
|
public static function getLight(file: String, name: String, done: LightData->Void) {
|
||
|
var handle = file + name;
|
||
|
var cached = cachedLights.get(handle);
|
||
|
if (cached != null) {
|
||
|
done(cached);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var loading = loadingLights.get(handle);
|
||
|
if (loading != null) {
|
||
|
loading.push(done);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
loadingLights.set(handle, [done]);
|
||
|
|
||
|
LightData.parse(file, name, function(b: LightData) {
|
||
|
cachedLights.set(handle, b);
|
||
|
for (f in loadingLights.get(handle)) f(b);
|
||
|
loadingLights.remove(handle);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
#if rp_probes
|
||
|
public static function getProbe(file: String, name: String, done: ProbeData->Void) {
|
||
|
var handle = file + name;
|
||
|
var cached = cachedProbes.get(handle);
|
||
|
if (cached != null) {
|
||
|
done(cached);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var loading = loadingProbes.get(handle);
|
||
|
if (loading != null) {
|
||
|
loading.push(done);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
loadingProbes.set(handle, [done]);
|
||
|
|
||
|
ProbeData.parse(file, name, function(b: ProbeData) {
|
||
|
cachedProbes.set(handle, b);
|
||
|
for (f in loadingProbes.get(handle)) f(b);
|
||
|
loadingProbes.remove(handle);
|
||
|
});
|
||
|
}
|
||
|
#end
|
||
|
|
||
|
public static function getCamera(file: String, name: String, done: CameraData->Void) {
|
||
|
var handle = file + name;
|
||
|
var cached = cachedCameras.get(handle);
|
||
|
if (cached != null) {
|
||
|
done(cached);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var loading = loadingCameras.get(handle);
|
||
|
if (loading != null) {
|
||
|
loading.push(done);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
loadingCameras.set(handle, [done]);
|
||
|
|
||
|
CameraData.parse(file, name, function(b: CameraData) {
|
||
|
cachedCameras.set(handle, b);
|
||
|
for (f in loadingCameras.get(handle)) f(b);
|
||
|
loadingCameras.remove(handle);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
public static function getMaterial(file: String, name: String, done: MaterialData->Void) {
|
||
|
var handle = file + name;
|
||
|
var cached = cachedMaterials.get(handle);
|
||
|
if (cached != null) {
|
||
|
done(cached);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var loading = loadingMaterials.get(handle);
|
||
|
if (loading != null) {
|
||
|
loading.push(done);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
loadingMaterials.set(handle, [done]);
|
||
|
|
||
|
MaterialData.parse(file, name, function(b: MaterialData) {
|
||
|
cachedMaterials.set(handle, b);
|
||
|
for (f in loadingMaterials.get(handle)) f(b);
|
||
|
loadingMaterials.remove(handle);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
public static function getParticle(file: String, name: String, done: ParticleData->Void) {
|
||
|
var handle = file + name;
|
||
|
var cached = cachedParticles.get(handle);
|
||
|
if (cached != null) {
|
||
|
done(cached);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var loading = loadingParticles.get(handle);
|
||
|
if (loading != null) {
|
||
|
loading.push(done);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
loadingParticles.set(handle, [done]);
|
||
|
|
||
|
ParticleData.parse(file, name, function(b: ParticleData) {
|
||
|
cachedParticles.set(handle, b);
|
||
|
for (f in loadingParticles.get(handle)) f(b);
|
||
|
loadingParticles.remove(handle);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
public static function getWorld(file: String, name: String, done: WorldData->Void) {
|
||
|
if (name == null) { // No world defined in scene
|
||
|
done(null);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var handle = file + name;
|
||
|
var cached = cachedWorlds.get(handle);
|
||
|
if (cached != null) {
|
||
|
done(cached);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var loading = loadingWorlds.get(handle);
|
||
|
if (loading != null) {
|
||
|
loading.push(done);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
loadingWorlds.set(handle, [done]);
|
||
|
|
||
|
WorldData.parse(file, name, function(b: WorldData) {
|
||
|
cachedWorlds.set(handle, b);
|
||
|
for (f in loadingWorlds.get(handle)) f(b);
|
||
|
loadingWorlds.remove(handle);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
public static function getShader(file: String, name: String, done: ShaderData->Void, overrideContext: TShaderOverride = null) {
|
||
|
// Only one context override per shader data for now
|
||
|
var cacheName = name;
|
||
|
if (overrideContext != null) cacheName += "2";
|
||
|
var cached = cachedShaders.get(cacheName); // Shader must have unique name
|
||
|
if (cached != null) {
|
||
|
done(cached);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var loading = loadingShaders.get(cacheName);
|
||
|
if (loading != null) {
|
||
|
loading.push(done);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
loadingShaders.set(cacheName, [done]);
|
||
|
|
||
|
ShaderData.parse(file, name, function(b: ShaderData) {
|
||
|
cachedShaders.set(cacheName, b);
|
||
|
for (f in loadingShaders.get(cacheName)) f(b);
|
||
|
loadingShaders.remove(cacheName);
|
||
|
}, overrideContext);
|
||
|
}
|
||
|
|
||
|
public static function getSceneRaw(file: String, done: TSceneFormat->Void) {
|
||
|
var cached = cachedSceneRaws.get(file);
|
||
|
if (cached != null) {
|
||
|
done(cached);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var loading = loadingSceneRaws.get(file);
|
||
|
if (loading != null) {
|
||
|
loading.push(done);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
loadingSceneRaws.set(file, [done]);
|
||
|
|
||
|
// If no extension specified, set to .arm
|
||
|
var compressed = file.endsWith(".lz4");
|
||
|
var isJson = file.endsWith(".json");
|
||
|
var ext = (compressed || isJson || file.endsWith(".lnx")) ? "" : ".lnx";
|
||
|
|
||
|
getBlob(file + ext, function(b: kha.Blob) {
|
||
|
var parsed: TSceneFormat = null;
|
||
|
|
||
|
#if lnx_compress
|
||
|
if (compressed) {
|
||
|
var bytes = b.toBytes();
|
||
|
|
||
|
// First 8 bytes contain data size for decoding
|
||
|
var packedSize = haxe.Int64.toInt(bytes.getInt64(0));
|
||
|
|
||
|
parsed = LnxPack.decode(Lz4.decode(bytes.sub(8, bytes.length - 8), packedSize));
|
||
|
}
|
||
|
|
||
|
else #end if (isJson) {
|
||
|
var s = b.toString();
|
||
|
parsed = s.charAt(0) == "{" ? Json.parse(s) : LnxPack.decode(b.toBytes());
|
||
|
}
|
||
|
else {
|
||
|
parsed = LnxPack.decode(b.toBytes());
|
||
|
}
|
||
|
|
||
|
returnSceneRaw(file, parsed);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
static function returnSceneRaw(file: String, parsed: TSceneFormat) {
|
||
|
cachedSceneRaws.set(file, parsed);
|
||
|
for (f in loadingSceneRaws.get(file)) f(parsed);
|
||
|
loadingSceneRaws.remove(file);
|
||
|
}
|
||
|
|
||
|
public static function getMeshRawByName(datas: Array<TMeshData>, name: String): TMeshData {
|
||
|
if (name == "") return datas[0];
|
||
|
for (dat in datas) if (dat.name == name) return dat;
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
public static function getLightRawByName(datas: Array<TLightData>, name: String): TLightData {
|
||
|
if (name == "") return datas[0];
|
||
|
for (dat in datas) if (dat.name == name) return dat;
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
#if rp_probes
|
||
|
public static function getProbeRawByName(datas: Array<TProbeData>, name: String): TProbeData {
|
||
|
if (name == "") return datas[0];
|
||
|
for (dat in datas) if (dat.name == name) return dat;
|
||
|
return null;
|
||
|
}
|
||
|
#end
|
||
|
|
||
|
public static function getCameraRawByName(datas: Array<TCameraData>, name: String): TCameraData {
|
||
|
if (name == "") return datas[0];
|
||
|
for (dat in datas) if (dat.name == name) return dat;
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
public static function getMaterialRawByName(datas: Array<TMaterialData>, name: String): TMaterialData {
|
||
|
if (name == "") return datas[0];
|
||
|
for (dat in datas) if (dat.name == name) return dat;
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
public static function getParticleRawByName(datas: Array<TParticleData>, name: String): TParticleData {
|
||
|
if (name == "") return datas[0];
|
||
|
for (dat in datas) if (dat.name == name) return dat;
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
public static function getWorldRawByName(datas: Array<TWorldData>, name: String): TWorldData {
|
||
|
if (name == "") return datas[0];
|
||
|
for (dat in datas) if (dat.name == name) return dat;
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
public static function getShaderRawByName(datas: Array<TShaderData>, name: String): TShaderData {
|
||
|
if (name == "") return datas[0];
|
||
|
for (dat in datas) if (dat.name == name) return dat;
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
#if lnx_audio
|
||
|
public static function getSpeakerRawByName(datas: Array<TSpeakerData>, name: String): TSpeakerData {
|
||
|
if (name == "") return datas[0];
|
||
|
for (dat in datas) if (dat.name == name) return dat;
|
||
|
return null;
|
||
|
}
|
||
|
#end
|
||
|
|
||
|
// Raw assets
|
||
|
public static function getBlob(file: String, done: kha.Blob->Void) {
|
||
|
var cached = cachedBlobs.get(file); // Is already cached
|
||
|
if (cached != null) {
|
||
|
done(cached);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var loading = loadingBlobs.get(file); // Is already being loaded
|
||
|
if (loading != null) {
|
||
|
loading.push(done);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
loadingBlobs.set(file, [done]); // Start loading
|
||
|
|
||
|
kha.Assets.loadBlobFromPath(resolvePath(file), function(b: kha.Blob) {
|
||
|
cachedBlobs.set(file, b);
|
||
|
for (f in loadingBlobs.get(file)) f(b);
|
||
|
loadingBlobs.remove(file);
|
||
|
assetsLoaded++;
|
||
|
});
|
||
|
}
|
||
|
|
||
|
public static function deleteBlob(handle: String) {
|
||
|
var blob = cachedBlobs.get(handle);
|
||
|
if (blob == null) return;
|
||
|
blob.unload();
|
||
|
cachedBlobs.remove(handle);
|
||
|
}
|
||
|
|
||
|
public static function getImage(file: String, done: kha.Image->Void, readable = false, format = "RGBA32") {
|
||
|
#if (cpp || hl || lnx_use_k_images)
|
||
|
if (!file.endsWith(".k")) {
|
||
|
file = file.substring(0, file.length - 4) + ".k";
|
||
|
}
|
||
|
#end
|
||
|
|
||
|
var cached = cachedImages.get(file);
|
||
|
if (cached != null) {
|
||
|
done(cached);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var loading = loadingImages.get(file);
|
||
|
if (loading != null) {
|
||
|
loading.push(done);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
loadingImages.set(file, [done]);
|
||
|
|
||
|
#if lnx_image_embed
|
||
|
var imageBlob = cachedBlobs.get(file);
|
||
|
if (imageBlob != null) {
|
||
|
kha.Image.fromEncodedBytes(imageBlob.bytes, ".k", function(b: kha.Image) {
|
||
|
cachedImages.set(file, b);
|
||
|
for (f in loadingImages.get(file)) f(b);
|
||
|
loadingImages.remove(file);
|
||
|
assetsLoaded++;
|
||
|
}, null, readable);
|
||
|
return;
|
||
|
}
|
||
|
#end
|
||
|
|
||
|
kha.Assets.loadImageFromPath(resolvePath(file), readable, function(b: kha.Image) {
|
||
|
cachedImages.set(file, b);
|
||
|
for (f in loadingImages.get(file)) f(b);
|
||
|
loadingImages.remove(file);
|
||
|
assetsLoaded++;
|
||
|
});
|
||
|
}
|
||
|
|
||
|
public static function deleteImage(handle: String) {
|
||
|
var image = cachedImages.get(handle);
|
||
|
if (image == null) return;
|
||
|
image.unload();
|
||
|
cachedImages.remove(handle);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Load sound file from disk into ram.
|
||
|
@param file A String matching the file name of the sound file on disk.
|
||
|
@param done Completion handler function to do something after the sound is loaded.
|
||
|
*/
|
||
|
#if lnx_audio
|
||
|
public static function getSound(file: String, done: kha.Sound->Void) {
|
||
|
#if lnx_soundcompress
|
||
|
if (file.endsWith(".wav")) file = file.substring(0, file.length - 4) + ".ogg";
|
||
|
#end
|
||
|
|
||
|
var cached = cachedSounds.get(file);
|
||
|
if (cached != null) {
|
||
|
done(cached);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var loading = loadingSounds.get(file);
|
||
|
if (loading != null) {
|
||
|
loading.push(done);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
loadingSounds.set(file, [done]);
|
||
|
|
||
|
kha.Assets.loadSoundFromPath(resolvePath(file), function(b: kha.Sound) {
|
||
|
#if lnx_soundcompress
|
||
|
b.uncompress(function () {
|
||
|
#end
|
||
|
cachedSounds.set(file, b);
|
||
|
for (f in loadingSounds.get(file)) f(b);
|
||
|
loadingSounds.remove(file);
|
||
|
assetsLoaded++;
|
||
|
#if lnx_soundcompress
|
||
|
});
|
||
|
#end
|
||
|
});
|
||
|
}
|
||
|
|
||
|
public static function deleteSound(handle: String) {
|
||
|
var sound = cachedSounds.get(handle);
|
||
|
if (sound == null) return;
|
||
|
sound.unload();
|
||
|
cachedSounds.remove(handle);
|
||
|
}
|
||
|
#end // lnx_audio
|
||
|
|
||
|
public static function getVideo(file: String, done: kha.Video->Void) {
|
||
|
#if (cpp || hl)
|
||
|
file = file.substring(0, file.length - 4) + ".avi";
|
||
|
#elseif krom
|
||
|
file = file.substring(0, file.length - 4) + ".webm";
|
||
|
#end
|
||
|
var cached = cachedVideos.get(file);
|
||
|
if (cached != null) {
|
||
|
done(cached);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var loading = loadingVideos.get(file);
|
||
|
if (loading != null) {
|
||
|
loading.push(done);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
loadingVideos.set(file, [done]);
|
||
|
|
||
|
kha.Assets.loadVideoFromPath(resolvePath(file), function(b: kha.Video) {
|
||
|
cachedVideos.set(file, b);
|
||
|
for (f in loadingVideos.get(file)) f(b);
|
||
|
loadingVideos.remove(file);
|
||
|
assetsLoaded++;
|
||
|
});
|
||
|
}
|
||
|
|
||
|
public static function deleteVideo(handle: String) {
|
||
|
var video = cachedVideos.get(handle);
|
||
|
if (video == null) return;
|
||
|
video.unload();
|
||
|
cachedVideos.remove(handle);
|
||
|
}
|
||
|
|
||
|
public static function getFont(file: String, done: kha.Font->Void) {
|
||
|
var cached = cachedFonts.get(file);
|
||
|
if (cached != null) {
|
||
|
done(cached);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var loading = loadingFonts.get(file);
|
||
|
if (loading != null) {
|
||
|
loading.push(done);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
loadingFonts.set(file, [done]);
|
||
|
|
||
|
kha.Assets.loadFontFromPath(resolvePath(file), function(b: kha.Font) {
|
||
|
cachedFonts.set(file, b);
|
||
|
for (f in loadingFonts.get(file)) f(b);
|
||
|
loadingFonts.remove(file);
|
||
|
assetsLoaded++;
|
||
|
});
|
||
|
}
|
||
|
|
||
|
public static function deleteFont(handle: String) {
|
||
|
var font = cachedFonts.get(handle);
|
||
|
if (font == null) return;
|
||
|
font.unload();
|
||
|
cachedFonts.remove(handle);
|
||
|
}
|
||
|
|
||
|
public static function isAbsolute(file: String): Bool {
|
||
|
return file.charAt(0) == "/" || file.charAt(1) == ":" || file.charAt(4) == ":" || (file.charAt(0) == "\\" && file.charAt(1) == "\\");
|
||
|
}
|
||
|
|
||
|
static inline function isUp(file: String): Bool {
|
||
|
return file.charAt(0) == "." && file.charAt(1) == ".";
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Extract filename from path.
|
||
|
*/
|
||
|
static inline function baseName(path: String): String {
|
||
|
var slash = path.lastIndexOf(sep);
|
||
|
return slash >= 0 ? path.substr(slash + 1) : path;
|
||
|
}
|
||
|
|
||
|
static inline function resolvePath(file: String): String {
|
||
|
if (isAbsolute(file) || isUp(file)) return file;
|
||
|
#if lnx_data_dir
|
||
|
return dataPath + file;
|
||
|
#else
|
||
|
return baseName(file);
|
||
|
#end
|
||
|
}
|
||
|
}
|