mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-14 16:14:38 +00:00
Updates ImageAsset usage to utilize AssetRef, and standardizes the setter/getter functions and naming conventions, as well as the ability to use and bind named targets.
This commit is contained in:
parent
a858d8624e
commit
34e3f78a22
82 changed files with 1451 additions and 951 deletions
|
|
@ -129,7 +129,15 @@ function MaterialAsset::generatePreviewImage(%this, %previewButton, %forceRegene
|
|||
{
|
||||
if(isObject(%this.materialDefinitionName))
|
||||
{
|
||||
if(compareFileTimes(%this.materialDefinitionName.getDiffuseMap(0), %previewFilePath) == 1 ||
|
||||
%diffuseMapFile = "";
|
||||
%diffuseMapAssetId = %this.materialDefinitionName.getDiffuseMapAsset(0);
|
||||
if(AssetDatabase.isDeclaredAsset(%diffuseMapAssetId))
|
||||
{
|
||||
%diffuseMapFile = AssetDatabase.acquireAsset(%diffuseMapAssetId).getImagePath();
|
||||
AssetDatabase.releaseAsset(%diffuseMapAssetId);
|
||||
}
|
||||
|
||||
if(compareFileTimes(%diffuseMapFile, %previewFilePath) == 1 ||
|
||||
compareFileTimes(%this.materialDefinitionName.getFilename(), %previewFilePath) == 1)
|
||||
%generatePreview = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -120,7 +120,15 @@ function TerrainAssetMaterial::generatePreviewImage(%this, %previewButton, %forc
|
|||
{
|
||||
if(isObject(%this.materialDefinitionName))
|
||||
{
|
||||
if(compareFileTimes(%this.materialDefinitionName.getDiffuseMap(), %previewFilePath) == 1 ||
|
||||
%diffuseMapFile = "";
|
||||
%diffuseMapAssetId = %this.materialDefinitionName.getDiffuseMapAsset();
|
||||
if(AssetDatabase.isDeclaredAsset(%diffuseMapAssetId))
|
||||
{
|
||||
%diffuseMapFile = AssetDatabase.acquireAsset(%diffuseMapAssetId).getImagePath();
|
||||
AssetDatabase.releaseAsset(%diffuseMapAssetId);
|
||||
}
|
||||
|
||||
if(compareFileTimes(%diffuseMapFile, %previewFilePath) == 1 ||
|
||||
compareFileTimes(%this.materialDefinitionName.getFilename(), %previewFilePath) == 1)
|
||||
%generatePreview = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ function ConvexEditorGui::onWake( %this )
|
|||
{
|
||||
convexEditorToolbar-->gridSnapSizeEdit.setText(%this.getGridSnapSize());
|
||||
|
||||
if(ConvexEditorOptionsWindow-->matPreviewBtn.getBitmap() $= "")
|
||||
if(ConvexEditorOptionsWindow-->matPreviewBtn.getBitmapAsset() $= "")
|
||||
{
|
||||
//no active material, so set one
|
||||
ConvexEditorOptionsWindow-->matPreviewBtn.setText("");
|
||||
|
|
@ -38,7 +38,7 @@ function ConvexEditorGui::onWake( %this )
|
|||
%mat = %matName;
|
||||
}
|
||||
|
||||
ConvexEditorOptionsWindow-->matPreviewBtn.bitmapAsset = getAssetPreviewImage(%mat.getDiffuseMap(0));
|
||||
ConvexEditorOptionsWindow-->matPreviewBtn.setBitmap(getAssetPreviewImage(%mat.getDiffuseMapAsset(0)));
|
||||
|
||||
ConvexEditorOptionsWindow.activeMaterial = %mat;
|
||||
}
|
||||
|
|
@ -82,8 +82,6 @@ function ConvexEditorGui::createConvexBox( %this )
|
|||
|
||||
function ConvexEditorGui::onSelectionChanged( %this, %shape, %face )
|
||||
{
|
||||
//echo( "onSelectionChanged: " @ %shape SPC %face );
|
||||
|
||||
ConvexEditorSplitFaceBtn.setActive( false );
|
||||
ConvexEditorSplitFaceBtn.ToolTip = "Split selected face [Disabled]" NL "Use Ctrl + Rotate instead for more control";
|
||||
ConvexEditorDeleteFaceBtn.setActive( false );
|
||||
|
|
@ -100,7 +98,7 @@ function ConvexEditorGui::onSelectionChanged( %this, %shape, %face )
|
|||
|
||||
ConvexEditorOptionsWindow-->defMatPreviewBtn.setText("");
|
||||
%shapeMat = %shape.getMaterial();
|
||||
ConvexEditorOptionsWindow-->defMatPreviewBtn.bitmapAsset = getAssetPreviewImage(%shapeMat.getDiffuseMap(0));
|
||||
ConvexEditorOptionsWindow-->defMatPreviewBtn.setBitmap(getAssetPreviewImage(%shapeMat.getDiffuseMapAsset(0)));
|
||||
|
||||
ConvexEditorOptionsWindow.activeShape = %shape;
|
||||
|
||||
|
|
@ -205,7 +203,7 @@ function ConvexEditorMaterialLiftBtn::onClick(%this)
|
|||
{
|
||||
%mat = ConvexEditorGui.getSelectedFaceMaterial();
|
||||
ConvexEditorOptionsWindow.activeMaterial = %mat;
|
||||
ConvexEditorOptionsWindow-->matPreviewBtn.setBitmap(getAssetPreviewImage(%mat.getDiffuseMap(0)));
|
||||
ConvexEditorOptionsWindow-->matPreviewBtn.setBitmap(getAssetPreviewImage(%mat.getDiffuseMapAsset(0)));
|
||||
}
|
||||
|
||||
function ConvexEditorMaterialResetBtn::onClick(%this)
|
||||
|
|
@ -248,18 +246,9 @@ function ConvexEditorDefaultMaterialBtn::gotMaterialName(%this, %name)
|
|||
//eval(%this.object @ "." @ %this.targetField @ " = " @ %name @ ";");
|
||||
//%this.object.changeMaterial(getTrailingNumber(%this.targetField), %name);
|
||||
//%this.object.inspectorApply();
|
||||
%diffusemap = %materialAsset.materialDefinitionName.getDiffuseMap(0);
|
||||
if(%diffusemap $= "")
|
||||
{
|
||||
%diffuseAsset = %materialAsset.materialDefinitionName.getDiffuseMapAsset(0);
|
||||
if(%diffuseAsset !$= "")
|
||||
{
|
||||
%diffuseAssetDef = AssetDatabase.acquireAsset(%diffuseAsset);
|
||||
%diffusemap = %diffuseAssetDef.getImagePath();
|
||||
}
|
||||
}
|
||||
%diffuseAsset = %materialAsset.materialDefinitionName.getDiffuseMapAsset(0);
|
||||
|
||||
ConvexEditorOptionsWindow-->defMatPreviewBtn.bitmapAsset = getAssetPreviewImage(%diffusemap);
|
||||
ConvexEditorOptionsWindow-->defMatPreviewBtn.setBitmap(getAssetPreviewImage(%diffuseAsset));
|
||||
|
||||
ConvexEditorOptionsWindow.activeShape.setMaterial(%name);
|
||||
|
||||
|
|
|
|||
|
|
@ -608,7 +608,7 @@ function DecalEditorGui::updateDecalPreview( %this, %material )
|
|||
{
|
||||
%matAsset = AssetDatabase.acquireAsset(%material);
|
||||
|
||||
%previewImage = %matAsset.materialDefinitionName.getDiffuseMap(0);
|
||||
%previewImage = %matAsset.materialDefinitionName.getDiffuseMapAsset(0);
|
||||
//AssetDatabase.releaseAsset(%material);
|
||||
}
|
||||
else if(AssetDatabase.getAssetType(%material) $= "ImageAsset")
|
||||
|
|
@ -644,7 +644,7 @@ function DecalEditorGui::updateInstancePreview( %this, %material )
|
|||
{
|
||||
%matAsset = AssetDatabase.acquireAsset(%material);
|
||||
|
||||
%previewImage = %matAsset.materialDefinitionName.getDiffuseMap(0);
|
||||
%previewImage = %matAsset.materialDefinitionName.getDiffuseMapAsset(0);
|
||||
}
|
||||
else if(AssetDatabase.getAssetType(%material) $= "ImageAsset")
|
||||
{
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ function MaterialEditorGui::establishMaterials(%this)
|
|||
singleton CustomMaterial( materialEd_justAlphaMaterial )
|
||||
{
|
||||
mapTo = "matEd_mappedMatB";
|
||||
texture[0] = materialEd_previewMaterial.getdiffuseMap(0);
|
||||
texture[0] = materialEd_previewMaterial.getDiffuseMapAsset(0);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -650,9 +650,6 @@ function MaterialEditorGui::setActiveMaterial( %this, %material )
|
|||
};
|
||||
}
|
||||
|
||||
// Converts the texture files into absolute paths.
|
||||
MaterialEditorGui.convertTextureFields();
|
||||
|
||||
// If we're allowing for name changes, make sure to save the name seperately
|
||||
%this.originalName = MaterialEditorGui.currentMaterial.name;
|
||||
|
||||
|
|
@ -733,50 +730,6 @@ function MaterialEditorGui::setMaterialDirty(%this)
|
|||
matEd_PersistMan.setDirty(MaterialEditorGui.currentMaterial, MaterialEditorGui.defaultMaterialFile);
|
||||
}
|
||||
|
||||
function MaterialEditorGui::convertTextureFields(%this)
|
||||
{
|
||||
// Find the absolute paths for the texture filenames so that
|
||||
// we can properly wire up the preview materials and controls.
|
||||
|
||||
%this.convertMaterialTextureField(MaterialEditorGui.currentMaterial, "DiffuseMap");
|
||||
%this.convertMaterialTextureField(MaterialEditorGui.currentMaterial, "NormalMap");
|
||||
%this.convertMaterialTextureField(MaterialEditorGui.currentMaterial, "OverlayMap");
|
||||
%this.convertMaterialTextureField(MaterialEditorGui.currentMaterial, "DetailMap");
|
||||
%this.convertMaterialTextureField(MaterialEditorGui.currentMaterial, "LightMap");
|
||||
%this.convertMaterialTextureField(MaterialEditorGui.currentMaterial, "ToneMap");
|
||||
%this.convertMaterialTextureField(MaterialEditorGui.currentMaterial, "ORMConfigMap");
|
||||
%this.convertMaterialTextureField(MaterialEditorGui.currentMaterial, "RoughMap");
|
||||
%this.convertMaterialTextureField(MaterialEditorGui.currentMaterial, "AOMap");
|
||||
%this.convertMaterialTextureField(MaterialEditorGui.currentMaterial, "MetalMap");
|
||||
%this.convertMaterialTextureField(MaterialEditorGui.currentMaterial, "GlowMap");
|
||||
}
|
||||
|
||||
function MaterialEditorGui::convertMaterialTextureField(%this, %material, %mapName)
|
||||
{
|
||||
for(%index = 0; %index < 4; %index++)
|
||||
{
|
||||
%mapFile = %material.call("get" @ %mapName, %index);
|
||||
if(%mapFile !$= "")
|
||||
{
|
||||
if(isFile(%mapFile))
|
||||
{
|
||||
//see if we can't go finding it
|
||||
%mapFile = MaterialEditorGui.searchForTexture(MaterialEditorGui.currentMaterial, %mapFile);
|
||||
MaterialEditorGui.currentMaterial.call("set" @ %mapName, %mapFile, %index);
|
||||
}
|
||||
else
|
||||
{
|
||||
%firstChar = getSubStr( %mapFile, 0, 1 );
|
||||
if(%firstChar $= "#" || %firstChar $= "$" ) // we are a named target
|
||||
{
|
||||
%assetPtr = %material.call("get" @ %mapName @ "Asset", %index);
|
||||
MaterialEditorGui.currentMaterial.call("set" @ %mapName, %assetPtr, %index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// still needs to be optimized further
|
||||
function MaterialEditorGui::searchForTexture(%this,%material, %texture)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ function PE_ParticleEditor::loadNewParticle( %this, %particle )
|
|||
%this.currParticle = %current;
|
||||
|
||||
error("PE_ParticleEditor::loadNewParticle() - Loading particle: " @ %current.getName());
|
||||
error("Particle TextureName: " @ %current.getTexture());
|
||||
error("Particle TextureName: " @ %current.getTextureAsset());
|
||||
|
||||
error("ReloadingParticle...");
|
||||
%current.reload();
|
||||
|
|
@ -116,8 +116,8 @@ function PE_ParticleEditor::loadNewParticle( %this, %particle )
|
|||
PE_ParticleEditor_NotDirtyParticle.assignFieldsFrom( %current );
|
||||
PE_ParticleEditor_NotDirtyParticle.originalName = %current.getName();
|
||||
|
||||
error("Post duplicate Particle TextureName: " @ %current.getTexture());
|
||||
error("Post duplicate PE_ParticleEditor_NotDirtyParticle TextureName: " @ PE_ParticleEditor_NotDirtyParticle.getTexture());
|
||||
error("Post duplicate Particle TextureName: " @ %current.getTextureAsset());
|
||||
error("Post duplicate PE_ParticleEditor_NotDirtyParticle TextureName: " @ PE_ParticleEditor_NotDirtyParticle.getTextureAsset());
|
||||
|
||||
%this.guiSync();
|
||||
%this.setNotDirty();
|
||||
|
|
|
|||
|
|
@ -784,8 +784,8 @@ T3Dpre4ProjectImporter::genProcessor("Sun", "coronaMaterial coronaMaterialAsset"
|
|||
T3Dpre4ProjectImporter::genProcessor("VolumetricFog", "shape ShapeAsset texture textureAsset");
|
||||
T3Dpre4ProjectImporter::genProcessor("WaterObject", "rippleTex rippleTexAsset foamTex foamTexAsset depthGradientTex depthGradientTexAsset");
|
||||
T3Dpre4ProjectImporter::genProcessor("ConvexShape", "material materialAsset");
|
||||
T3Dpre4ProjectImporter::genProcessor("RenderMesh", "material materialAsset");
|
||||
T3Dpre4ProjectImporter::genProcessor("RenderShape", "shape shapeAsset");
|
||||
T3Dpre4ProjectImporter::genProcessor("RenderMeshExample", "material materialAsset");
|
||||
T3Dpre4ProjectImporter::genProcessor("RenderShapeExample", "shape shapeAsset");
|
||||
T3Dpre4ProjectImporter::genProcessor("GroundCover", "material materialAsset shape shapeAsset shapeFilename shapeAsset");
|
||||
T3Dpre4ProjectImporter::genProcessor("GroundPlane", "material materialAsset");
|
||||
T3Dpre4ProjectImporter::genProcessor("LevelInfo", "accuTexture accuTextureAsset");
|
||||
|
|
@ -856,6 +856,7 @@ T3Dpre4ProjectImporter::genProcessor("GuiMissionArea", "handleBitmap handleBitma
|
|||
T3Dpre4ProjectImporter::genProcessor("WorldEditor", "selectHandle selectHandleAsset defaultHandle defaultHandleAsset lockedHandle lockedHandleAsset");
|
||||
T3Dpre4ProjectImporter::genProcessor("GuiControlProfile", "bitmap bitmapAsset");
|
||||
T3Dpre4ProjectImporter::genProcessor("GuiMLTextCtrl", "deniedSound deniedSoundAsset");
|
||||
T3Dpre4ProjectImporter::genProcessor("GuiObjectView", "shapeName shapeAsset shapeFile shapeAsset model modelAsset mountedShapeName mountedShapeAsset mountedModelName mountedModelAsset");
|
||||
|
||||
function T3Dpre4ProjectImporter::processGuiBitmapButtonCtrlLine(%this, %line)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ function TerrainEditor::setPaintMaterial( %this, %matIndex, %terrainMat )
|
|||
ETerrainMaterialSelected.selectedMatIndex = %matIndex;
|
||||
ETerrainMaterialSelected.selectedMat = %terrainMat;
|
||||
|
||||
ETerrainMaterialSelected.setBitmap(getAssetPreviewImage(%terrainMat.getDiffuseMap()));
|
||||
ETerrainMaterialSelected.setBitmap(getAssetPreviewImage(%terrainMat.getDiffuseMapAsset()));
|
||||
|
||||
ETerrainMaterialSelectedEdit.Visible = isObject(%terrainMat);
|
||||
TerrainTextureText.text = %terrainMat.getInternalName();
|
||||
|
|
@ -178,7 +178,7 @@ function EPainter::updateLayers( %this, %matIndex )
|
|||
*/
|
||||
|
||||
%ctrl.setText( %matInternalName );
|
||||
%ctrl.setBitmap( getAssetPreviewImage(%mat.getDiffuseMap()) );
|
||||
%ctrl.setBitmap( getAssetPreviewImage(%mat.getDiffuseMapAsset()) );
|
||||
|
||||
%tooltip = %matInternalName;
|
||||
if(%i < 9)
|
||||
|
|
|
|||
|
|
@ -381,8 +381,8 @@ function TerrainMaterialDlg::activateMaterialCtrls( %this, %active )
|
|||
%parent.getObject( %i ).setActive( %active );
|
||||
}
|
||||
|
||||
%detailz = %this-->texDetailMap.getBitmap();
|
||||
if(%this-->texDetailMap.getBitmap() $= "" || %this-->texDetailMap.getBitmap() $= $TerrainMaterialEditor::emptyMaterialImage)
|
||||
%detailz = %this-->texDetailMap.getBitmapAsset();
|
||||
if(%detailz $= "" || %detailz $= $TerrainMaterialEditor::emptyMaterialImage)
|
||||
{
|
||||
NormalMapContainer.callOnChildren("setActive", false);
|
||||
ORMConfigMapContainer.callOnChildren("setActive", false);
|
||||
|
|
@ -432,34 +432,34 @@ function TerrainMaterialDlg::setActiveMaterial( %this, %mat )
|
|||
%this-->matNameCtrl.setText( %mat.internalName );
|
||||
|
||||
//
|
||||
%imgPath = %mat.getDiffuseMap();
|
||||
%imgPathText = %imgPath !$= "" && %imgPath !$= $TerrainMaterialEditor::emptyMaterialImage ? %mat.getDiffuseMapAsset() : "None";
|
||||
%imgAssetId = %mat.getDiffuseMapAsset();
|
||||
%imgPathText = %imgAssetId !$= "" && %imgAssetId !$= $TerrainMaterialEditor::emptyMaterialImage ? %imgAssetId : "None";
|
||||
%this-->diffuseMapAssetId.setText( %imgPathText );
|
||||
%this-->texDiffuseMap.setBitmap( getAssetPreviewImage(%imgPath) );
|
||||
%this-->texDiffuseMap.setBitmap( getAssetPreviewImage(%imgAssetId) );
|
||||
|
||||
//
|
||||
%imgPath = %mat.getNormalMap();
|
||||
%imgPathText = %imgPath !$= "" && %imgPath !$= $TerrainMaterialEditor::emptyMaterialImage ? %mat.getNormalMapAsset() : "None";
|
||||
%imgAssetId = %mat.getNormalMapAsset();
|
||||
%imgPathText = %imgAssetId !$= "" && %imgAssetId !$= $TerrainMaterialEditor::emptyMaterialImage ? %imgAssetId : "None";
|
||||
%this-->normalMapAssetId.setText( %imgPathText );
|
||||
%this-->texNormalMap.setBitmap( getAssetPreviewImage(%imgPath) );
|
||||
%this-->texNormalMap.setBitmap( getAssetPreviewImage(%imgAssetId) );
|
||||
|
||||
//
|
||||
%imgPath = %mat.getORMConfigMap();
|
||||
%imgPathText = %imgPath !$= "" && %imgPath !$= $TerrainMaterialEditor::emptyMaterialImage ? %mat.getORMConfigMapAsset() : "None";
|
||||
%imgAssetId = %mat.getORMConfigMapAsset();
|
||||
%imgPathText = %imgAssetId !$= "" && %imgAssetId !$= $TerrainMaterialEditor::emptyMaterialImage ? %imgAssetId : "None";
|
||||
%this-->ORMConfigMapAssetId.setText( %imgPathText );
|
||||
%this-->texORMConfigMap.setBitmap( getAssetPreviewImage(%imgPath) );
|
||||
|
||||
%this-->texORMConfigMap.setBitmap( getAssetPreviewImage(%imgAssetId) );
|
||||
|
||||
//
|
||||
%imgPath = %mat.getDetailMap();
|
||||
%imgPathText = %imgPath !$= "" && %imgPath !$= $TerrainMaterialEditor::emptyMaterialImage ? %mat.getDetailMapAsset() : "None";
|
||||
%imgAssetId = %mat.getDetailMapAsset();
|
||||
%imgPathText = %imgAssetId !$= "" && %imgAssetId !$= $TerrainMaterialEditor::emptyMaterialImage ? %imgAssetId : "None";
|
||||
%this-->detailMapAssetId.setText( %imgPathText );
|
||||
%this-->texDetailMap.setBitmap( getAssetPreviewImage(%imgPath) );
|
||||
|
||||
%this-->texDetailMap.setBitmap( getAssetPreviewImage(%imgAssetId) );
|
||||
|
||||
//
|
||||
%imgPath = %mat.getMacroMap();
|
||||
%imgPathText = %imgPath !$= "" && %imgPath !$= $TerrainMaterialEditor::emptyMaterialImage ? %mat.getMacroMapAsset() : "None";
|
||||
%imgAssetId = %mat.getMacroMapAsset();
|
||||
%imgPathText = %imgAssetId !$= "" && %imgAssetId !$= $TerrainMaterialEditor::emptyMaterialImage ? %imgAssetId : "None";
|
||||
%this-->macroMapAssetId.setText( %imgPathText );
|
||||
%this-->texMacroMap.setBitmap( getAssetPreviewImage(%imgPath) );
|
||||
%this-->texMacroMap.setBitmap( getAssetPreviewImage(%imgAssetId) );
|
||||
|
||||
//
|
||||
%this-->detSizeCtrl.setText( %mat.detailSize );
|
||||
|
|
@ -714,11 +714,11 @@ function TerrainMaterialDlg::saveDirtyMaterial( %this, %materialAssetId )
|
|||
// return.
|
||||
|
||||
if ( %mat.internalName $= %newName &&
|
||||
%mat.getDiffuseMap() $= %newDiffuse &&
|
||||
%mat.getNormalMap() $= %newNormal &&
|
||||
%mat.getDetailMap() $= %newDetail &&
|
||||
%mat.getORMConfigMap() $= %newormConfig &&
|
||||
%mat.getMacroMap() $= %newMacro &&
|
||||
%mat.getDiffuseMapAsset() $= %newDiffuse &&
|
||||
%mat.getNormalMapAsset() $= %newNormal &&
|
||||
%mat.getDetailMapAsset() $= %newDetail &&
|
||||
%mat.getORMConfigMapAsset() $= %newormConfig &&
|
||||
%mat.getMacroMapAsset() $= %newMacro &&
|
||||
%mat.detailSize == %detailSize &&
|
||||
%mat.diffuseSize == %diffuseSize &&
|
||||
%mat.detailStrength == %detailStrength &&
|
||||
|
|
@ -852,11 +852,11 @@ function TerrainMaterialDlg::snapshotMaterials( %this )
|
|||
parentGroup = %group;
|
||||
material = %mat;
|
||||
internalName = %mat.internalName;
|
||||
diffuseMap = %mat.getDiffuseMap();
|
||||
normalMap = %mat.getNormalMap();
|
||||
ormConfigMap = %mat.getORMConfigMap();
|
||||
detailMap = %mat.getDetailMap();
|
||||
macroMap = %mat.getMacroMap();
|
||||
diffuseMap = %mat.getDiffuseMapAsset();
|
||||
normalMap = %mat.getNormalMapAsset();
|
||||
ormConfigMap = %mat.getORMConfigMapAsset();
|
||||
detailMap = %mat.getDetailMapAsset();
|
||||
macroMap = %mat.getMacroMapAsset();
|
||||
detailSize = %mat.detailSize;
|
||||
diffuseSize = %mat.diffuseSize;
|
||||
detailStrength = %mat.detailStrength;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue