16/32bit exr texture export

This commit is contained in:
luboslenco
2019-06-19 09:40:14 +02:00
parent b032ebe6eb
commit bc5e89a834
7 changed files with 155 additions and 283 deletions
+56 -222
View File
@@ -6,13 +6,45 @@ import arm.ui.UIBox;
class Exporter {
static inline var gamma = 1.0 / 2.2;
static function writeTexture(file:String, pixels:haxe.io.Bytes, type = 1, off = 0) {
var out = new haxe.io.BytesOutput();
var res = Config.getTextureRes();
var bitsHandle = UITrait.inst.bitsHandle.position;
var bits = bitsHandle == 0 ? 8 : bitsHandle == 1 ? 16 : 32;
if (bits > 8) { // 16/32bit
var writer = new iron.format.exr.Writer(out, res, res, pixels, bits, type, off);
}
else if (UITrait.inst.formatType == 0) {
var writer = new iron.format.jpg.Writer(out);
writer.write({
width: res,
height: res,
quality: UITrait.inst.formatQuality,
pixels: pixels
}, type, off);
}
else {
var writer = new iron.format.png.Writer(out);
var data = type == 1 ?
iron.format.png.Tools.build32RGBA(res, res, pixels) :
iron.format.png.Tools.build32RGBA_(res, res, pixels, off);
writer.write(data);
}
#if kha_krom
Krom.fileSaveBytes(file, out.getBytes().getData());
#end
}
public static function exportTextures(path:String) {
var textureSize = Config.getTextureRes();
var formatQuality = UITrait.inst.formatQuality;
var f = arm.App.filenameHandle.text;
if (f == "") f = "untitled";
var formatType = UITrait.inst.formatType;
var ext = formatType == 0 ? ".jpg" : formatType == 1 ? ".png" : ".tga";
var bits = UITrait.inst.bitsHandle.position == 0 ? 8 : 16;
var ext = bits == 16 ? ".exr" : formatType == 0 ? ".jpg" : ".png";
if (StringTools.endsWith(f, ext)) f = f.substr(0, f.length - 4);
var texpaint:kha.Image = null;
var texpaint_nor:kha.Image = null;
@@ -115,227 +147,76 @@ class Exporter {
}
}
var bo = new haxe.io.BytesOutput();
var pixels:haxe.io.Bytes = null;
if (UITrait.inst.isBase || UITrait.inst.isOpac) {
pixels = texpaint.getPixels(); // bgra
if (UITrait.inst.isBase && UITrait.inst.isBaseSpace == 1) {
for (i in 0...Std.int(pixels.length / 4)) {
pixels.set(i * 4 , Std.int(Math.pow(pixels.get(i * 4 ) / 255, 1.0 / 2.2) * 255));
pixels.set(i * 4 + 1, Std.int(Math.pow(pixels.get(i * 4 + 1) / 255, 1.0 / 2.2) * 255));
pixels.set(i * 4 + 2, Std.int(Math.pow(pixels.get(i * 4 + 2) / 255, 1.0 / 2.2) * 255));
pixels.set(i * 4 , Std.int(Math.pow(pixels.get(i * 4 ) / 255, gamma) * 255));
pixels.set(i * 4 + 1, Std.int(Math.pow(pixels.get(i * 4 + 1) / 255, gamma) * 255));
pixels.set(i * 4 + 2, Std.int(Math.pow(pixels.get(i * 4 + 2) / 255, gamma) * 255));
}
}
if (UITrait.inst.isOpac && UITrait.inst.isOpacSpace == 1) {
for (i in 0...Std.int(pixels.length / 4)) {
pixels.set(i * 4 + 3, Std.int(Math.pow(pixels.get(i * 4 + 3) / 255, 1.0 / 2.2) * 255));
pixels.set(i * 4 + 3, Std.int(Math.pow(pixels.get(i * 4 + 3) / 255, gamma) * 255));
}
}
if (UITrait.inst.isBase) {
if (formatType == 0) {
var jpgdata:iron.format.jpg.Data.Data = {
width: textureSize,
height: textureSize,
quality: formatQuality,
pixels: pixels
};
var jpgwriter = new iron.format.jpg.Writer(bo);
jpgwriter.write(jpgdata, 1);
}
else {
var pngwriter = new iron.format.png.Writer(bo);
pngwriter.write(iron.format.png.Tools.build32RGBA(textureSize, textureSize, pixels));
}
#if kha_krom
Krom.fileSaveBytes(path + "/" + f + "_base" + ext, bo.getBytes().getData());
#end
}
if (UITrait.inst.isOpac) {
bo = new haxe.io.BytesOutput();
if (formatType == 0) {
var jpgdata:iron.format.jpg.Data.Data = {
width: textureSize,
height: textureSize,
quality: formatQuality,
pixels: pixels
};
var jpgwriter = new iron.format.jpg.Writer(bo);
jpgwriter.write(jpgdata, 2, 3);
}
else {
var pngwriter = new iron.format.png.Writer(bo);
pngwriter.write(iron.format.png.Tools.build32RGBA(textureSize, textureSize, pixels, 3));
}
#if kha_krom
Krom.fileSaveBytes(path + "/" + f + "_opac" + ext, bo.getBytes().getData());
#end
}
if (UITrait.inst.isBase) writeTexture(path + "/" + f + "_base" + ext, pixels);
if (UITrait.inst.isOpac) writeTexture(path + "/" + f + "_opac" + ext, pixels, 2, 3);
}
if (UITrait.inst.isNor) {
pixels = texpaint_nor.getPixels();
if (UITrait.inst.isNorSpace == 1) {
for (i in 0...Std.int(pixels.length / 4)) {
pixels.set(i * 4 , Std.int(Math.pow(pixels.get(i * 4 ) / 255, 1.0 / 2.2) * 255));
pixels.set(i * 4 + 1, Std.int(Math.pow(pixels.get(i * 4 + 1) / 255, 1.0 / 2.2) * 255));
pixels.set(i * 4 + 2, Std.int(Math.pow(pixels.get(i * 4 + 2) / 255, 1.0 / 2.2) * 255));
pixels.set(i * 4 , Std.int(Math.pow(pixels.get(i * 4 ) / 255, gamma) * 255));
pixels.set(i * 4 + 1, Std.int(Math.pow(pixels.get(i * 4 + 1) / 255, gamma) * 255));
pixels.set(i * 4 + 2, Std.int(Math.pow(pixels.get(i * 4 + 2) / 255, gamma) * 255));
}
}
bo = new haxe.io.BytesOutput();
if (formatType == 0) {
var jpgdata:iron.format.jpg.Data.Data = {
width: textureSize,
height: textureSize,
quality: formatQuality,
pixels: pixels
};
var jpgwriter = new iron.format.jpg.Writer(bo);
jpgwriter.write(jpgdata, 1);
}
else {
var pngwriter = new iron.format.png.Writer(bo);
pngwriter.write(iron.format.png.Tools.build32RGBA(textureSize, textureSize, pixels));
}
#if kha_krom
Krom.fileSaveBytes(path + "/" + f + "_nor" + ext, bo.getBytes().getData());
#end
writeTexture(path + "/" + f + "_nor" + ext, pixels);
}
if (UITrait.inst.isOcc || UITrait.inst.isRough || UITrait.inst.isMet || UITrait.inst.isHeight) {
pixels = texpaint_pack.getPixels(); // occ, rough, met, height
if (UITrait.inst.isOcc && UITrait.inst.isOccSpace == 1) {
for (i in 0...Std.int(pixels.length / 4)) {
pixels.set(i * 4 + 2, Std.int(Math.pow(pixels.get(i * 4 + 2) / 255, 1.0 / 2.2) * 255));
pixels.set(i * 4 + 2, Std.int(Math.pow(pixels.get(i * 4 + 2) / 255, gamma) * 255));
}
}
if (UITrait.inst.isRough && UITrait.inst.isRoughSpace == 1) {
for (i in 0...Std.int(pixels.length / 4)) {
pixels.set(i * 4 + 1, Std.int(Math.pow(pixels.get(i * 4 + 1) / 255, 1.0 / 2.2) * 255));
pixels.set(i * 4 + 1, Std.int(Math.pow(pixels.get(i * 4 + 1) / 255, gamma) * 255));
}
}
if (UITrait.inst.isMet && UITrait.inst.isMetSpace == 1) {
for (i in 0...Std.int(pixels.length / 4)) {
pixels.set(i * 4 , Std.int(Math.pow(pixels.get(i * 4 ) / 255, 1.0 / 2.2) * 255));
pixels.set(i * 4 , Std.int(Math.pow(pixels.get(i * 4 ) / 255, gamma) * 255));
}
}
if (UITrait.inst.isHeight && UITrait.inst.isHeightSpace == 1) {
for (i in 0...Std.int(pixels.length / 4)) {
pixels.set(i * 4 + 3, Std.int(Math.pow(pixels.get(i * 4 + 3) / 255, 1.0 / 2.2) * 255));
pixels.set(i * 4 + 3, Std.int(Math.pow(pixels.get(i * 4 + 3) / 255, gamma) * 255));
}
}
if (UITrait.inst.outputType == 0) {
if (UITrait.inst.isOcc) {
bo = new haxe.io.BytesOutput();
if (formatType == 0) {
var jpgdata:iron.format.jpg.Data.Data = {
width: textureSize,
height: textureSize,
quality: formatQuality,
pixels: pixels
};
var jpgwriter = new iron.format.jpg.Writer(bo);
jpgwriter.write(jpgdata, 2, 0);
}
else {
var pngwriter = new iron.format.png.Writer(bo);
pngwriter.write(iron.format.png.Tools.build32RGBA_(textureSize, textureSize, pixels, 0));
}
#if kha_krom
Krom.fileSaveBytes(path + "/" + f + "_occ" + ext, bo.getBytes().getData());
#end
}
if (UITrait.inst.isRough) {
bo = new haxe.io.BytesOutput();
if (formatType == 0) {
var jpgdata:iron.format.jpg.Data.Data = {
width: textureSize,
height: textureSize,
quality: formatQuality,
pixels: pixels
};
var jpgwriter = new iron.format.jpg.Writer(bo);
jpgwriter.write(jpgdata, 2, 1);
}
else {
var pngwriter = new iron.format.png.Writer(bo);
pngwriter.write(iron.format.png.Tools.build32RGBA_(textureSize, textureSize, pixels, 1));
}
#if kha_krom
Krom.fileSaveBytes(path + "/" + f + "_rough" + ext, bo.getBytes().getData());
#end
}
if (UITrait.inst.isMet) {
bo = new haxe.io.BytesOutput();
if (formatType == 0) {
var jpgdata:iron.format.jpg.Data.Data = {
width: textureSize,
height: textureSize,
quality: formatQuality,
pixels: pixels
};
var jpgwriter = new iron.format.jpg.Writer(bo);
jpgwriter.write(jpgdata, 2, 2);
}
else {
var pngwriter = new iron.format.png.Writer(bo);
pngwriter.write(iron.format.png.Tools.build32RGBA_(textureSize, textureSize, pixels, 2));
}
#if kha_krom
Krom.fileSaveBytes(path + "/" + f + "_met" + ext, bo.getBytes().getData());
#end
}
if (UITrait.inst.isOcc) writeTexture(path + "/" + f + "_occ" + ext, pixels, 2, 0);
if (UITrait.inst.isRough) writeTexture(path + "/" + f + "_rough" + ext, pixels, 2, 1);
if (UITrait.inst.isMet) writeTexture(path + "/" + f + "_met" + ext, pixels, 2, 2);
}
else { // UE4
if (UITrait.inst.isOcc || UITrait.inst.isRough || UITrait.inst.isMet) {
bo = new haxe.io.BytesOutput();
if (formatType == 0) {
var jpgdata:iron.format.jpg.Data.Data = {
width: textureSize,
height: textureSize,
quality: formatQuality,
pixels: pixels
};
var jpgwriter = new iron.format.jpg.Writer(bo);
jpgwriter.write(jpgdata, 1);
}
else {
var pngwriter = new iron.format.png.Writer(bo);
pngwriter.write(iron.format.png.Tools.build32RGBA(textureSize, textureSize, pixels));
}
#if kha_krom
Krom.fileSaveBytes(path + "/" + f + "_orm" + ext, bo.getBytes().getData());
#end
writeTexture(path + "/" + f + "_orm" + ext, pixels);
}
}
if (UITrait.inst.isHeight) {
bo = new haxe.io.BytesOutput();
if (formatType == 0) {
var jpgdata:iron.format.jpg.Data.Data = {
width: textureSize,
height: textureSize,
quality: formatQuality,
pixels: pixels
};
var jpgwriter = new iron.format.jpg.Writer(bo);
jpgwriter.write(jpgdata, 2, 3);
}
else {
var pngwriter = new iron.format.png.Writer(bo);
pngwriter.write(iron.format.png.Tools.build32RGBA(textureSize, textureSize, pixels, 3));
}
#if kha_krom
Krom.fileSaveBytes(path + "/" + f + "_height" + ext, bo.getBytes().getData());
#end
}
if (UITrait.inst.isHeight) writeTexture(path + "/" + f + "_height" + ext, pixels, 2, 3);
}
// if (UITrait.inst.isEmis) Krom.fileSaveBytes(path + "/tex_emis" + ext, bo.getBytes().getData());
@@ -343,54 +224,7 @@ class Exporter {
}
public static function exportMesh(path:String) {
if (UITrait.inst.exportMeshFormat == 0) { // .obj
var s = "";
var off = 0;
for (p in UITrait.inst.paintObjects) {
var mesh = p.data.raw;
var sc = p.data.scalePos;
var posa = mesh.vertex_arrays[0].values;
var nora = mesh.vertex_arrays[1].values;
var texa = mesh.vertex_arrays[2].values;
var len = Std.int(posa.length / 4);
s += "o " + p.name + "\n";
for (i in 0...len) {
s += "v " + posa[i * 4 ] * sc + " " +
posa[i * 4 + 2] * sc + " " +
(-posa[i * 4 + 1] * sc) + "\n";
}
for (i in 0...len) {
s += "vn " + nora[i * 2 ] + " " +
posa[i * 4 + 3] + " " +
(-nora[i * 2 + 1]) + "\n";
}
for (i in 0...len) {
s += "vt " + texa[i * 2 ] + " " +
(1.0 - texa[i * 2 + 1]) + "\n";
}
var inda = mesh.index_arrays[0].values;
for (i in 0...Std.int(inda.length / 3)) {
var i1 = inda[i * 3 ] + 1 + off;
var i2 = inda[i * 3 + 1] + 1 + off;
var i3 = inda[i * 3 + 2] + 1 + off;
s += "f " + i1 + "/" + i1 + "/" + i1 + " " +
i2 + "/" + i2 + "/" + i2 + " " +
i3 + "/" + i3 + "/" + i3 + "\n";
}
off += inda.length;
}
if (!StringTools.endsWith(path, ".obj")) path += ".obj";
#if kha_krom
Krom.fileSaveBytes(path, haxe.io.Bytes.ofString(s).getData());
#end
}
else { // .arm
var raw:TSceneFormat = { mesh_datas: [ UITrait.inst.paintObject.data.raw ] };
var b = iron.system.ArmPack.encode(raw);
if (!StringTools.endsWith(path, ".arm")) path += ".arm";
#if kha_krom
Krom.fileSaveBytes(path, b.getData());
#end
}
if (UITrait.inst.exportMeshFormat == 0) arm.io.ExportObj.run(path);
else arm.io.ExportArm.run(path);
}
}
+19 -49
View File
@@ -72,7 +72,8 @@ class LayerSlot {
}
this.ext = ext;
name = "Layer " + (id + 1);
var format = UITrait.inst.bitsHandle.position == 0 ? 'RGBA32' : 'RGBA64';
var format = UITrait.inst.bitsHandle.position == 0 ? 'RGBA32' :
UITrait.inst.bitsHandle.position == 1 ? 'RGBA64' : 'RGBA128';
{
var t = new RenderTargetRaw();
@@ -274,7 +275,10 @@ class LayerSlot {
return l;
}
public function resize() {
public function resizeAndSetBits() {
var format = UITrait.inst.bitsHandle.position == 0 ? TextureFormat.RGBA32 :
UITrait.inst.bitsHandle.position == 1 ? TextureFormat.RGBA64 : TextureFormat.RGBA128;
var res = Config.getTextureRes();
var rts = RenderPath.active.renderTargets;
@@ -282,53 +286,6 @@ class LayerSlot {
var texpaint_nor = this.texpaint_nor;
var texpaint_pack = this.texpaint_pack;
this.texpaint = kha.Image.createRenderTarget(res, res, TextureFormat.RGBA32);
this.texpaint_nor = kha.Image.createRenderTarget(res, res, TextureFormat.RGBA32);
this.texpaint_pack = kha.Image.createRenderTarget(res, res, TextureFormat.RGBA32);
this.texpaint.g2.begin(false);
this.texpaint.g2.drawScaledImage(texpaint, 0, 0, res, res);
this.texpaint.g2.end();
this.texpaint_nor.g2.begin(false);
this.texpaint_nor.g2.drawScaledImage(texpaint_nor, 0, 0, res, res);
this.texpaint_nor.g2.end();
this.texpaint_pack.g2.begin(false);
this.texpaint_pack.g2.drawScaledImage(texpaint_pack, 0, 0, res, res);
this.texpaint_pack.g2.end();
texpaint.unload();
texpaint_nor.unload();
texpaint_pack.unload();
rts.get("texpaint" + this.ext).image = this.texpaint;
rts.get("texpaint_nor" + this.ext).image = this.texpaint_nor;
rts.get("texpaint_pack" + this.ext).image = this.texpaint_pack;
if (this.texpaint_mask != null) {
var texpaint_mask = this.texpaint_mask;
this.texpaint_mask = kha.Image.createRenderTarget(res, res, TextureFormat.L8);
this.texpaint_mask.g2.begin(false);
this.texpaint_mask.g2.drawScaledImage(texpaint_mask, 0, 0, res, res);
this.texpaint_mask.g2.end();
texpaint_mask.unload();
rts.get("texpaint_mask" + this.ext).image = this.texpaint_mask;
}
}
public function setBits(formatName:String) {
var format = formatName == "RGBA32" ? TextureFormat.RGBA32 : TextureFormat.RGBA64;
var res = this.texpaint.width;
var rts = RenderPath.active.renderTargets;
var texpaint = this.texpaint;
var texpaint_nor = this.texpaint_nor;
var texpaint_pack = this.texpaint_pack;
this.texpaint = kha.Image.createRenderTarget(res, res, format);
this.texpaint_nor = kha.Image.createRenderTarget(res, res, format);
this.texpaint_pack = kha.Image.createRenderTarget(res, res, format);
@@ -352,5 +309,18 @@ class LayerSlot {
rts.get("texpaint" + this.ext).image = this.texpaint;
rts.get("texpaint_nor" + this.ext).image = this.texpaint_nor;
rts.get("texpaint_pack" + this.ext).image = this.texpaint_pack;
if (this.texpaint_mask != null && this.texpaint_mask.width != res) {
var texpaint_mask = this.texpaint_mask;
this.texpaint_mask = kha.Image.createRenderTarget(res, res, TextureFormat.L8);
this.texpaint_mask.g2.begin(false);
this.texpaint_mask.g2.drawScaledImage(texpaint_mask, 0, 0, res, res);
this.texpaint_mask.g2.end();
texpaint_mask.unload();
rts.get("texpaint_mask" + this.ext).image = this.texpaint_mask;
}
}
}
+4 -5
View File
@@ -90,8 +90,8 @@ class Layers {
while (UITrait.inst.undoLayers.length > C.undo_steps) { var l = UITrait.inst.undoLayers.pop(); l.unload(); }
}
g.end();
for (l in UITrait.inst.layers) l.resize();
for (l in UITrait.inst.undoLayers) l.resize();
for (l in UITrait.inst.layers) l.resizeAndSetBits();
for (l in UITrait.inst.undoLayers) l.resizeAndSetBits();
var rts = RenderPath.active.renderTargets;
rts.get("texpaint_blend0").image.unload();
rts.get("texpaint_blend0").raw.width = Config.getTextureRes();
@@ -109,9 +109,8 @@ class Layers {
public static function setLayerBits(g:kha.graphics4.Graphics) {
g.end();
var format = UITrait.inst.bitsHandle.position == 0 ? 'RGBA32' : 'RGBA64';
for (l in UITrait.inst.layers) l.setBits(format);
for (l in UITrait.inst.undoLayers) l.setBits(format);
for (l in UITrait.inst.layers) l.resizeAndSetBits();
for (l in UITrait.inst.undoLayers) l.resizeAndSetBits();
g.begin();
iron.App.removeRender(setLayerBits);
}
+2 -2
View File
@@ -360,8 +360,8 @@ class Project {
UITrait.inst.resHandle.position = Config.getTextureResPos(project.layer_datas[0].res);
if (UITrait.inst.layers[0].texpaint.width != Config.getTextureRes()) {
for (l in UITrait.inst.layers) l.resize();
if (UITrait.inst.undoLayers != null) for (l in UITrait.inst.undoLayers) l.resize();
for (l in UITrait.inst.layers) l.resizeAndSetBits();
if (UITrait.inst.undoLayers != null) for (l in UITrait.inst.undoLayers) l.resizeAndSetBits();
var rts = iron.RenderPath.active.renderTargets;
rts.get("texpaint_blend0").image.unload();
rts.get("texpaint_blend0").raw.width = Config.getTextureRes();
+16
View File
@@ -0,0 +1,16 @@
package arm.io;
import iron.data.SceneFormat;
import arm.ui.UITrait;
class ExportArm {
public static function run(path:String) {
var raw:TSceneFormat = { mesh_datas: [ UITrait.inst.paintObject.data.raw ] };
var b = iron.system.ArmPack.encode(raw);
if (!StringTools.endsWith(path, ".arm")) path += ".arm";
#if kha_krom
Krom.fileSaveBytes(path, b.getData());
#end
}
}
+48
View File
@@ -0,0 +1,48 @@
package arm.io;
import arm.ui.UITrait;
class ExportObj {
public static function run(path:String) {
var s = "";
var off = 0;
for (p in UITrait.inst.paintObjects) {
var mesh = p.data.raw;
var sc = p.data.scalePos;
var posa = mesh.vertex_arrays[0].values;
var nora = mesh.vertex_arrays[1].values;
var texa = mesh.vertex_arrays[2].values;
var len = Std.int(posa.length / 4);
s += "o " + p.name + "\n";
for (i in 0...len) {
s += "v " + posa[i * 4 ] * sc + " " +
posa[i * 4 + 2] * sc + " " +
(-posa[i * 4 + 1] * sc) + "\n";
}
for (i in 0...len) {
s += "vn " + nora[i * 2 ] + " " +
posa[i * 4 + 3] + " " +
(-nora[i * 2 + 1]) + "\n";
}
for (i in 0...len) {
s += "vt " + texa[i * 2 ] + " " +
(1.0 - texa[i * 2 + 1]) + "\n";
}
var inda = mesh.index_arrays[0].values;
for (i in 0...Std.int(inda.length / 3)) {
var i1 = inda[i * 3 ] + 1 + off;
var i2 = inda[i * 3 + 1] + 1 + off;
var i3 = inda[i * 3 + 2] + 1 + off;
s += "f " + i1 + "/" + i1 + "/" + i1 + " " +
i2 + "/" + i2 + "/" + i2 + " " +
i3 + "/" + i3 + "/" + i3 + "\n";
}
off += inda.length;
}
if (!StringTools.endsWith(path, ".obj")) path += ".obj";
#if kha_krom
Krom.fileSaveBytes(path, haxe.io.Bytes.ofString(s).getData());
#end
}
}
+10 -5
View File
@@ -485,7 +485,7 @@ class UITrait extends iron.Trait {
arm.App.whandle.redraws = 2;
arm.App.foldersOnly = true;
arm.App.showFilename = true;
UIFiles.filters = formatType == 0 ? "jpg" : "png";
UIFiles.filters = bitsHandle.position > 0 ? "exr" : formatType == 0 ? "jpg" : "png";
arm.App.filesDone = function(path:String) {
textureExport = true;
textureExportPath = path;
@@ -2268,7 +2268,7 @@ class UITrait extends iron.Trait {
arm.App.foldersOnly = true;
arm.App.showFilename = true;
// var path = 'C:\\Users\\lubos\\Documents\\';
UIFiles.filters = formatType == 0 ? "jpg" : "png";
UIFiles.filters = bitsHandle.position > 0 ? "exr" : formatType == 0 ? "jpg" : "png";
arm.App.filesDone = function(path:String) {
textureExport = true;
textureExportPath = path;
@@ -2285,14 +2285,19 @@ class UITrait extends iron.Trait {
UVUtil.trianglemap = null;
UVUtil.trianglemapCached = false;
}
ui.combo(bitsHandle, ["8bit", "16bit"], "Color", true);
ui.combo(bitsHandle, ["8bit", "16bit", "32bit"], "Color", true);
if (bitsHandle.changed) {
iron.App.notifyOnRender(Layers.setLayerBits);
}
ui.row([1/2, 1/2]);
formatType = ui.combo(Id.handle({position: formatType}), ["jpg", "png"], "Format", true);
ui.enabled = formatType == 0;
if (bitsHandle.position == 0) {
formatType = ui.combo(Id.handle({position: formatType}), ["jpg", "png"], "Format", true);
}
else {
ui.combo(Id.handle({position: formatType}), ["exr"], "Format", true);
}
ui.enabled = formatType == 0 && bitsHandle.position == 0;
formatQuality = ui.slider(Id.handle({value: formatQuality}), "Quality", 0.0, 100.0, true, 1);
ui.enabled = true;
ui.row([1/2, 1/2]);