Urho3D/bin/Data/Scripts/Editor/EditorParticleEffect.as
Neal_Nicdao b1c3ce30ec
Added new EmitterTypes
* Added SphereVolume, Cylinder, and Ring enum with calculations
 * Modified EditorParticle to incorporate new emitter shapes
2018-11-25 21:25:58 +08:00

1778 lines
63 KiB
ActionScript

// Urho3D material editor
Window@ particleEffectWindow;
ParticleEffect@ editParticleEffect;
XMLFile@ oldParticleEffectState;
bool inParticleEffectRefresh = false;
View3D@ particleEffectPreview;
Camera@ particlePreviewCamera;
Scene@ particlePreviewScene;
Node@ particleEffectPreviewNode;
Node@ particleEffectPreviewGizmoNode;
Node@ particleEffectPreviewGridNode;
CustomGeometry@ particleEffectPreviewGrid;
Node@ particlePreviewCameraNode;
Node@ particlePreviewLightNode;
Light@ particlePreviewLight;
ParticleEmitter@ particleEffectEmitter;
float particleResetTimer;
bool showParticlePreviewAxes = true;
Vector3 particleViewCamDir;
Vector3 particleViewCamRot;
float particleViewCamDist;
float gizmoOffset = 0.1f;
float gizmoOffsetX;
float gizmoOffsetY;
void CreateParticleEffectEditor()
{
if (particleEffectWindow !is null)
return;
particleEffectWindow = LoadEditorUI("UI/EditorParticleEffectWindow.xml");
ui.root.AddChild(particleEffectWindow);
particleEffectWindow.opacity = uiMaxOpacity;
InitParticleEffectPreview();
InitParticleEffectBasicAttributes();
RefreshParticleEffectEditor();
int width = Min(ui.root.width - 60, 800);
int height = Min(ui.root.height - 60, 600);
particleEffectWindow.SetSize(width, height);
CenterDialog(particleEffectWindow);
HideParticleEffectEditor();
SubscribeToEvent(particleEffectWindow.GetChild("NewButton", true), "Released", "NewParticleEffect");
SubscribeToEvent(particleEffectWindow.GetChild("RevertButton", true), "Released", "RevertParticleEffect");
SubscribeToEvent(particleEffectWindow.GetChild("SaveButton", true), "Released", "SaveParticleEffect");
SubscribeToEvent(particleEffectWindow.GetChild("SaveAsButton", true), "Released", "SaveParticleEffectAs");
SubscribeToEvent(particleEffectWindow.GetChild("CloseButton", true), "Released", "HideParticleEffectEditor");
SubscribeToEvent(particleEffectWindow.GetChild("NewColorFrame", true), "Released", "EditParticleEffectColorFrameNew");
SubscribeToEvent(particleEffectWindow.GetChild("RemoveColorFrame", true), "Released", "EditParticleEffectColorFrameRemove");
SubscribeToEvent(particleEffectWindow.GetChild("ColorFrameSort", true), "Released", "EditParticleEffectColorFrameSort");
SubscribeToEvent(particleEffectWindow.GetChild("NewTextureFrame", true), "Released", "EditParticleEffectTextureFrameNew");
SubscribeToEvent(particleEffectWindow.GetChild("RemoveTextureFrame", true), "Released", "EditParticleEffectTextureFrameRemove");
SubscribeToEvent(particleEffectWindow.GetChild("TextureFrameSort", true), "Released", "EditParticleEffectTextureFrameSort");
SubscribeToEvent(particleEffectWindow.GetChild("ConstantForceX", true), "TextChanged", "EditParticleEffectConstantForce");
SubscribeToEvent(particleEffectWindow.GetChild("ConstantForceY", true), "TextChanged", "EditParticleEffectConstantForce");
SubscribeToEvent(particleEffectWindow.GetChild("ConstantForceZ", true), "TextChanged", "EditParticleEffectConstantForce");
SubscribeToEvent(particleEffectWindow.GetChild("DirectionMinX", true), "TextChanged", "EditParticleEffectDirection");
SubscribeToEvent(particleEffectWindow.GetChild("DirectionMinY", true), "TextChanged", "EditParticleEffectDirection");
SubscribeToEvent(particleEffectWindow.GetChild("DirectionMinZ", true), "TextChanged", "EditParticleEffectDirection");
SubscribeToEvent(particleEffectWindow.GetChild("DirectionMaxX", true), "TextChanged", "EditParticleEffectDirection");
SubscribeToEvent(particleEffectWindow.GetChild("DirectionMaxY", true), "TextChanged", "EditParticleEffectDirection");
SubscribeToEvent(particleEffectWindow.GetChild("DirectionMaxZ", true), "TextChanged", "EditParticleEffectDirection");
SubscribeToEvent(particleEffectWindow.GetChild("DampingForce", true), "TextChanged", "EditParticleEffectDampingForce");
SubscribeToEvent(particleEffectWindow.GetChild("ActiveTime", true), "TextChanged", "EditParticleEffectActiveTime");
SubscribeToEvent(particleEffectWindow.GetChild("InactiveTime", true), "TextChanged", "EditParticleEffectInactiveTime");
SubscribeToEvent(particleEffectWindow.GetChild("ParticleSizeMinX", true), "TextChanged", "EditParticleEffectParticleSize");
SubscribeToEvent(particleEffectWindow.GetChild("ParticleSizeMinY", true), "TextChanged", "EditParticleEffectParticleSize");
SubscribeToEvent(particleEffectWindow.GetChild("ParticleSizeMaxX", true), "TextChanged", "EditParticleEffectParticleSize");
SubscribeToEvent(particleEffectWindow.GetChild("ParticleSizeMaxY", true), "TextChanged", "EditParticleEffectParticleSize");
SubscribeToEvent(particleEffectWindow.GetChild("TimeToLiveMin", true), "TextChanged", "EditParticleEffectTimeToLive");
SubscribeToEvent(particleEffectWindow.GetChild("TimeToLiveMax", true), "TextChanged", "EditParticleEffectTimeToLive");
SubscribeToEvent(particleEffectWindow.GetChild("VelocityMin", true), "TextChanged", "EditParticleEffectVelocity");
SubscribeToEvent(particleEffectWindow.GetChild("VelocityMax", true), "TextChanged", "EditParticleEffectVelocity");
SubscribeToEvent(particleEffectWindow.GetChild("RotationMin", true), "TextChanged", "EditParticleEffectRotation");
SubscribeToEvent(particleEffectWindow.GetChild("RotationMax", true), "TextChanged", "EditParticleEffectRotation");
SubscribeToEvent(particleEffectWindow.GetChild("RotationSpeedMin", true), "TextChanged", "EditParticleEffectRotationSpeed");
SubscribeToEvent(particleEffectWindow.GetChild("RotationSpeedMax", true), "TextChanged", "EditParticleEffectRotationSpeed");
SubscribeToEvent(particleEffectWindow.GetChild("SizeAdd", true), "TextChanged", "EditParticleEffectSizeAdd");
SubscribeToEvent(particleEffectWindow.GetChild("SizeMultiply", true), "TextChanged", "EditParticleEffectSizeMultiply");
SubscribeToEvent(particleEffectWindow.GetChild("AnimationLodBias", true), "TextChanged", "EditParticleEffectAnimationLodBias");
SubscribeToEvent(particleEffectWindow.GetChild("NumParticles", true), "TextChanged", "EditParticleEffectNumParticles");
SubscribeToEvent(particleEffectWindow.GetChild("EmitterSizeX", true), "TextChanged", "EditParticleEffectEmitterSize");
SubscribeToEvent(particleEffectWindow.GetChild("EmitterSizeY", true), "TextChanged", "EditParticleEffectEmitterSize");
SubscribeToEvent(particleEffectWindow.GetChild("EmitterSizeZ", true), "TextChanged", "EditParticleEffectEmitterSize");
SubscribeToEvent(particleEffectWindow.GetChild("EmissionRateMin", true), "TextChanged", "EditParticleEffectEmissionRate");
SubscribeToEvent(particleEffectWindow.GetChild("EmissionRateMax", true), "TextChanged", "EditParticleEffectEmissionRate");
SubscribeToEvent(particleEffectWindow.GetChild("ConstantForceX", true), "TextFinished", "EditParticleEffectConstantForce");
SubscribeToEvent(particleEffectWindow.GetChild("ConstantForceY", true), "TextFinished", "EditParticleEffectConstantForce");
SubscribeToEvent(particleEffectWindow.GetChild("ConstantForceZ", true), "TextFinished", "EditParticleEffectConstantForce");
SubscribeToEvent(particleEffectWindow.GetChild("DirectionMinX", true), "TextFinished", "EditParticleEffectDirection");
SubscribeToEvent(particleEffectWindow.GetChild("DirectionMinY", true), "TextFinished", "EditParticleEffectDirection");
SubscribeToEvent(particleEffectWindow.GetChild("DirectionMinZ", true), "TextFinished", "EditParticleEffectDirection");
SubscribeToEvent(particleEffectWindow.GetChild("DirectionMaxX", true), "TextFinished", "EditParticleEffectDirection");
SubscribeToEvent(particleEffectWindow.GetChild("DirectionMaxY", true), "TextFinished", "EditParticleEffectDirection");
SubscribeToEvent(particleEffectWindow.GetChild("DirectionMaxZ", true), "TextFinished", "EditParticleEffectDirection");
SubscribeToEvent(particleEffectWindow.GetChild("DampingForce", true), "TextFinished", "EditParticleEffectDampingForce");
SubscribeToEvent(particleEffectWindow.GetChild("ActiveTime", true), "TextFinished", "EditParticleEffectActiveTime");
SubscribeToEvent(particleEffectWindow.GetChild("InactiveTime", true), "TextFinished", "EditParticleEffectInactiveTime");
SubscribeToEvent(particleEffectWindow.GetChild("ParticleSizeMinX", true), "TextFinished", "EditParticleEffectParticleSize");
SubscribeToEvent(particleEffectWindow.GetChild("ParticleSizeMinY", true), "TextFinished", "EditParticleEffectParticleSize");
SubscribeToEvent(particleEffectWindow.GetChild("ParticleSizeMaxX", true), "TextFinished", "EditParticleEffectParticleSize");
SubscribeToEvent(particleEffectWindow.GetChild("ParticleSizeMaxY", true), "TextFinished", "EditParticleEffectParticleSize");
SubscribeToEvent(particleEffectWindow.GetChild("TimeToLiveMin", true), "TextFinished", "EditParticleEffectTimeToLive");
SubscribeToEvent(particleEffectWindow.GetChild("TimeToLiveMax", true), "TextFinished", "EditParticleEffectTimeToLive");
SubscribeToEvent(particleEffectWindow.GetChild("VelocityMin", true), "TextFinished", "EditParticleEffectVelocity");
SubscribeToEvent(particleEffectWindow.GetChild("VelocityMax", true), "TextFinished", "EditParticleEffectVelocity");
SubscribeToEvent(particleEffectWindow.GetChild("RotationMin", true), "TextFinished", "EditParticleEffectRotation");
SubscribeToEvent(particleEffectWindow.GetChild("RotationMax", true), "TextFinished", "EditParticleEffectRotation");
SubscribeToEvent(particleEffectWindow.GetChild("RotationSpeedMin", true), "TextFinished", "EditParticleEffectRotationSpeed");
SubscribeToEvent(particleEffectWindow.GetChild("RotationSpeedMax", true), "TextFinished", "EditParticleEffectRotationSpeed");
SubscribeToEvent(particleEffectWindow.GetChild("SizeAdd", true), "TextFinished", "EditParticleEffectSizeAdd");
SubscribeToEvent(particleEffectWindow.GetChild("SizeMultiply", true), "TextFinished", "EditParticleEffectSizeMultiply");
SubscribeToEvent(particleEffectWindow.GetChild("AnimationLodBias", true), "TextFinished", "EditParticleEffectAnimationLodBias");
SubscribeToEvent(particleEffectWindow.GetChild("NumParticles", true), "TextFinished", "EditParticleEffectNumParticles");
SubscribeToEvent(particleEffectWindow.GetChild("EmitterSizeX", true), "TextFinished", "EditParticleEffectEmitterSize");
SubscribeToEvent(particleEffectWindow.GetChild("EmitterSizeY", true), "TextFinished", "EditParticleEffectEmitterSize");
SubscribeToEvent(particleEffectWindow.GetChild("EmitterSizeZ", true), "TextFinished", "EditParticleEffectEmitterSize");
SubscribeToEvent(particleEffectWindow.GetChild("EmissionRateMin", true), "TextFinished", "EditParticleEffectEmissionRate");
SubscribeToEvent(particleEffectWindow.GetChild("EmissionRateMax", true), "TextFinished", "EditParticleEffectEmissionRate");
SubscribeToEvent(particleEffectWindow.GetChild("EmitterShape", true), "ItemSelected", "EditParticleEffectEmitterShape");
SubscribeToEvent(particleEffectWindow.GetChild("Scaled", true), "Toggled", "EditParticleEffectScaled");
SubscribeToEvent(particleEffectWindow.GetChild("Sorted", true), "Toggled", "EditParticleEffectSorted");
SubscribeToEvent(particleEffectWindow.GetChild("Relative", true), "Toggled", "EditParticleEffectRelative");
SubscribeToEvent(particleEffectWindow.GetChild("FixedScreenSize", true), "Toggled", "EditParticleEffectFixedScreenSize");
SubscribeToEvent(particleEffectWindow.GetChild("FaceCameraMode", true), "ItemSelected", "EditParticleEffectFaceCameraMode");
SubscribeToEvent(particleEffectWindow.GetChild("ResetViewport", true), "Released", "ParticleEffectResetViewport");
SubscribeToEvent(particleEffectWindow.GetChild("ShowGrid", true), "Toggled", "ParticleEffectShowGrid");
}
void SetGizmoPosition()
{
Vector3 screenPos = Vector3(gizmoOffsetX, gizmoOffsetY, 25.0);
Vector3 newPos = particlePreviewCamera.ScreenToWorldPoint(screenPos);
particleEffectPreviewGizmoNode.position = newPos;
}
void ResetCameraTransformation()
{
particlePreviewCameraNode.position = Vector3(0, 0, -5);
particlePreviewCameraNode.LookAt(Vector3(0, 0, 0));
particleViewCamDir = -particlePreviewCameraNode.position;
// Manually set initial rotation because eulerAngle always return 0 on first frame
particleViewCamRot = Vector3(0.0, 180.0, 0.0);
particleViewCamDist = particleViewCamDir.length;
particleViewCamDir.Normalize();
}
void ParticleEffectResetViewport(StringHash eventType, VariantMap& eventData)
{
ResetCameraTransformation();
SetGizmoPosition();
particleEffectPreview.QueueUpdate();
}
void ParticleEffectShowGrid(StringHash eventType, VariantMap& eventData)
{
CheckBox@ element = eventData["Element"].GetPtr();
showParticlePreviewAxes = element.checked;
particleEffectPreviewGridNode.enabled = showParticlePreviewAxes;
particleEffectPreview.QueueUpdate();
}
void EditParticleEffectColorFrameNew(StringHash eventType, VariantMap& eventData)
{
if (inParticleEffectRefresh)
return;
if (editParticleEffect is null)
return;
BeginParticleEffectEdit();
uint num = editParticleEffect.numColorFrames;
editParticleEffect.numColorFrames = num + 1;
RefreshParticleEffectColorFrames();
EndParticleEffectEdit();
}
void EditParticleEffectTextureFrameNew(StringHash eventType, VariantMap& eventData)
{
if (inParticleEffectRefresh)
return;
if (editParticleEffect is null)
return;
BeginParticleEffectEdit();
uint num = editParticleEffect.numTextureFrames;
editParticleEffect.numTextureFrames = num + 1;
RefreshParticleEffectTextureFrames();
EndParticleEffectEdit();
}
void EditParticleEffectColorFrameRemove(StringHash eventType, VariantMap& eventData)
{
if (inParticleEffectRefresh)
return;
if (editParticleEffect is null)
return;
ListView@ lv = particleEffectWindow.GetChild("ColorFrameListView", true);
if (lv !is null && lv.selection != M_MAX_UNSIGNED)
{
BeginParticleEffectEdit();
editParticleEffect.RemoveColorFrame(lv.selection);
RefreshParticleEffectColorFrames();
EndParticleEffectEdit();
}
}
void EditParticleEffectTextureFrameRemove(StringHash eventType, VariantMap& eventData)
{
if (inParticleEffectRefresh)
return;
if (editParticleEffect is null)
return;
ListView@ lv = particleEffectWindow.GetChild("TextureFrameListView", true);
if (lv !is null && lv.selection != M_MAX_UNSIGNED)
{
BeginParticleEffectEdit();
editParticleEffect.RemoveTextureFrame(lv.selection);
RefreshParticleEffectTextureFrames();
EndParticleEffectEdit();
}
}
void EditParticleEffectColorFrameSort(StringHash eventType, VariantMap& eventData)
{
RefreshParticleEffectColorFrames();
}
void EditParticleEffectTextureFrameSort(StringHash eventType, VariantMap& eventData)
{
RefreshParticleEffectTextureFrames();
}
void InitParticleEffectBasicAttributes()
{
CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("ConstantForceX", true)));
CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("ConstantForceY", true)));
CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("ConstantForceZ", true)));
CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("DirectionMinX", true)));
CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("DirectionMinY", true)));
CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("DirectionMinZ", true)));
CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("DirectionMaxX", true)));
CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("DirectionMaxY", true)));
CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("DirectionMaxZ", true)));
CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("DampingForce", true)));
CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("ActiveTime", true)));
CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("InactiveTime", true)));
CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("ParticleSizeMinX", true)));
CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("ParticleSizeMinY", true)));
CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("ParticleSizeMaxX", true)));
CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("ParticleSizeMaxY", true)));
CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("TimeToLiveMin", true)));
CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("TimeToLiveMax", true)));
CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("VelocityMin", true)));
CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("VelocityMax", true)));
CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("RotationMin", true)));
CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("RotationMax", true)));
CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("RotationSpeedMin", true)));
CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("RotationSpeedMax", true)));
CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("SizeAdd", true)));
CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("SizeMultiply", true)));
CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("AnimationLodBias", true)));
CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("NumParticles", true)));
CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("EmitterSizeX", true)));
CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("EmitterSizeY", true)));
CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("EmitterSizeZ", true)));
CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("EmissionRateMin", true)));
CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("EmissionRateMax", true)));
}
void EditParticleEffectConstantForce(StringHash eventType, VariantMap& eventData)
{
if (inParticleEffectRefresh)
return;
if (editParticleEffect is null)
return;
BeginParticleEffectEdit();
LineEdit@ element = eventData["Element"].GetPtr();
Vector3 v = editParticleEffect.constantForce;
if (element.name == "ConstantForceX")
editParticleEffect.constantForce = Vector3(element.text.ToFloat(), v.y, v.z);
if (element.name == "ConstantForceY")
editParticleEffect.constantForce = Vector3(v.x, element.text.ToFloat(), v.z);
if (element.name == "ConstantForceZ")
editParticleEffect.constantForce = Vector3(v.x, v.y, element.text.ToFloat());
EndParticleEffectEdit();
}
void EditParticleEffectDirection(StringHash eventType, VariantMap& eventData)
{
if (inParticleEffectRefresh)
return;
if (editParticleEffect is null)
return;
BeginParticleEffectEdit();
LineEdit@ element = eventData["Element"].GetPtr();
Vector3 vMin = editParticleEffect.minDirection;
Vector3 vMax = editParticleEffect.maxDirection;
if (element.name == "DirectionMinX")
editParticleEffect.minDirection = Vector3(element.text.ToFloat(), vMin.y, vMin.z);
if (element.name == "DirectionMinY")
editParticleEffect.minDirection = Vector3(vMin.x, element.text.ToFloat(), vMin.z);
if (element.name == "DirectionMinZ")
editParticleEffect.minDirection = Vector3(vMin.x, vMin.y, element.text.ToFloat());
if (element.name == "DirectionMaxX")
editParticleEffect.maxDirection = Vector3(element.text.ToFloat(), vMax.y, vMax.z);
if (element.name == "DirectionMaxY")
editParticleEffect.maxDirection = Vector3(vMax.x, element.text.ToFloat(), vMax.z);
if (element.name == "DirectionMaxZ")
editParticleEffect.maxDirection = Vector3(vMax.x, vMax.y, element.text.ToFloat());
EndParticleEffectEdit();
}
void EditParticleEffectDampingForce(StringHash eventType, VariantMap& eventData)
{
if (inParticleEffectRefresh)
return;
if (editParticleEffect is null)
return;
BeginParticleEffectEdit();
LineEdit@ element = eventData["Element"].GetPtr();
editParticleEffect.dampingForce = element.text.ToFloat();
EndParticleEffectEdit();
}
void EditParticleEffectActiveTime(StringHash eventType, VariantMap& eventData)
{
if (inParticleEffectRefresh)
return;
if (editParticleEffect is null)
return;
if (particleEffectEmitter is null)
return;
BeginParticleEffectEdit();
LineEdit@ element = eventData["Element"].GetPtr();
editParticleEffect.activeTime = element.text.ToFloat();
particleEffectEmitter.Reset();
EndParticleEffectEdit();
}
void EditParticleEffectInactiveTime(StringHash eventType, VariantMap& eventData)
{
if (inParticleEffectRefresh)
return;
if (editParticleEffect is null)
return;
if (particleEffectEmitter is null)
return;
BeginParticleEffectEdit();
LineEdit@ element = eventData["Element"].GetPtr();
editParticleEffect.inactiveTime = element.text.ToFloat();
particleEffectEmitter.Reset();
EndParticleEffectEdit();
}
void EditParticleEffectParticleSize(StringHash eventType, VariantMap& eventData)
{
if (inParticleEffectRefresh)
return;
if (editParticleEffect is null)
return;
BeginParticleEffectEdit();
LineEdit@ element = eventData["Element"].GetPtr();
Vector2 vMin = editParticleEffect.minParticleSize;
Vector2 vMax = editParticleEffect.maxParticleSize;
if (element.name == "ParticleSizeMinX")
editParticleEffect.minParticleSize = Vector2(element.text.ToFloat(), vMin.y);
if (element.name == "ParticleSizeMinY")
editParticleEffect.minParticleSize = Vector2(vMin.x, element.text.ToFloat());
if (element.name == "ParticleSizeMaxX")
editParticleEffect.maxParticleSize = Vector2(element.text.ToFloat(), vMax.y);
if (element.name == "ParticleSizeMaxY")
editParticleEffect.maxParticleSize = Vector2(vMax.x, element.text.ToFloat());
EndParticleEffectEdit();
}
void EditParticleEffectTimeToLive(StringHash eventType, VariantMap& eventData)
{
if (inParticleEffectRefresh)
return;
if (editParticleEffect is null)
return;
BeginParticleEffectEdit();
LineEdit@ element = eventData["Element"].GetPtr();
float vMin = editParticleEffect.minTimeToLive;
float vMax = editParticleEffect.maxTimeToLive;
if (element.name == "TimeToLiveMin")
editParticleEffect.minTimeToLive = element.text.ToFloat();
if (element.name == "TimeToLiveMax")
editParticleEffect.maxTimeToLive = element.text.ToFloat();
EndParticleEffectEdit();
}
void EditParticleEffectVelocity(StringHash eventType, VariantMap& eventData)
{
if (inParticleEffectRefresh)
return;
if (editParticleEffect is null)
return;
BeginParticleEffectEdit();
LineEdit@ element = eventData["Element"].GetPtr();
float vMin = editParticleEffect.minVelocity;
float vMax = editParticleEffect.maxVelocity;
if (element.name == "VelocityMin")
editParticleEffect.minVelocity = element.text.ToFloat();
if (element.name == "VelocityMax")
editParticleEffect.maxVelocity = element.text.ToFloat();
EndParticleEffectEdit();
}
void EditParticleEffectRotation(StringHash eventType, VariantMap& eventData)
{
if (inParticleEffectRefresh)
return;
if (editParticleEffect is null)
return;
BeginParticleEffectEdit();
LineEdit@ element = eventData["Element"].GetPtr();
float vMin = editParticleEffect.minRotation;
float vMax = editParticleEffect.maxRotation;
if (element.name == "RotationMin")
editParticleEffect.minRotation = element.text.ToFloat();
if (element.name == "RotationMax")
editParticleEffect.maxRotation = element.text.ToFloat();
EndParticleEffectEdit();
}
void EditParticleEffectRotationSpeed(StringHash eventType, VariantMap& eventData)
{
if (inParticleEffectRefresh)
return;
if (editParticleEffect is null)
return;
BeginParticleEffectEdit();
LineEdit@ element = eventData["Element"].GetPtr();
float vMin = editParticleEffect.minRotationSpeed;
float vMax = editParticleEffect.maxRotationSpeed;
if (element.name == "RotationSpeedMin")
editParticleEffect.minRotationSpeed = element.text.ToFloat();
if (element.name == "RotationSpeedMax")
editParticleEffect.maxRotationSpeed = element.text.ToFloat();
EndParticleEffectEdit();
}
void EditParticleEffectSizeAdd(StringHash eventType, VariantMap& eventData)
{
if (inParticleEffectRefresh)
return;
if (editParticleEffect is null)
return;
BeginParticleEffectEdit();
LineEdit@ element = eventData["Element"].GetPtr();
editParticleEffect.sizeAdd = element.text.ToFloat();
EndParticleEffectEdit();
}
void EditParticleEffectSizeMultiply(StringHash eventType, VariantMap& eventData)
{
if (inParticleEffectRefresh)
return;
if (editParticleEffect is null)
return;
BeginParticleEffectEdit();
LineEdit@ element = eventData["Element"].GetPtr();
editParticleEffect.sizeMul = element.text.ToFloat();
EndParticleEffectEdit();
}
void EditParticleEffectAnimationLodBias(StringHash eventType, VariantMap& eventData)
{
if (inParticleEffectRefresh)
return;
if (editParticleEffect is null)
return;
BeginParticleEffectEdit();
LineEdit@ element = eventData["Element"].GetPtr();
editParticleEffect.animationLodBias = element.text.ToFloat();
EndParticleEffectEdit();
}
void EditParticleEffectNumParticles(StringHash eventType, VariantMap& eventData)
{
if (inParticleEffectRefresh)
return;
if (editParticleEffect is null)
return;
if (particleEffectEmitter is null)
return;
BeginParticleEffectEdit();
LineEdit@ element = eventData["Element"].GetPtr();
editParticleEffect.numParticles = element.text.ToInt();
particleEffectEmitter.ApplyEffect();
EndParticleEffectEdit();
}
void EditParticleEffectEmitterSize(StringHash eventType, VariantMap& eventData)
{
if (inParticleEffectRefresh)
return;
if (editParticleEffect is null)
return;
BeginParticleEffectEdit();
LineEdit@ element = eventData["Element"].GetPtr();
Vector3 v = editParticleEffect.emitterSize;
if (element.name == "EmitterSizeX")
editParticleEffect.emitterSize = Vector3(element.text.ToFloat(), v.y, v.z);
if (element.name == "EmitterSizeY")
editParticleEffect.emitterSize = Vector3(v.x, element.text.ToFloat(), v.z);
if (element.name == "EmitterSizeZ")
editParticleEffect.emitterSize = Vector3(v.x, v.y, element.text.ToFloat());
EndParticleEffectEdit();
}
void EditParticleEffectEmissionRate(StringHash eventType, VariantMap& eventData)
{
if (inParticleEffectRefresh)
return;
if (editParticleEffect is null)
return;
BeginParticleEffectEdit();
LineEdit@ element = eventData["Element"].GetPtr();
if (element.name == "EmissionRateMin")
editParticleEffect.minEmissionRate = element.text.ToFloat();
if (element.name == "EmissionRateMax")
editParticleEffect.maxEmissionRate = element.text.ToFloat();
EndParticleEffectEdit();
}
void EditParticleEffectEmitterShape(StringHash eventType, VariantMap& eventData)
{
if (inParticleEffectRefresh)
return;
if (editParticleEffect is null)
return;
BeginParticleEffectEdit();
DropDownList@ element = eventData["Element"].GetPtr();
switch (element.selection)
{
case 0:
editParticleEffect.emitterType = EMITTER_SPHERE;
break;
case 1:
editParticleEffect.emitterType = EMITTER_BOX;
break;
case 2:
editParticleEffect.emitterType = EMITTER_SPHEREVOLUME;
break;
case 3:
editParticleEffect.emitterType = EMITTER_CYLINDER;
break;
case 4:
editParticleEffect.emitterType = EMITTER_RING;
break;
}
EndParticleEffectEdit();
}
void EditParticleEffectFaceCameraMode(StringHash eventType, VariantMap& eventData)
{
if (inParticleEffectRefresh)
return;
if (editParticleEffect is null)
return;
BeginParticleEffectEdit();
DropDownList@ element = eventData["Element"].GetPtr();
switch (element.selection)
{
case 0:
editParticleEffect.faceCameraMode = FC_NONE;
break;
case 1:
editParticleEffect.faceCameraMode = FC_ROTATE_XYZ;
break;
case 2:
editParticleEffect.faceCameraMode = FC_ROTATE_Y;
break;
case 3:
editParticleEffect.faceCameraMode = FC_LOOKAT_XYZ;
break;
case 4:
editParticleEffect.faceCameraMode = FC_LOOKAT_Y;
break;
case 5:
editParticleEffect.faceCameraMode = FC_DIRECTION;
break;
}
particleEffectEmitter.ApplyEffect();
EndParticleEffectEdit();
}
void EditParticleEffectMaterial(StringHash eventType, VariantMap& eventData)
{
if (inParticleEffectRefresh)
return;
if (editParticleEffect is null)
return;
if (particleEffectEmitter is null)
return;
LineEdit@ element = eventData["Element"].GetPtr();
Material@ res = cache.GetResource("Material", element.text);
if (res !is null)
{
BeginParticleEffectEdit();
editParticleEffect.material = res;
particleEffectEmitter.ApplyEffect();
EndParticleEffectEdit();
}
}
void PickEditParticleEffectMaterial(StringHash eventType, VariantMap& eventData)
{
@resourcePicker = GetResourcePicker(StringHash("Material"));
if (resourcePicker is null)
return;
String lastPath = resourcePicker.lastPath;
if (lastPath.empty)
lastPath = sceneResourcePath;
CreateFileSelector(localization.Get("Pick ") + resourcePicker.typeName, "OK", "Cancel", lastPath, resourcePicker.filters, resourcePicker.lastFilter, false);
SubscribeToEvent(uiFileSelector, "FileSelected", "PickEditParticleEffectMaterialDone");
}
void PickEditParticleEffectMaterialDone(StringHash eventType, VariantMap& eventData)
{
StoreResourcePickerPath();
CloseFileSelector();
if (!eventData["OK"].GetBool())
{
@resourcePicker = null;
return;
}
String resourceName = eventData["FileName"].GetString();
Resource@ res = GetPickedResource(resourceName);
if (res !is null && editParticleEffect !is null && particleEffectEmitter !is null)
{
editParticleEffect.material = res;
particleEffectEmitter.ApplyEffect();
RefreshParticleEffectMaterial();
}
@resourcePicker = null;
}
void EditParticleEffectScaled(StringHash eventType, VariantMap& eventData)
{
if (inParticleEffectRefresh)
return;
if (editParticleEffect is null)
return;
if (particleEffectEmitter is null)
return;
BeginParticleEffectEdit();
CheckBox@ element = eventData["Element"].GetPtr();
editParticleEffect.scaled = element.checked;
particleEffectEmitter.ApplyEffect();
EndParticleEffectEdit();
}
void EditParticleEffectSorted(StringHash eventType, VariantMap& eventData)
{
if (inParticleEffectRefresh)
return;
if (editParticleEffect is null)
return;
if (particleEffectEmitter is null)
return;
BeginParticleEffectEdit();
CheckBox@ element = eventData["Element"].GetPtr();
editParticleEffect.sorted = element.checked;
particleEffectEmitter.ApplyEffect();
EndParticleEffectEdit();
}
void EditParticleEffectRelative(StringHash eventType, VariantMap& eventData)
{
if (inParticleEffectRefresh)
return;
if (editParticleEffect is null)
return;
if (particleEffectEmitter is null)
return;
BeginParticleEffectEdit();
CheckBox@ element = eventData["Element"].GetPtr();
editParticleEffect.relative = element.checked;
particleEffectEmitter.ApplyEffect();
EndParticleEffectEdit();
}
void EditParticleEffectFixedScreenSize(StringHash eventType, VariantMap& eventData)
{
if (inParticleEffectRefresh)
return;
if (editParticleEffect is null)
return;
if (particleEffectEmitter is null)
return;
BeginParticleEffectEdit();
CheckBox@ element = eventData["Element"].GetPtr();
editParticleEffect.fixedScreenSize = element.checked;
particleEffectEmitter.ApplyEffect();
EndParticleEffectEdit();
}
bool ToggleParticleEffectEditor()
{
if (particleEffectWindow.visible == false)
ShowParticleEffectEditor();
else
HideParticleEffectEditor();
return true;
}
void ShowParticleEffectEditor()
{
RefreshParticleEffectEditor();
particleEffectWindow.visible = true;
particleEffectWindow.BringToFront();
}
void HideParticleEffectEditor()
{
if (particleEffectWindow !is null)
particleEffectWindow.visible = false;
}
void UpdateParticleEffectPreviewGrid()
{
uint gridSize = 8;
uint gridSubdivisions = 3;
//particleEffectPreviewGridNode.scale = Vector3(gridScale, gridScale, gridScale);
uint size = uint(Floor(gridSize / 2) * 2);
float halfSizeScaled = size / 2;
float scale = 1.0;
uint subdivisionSize = uint(Pow(2.0f, float(gridSubdivisions)));
if (subdivisionSize > 0)
{
size *= subdivisionSize;
scale /= subdivisionSize;
}
uint halfSize = size / 2;
particleEffectPreviewGrid.BeginGeometry(0, LINE_LIST);
float lineOffset = -halfSizeScaled;
for (uint i = 0; i <= size; ++i)
{
bool lineCenter = i == halfSize;
bool lineSubdiv = !Equals(Mod(i, subdivisionSize), 0.0);
if (!grid2DMode)
{
particleEffectPreviewGrid.DefineVertex(Vector3(lineOffset, 0.0, halfSizeScaled));
particleEffectPreviewGrid.DefineColor(lineCenter ? gridZColor : (lineSubdiv ? gridSubdivisionColor : gridColor));
particleEffectPreviewGrid.DefineVertex(Vector3(lineOffset, 0.0, -halfSizeScaled));
particleEffectPreviewGrid.DefineColor(lineCenter ? gridZColor : (lineSubdiv ? gridSubdivisionColor : gridColor));
particleEffectPreviewGrid.DefineVertex(Vector3(-halfSizeScaled, 0.0, lineOffset));
particleEffectPreviewGrid.DefineColor(lineCenter ? gridXColor : (lineSubdiv ? gridSubdivisionColor : gridColor));
particleEffectPreviewGrid.DefineVertex(Vector3(halfSizeScaled, 0.0, lineOffset));
particleEffectPreviewGrid.DefineColor(lineCenter ? gridXColor : (lineSubdiv ? gridSubdivisionColor : gridColor));
}
else
{
particleEffectPreviewGrid.DefineVertex(Vector3(lineOffset, halfSizeScaled, 0.0));
particleEffectPreviewGrid.DefineColor(lineCenter ? gridYColor : (lineSubdiv ? gridSubdivisionColor : gridColor));
particleEffectPreviewGrid.DefineVertex(Vector3(lineOffset, -halfSizeScaled, 0.0));
particleEffectPreviewGrid.DefineColor(lineCenter ? gridYColor : (lineSubdiv ? gridSubdivisionColor : gridColor));
particleEffectPreviewGrid.DefineVertex(Vector3(-halfSizeScaled, lineOffset, 0.0));
particleEffectPreviewGrid.DefineColor(lineCenter ? gridXColor : (lineSubdiv ? gridSubdivisionColor : gridColor));
particleEffectPreviewGrid.DefineVertex(Vector3(halfSizeScaled, lineOffset, 0.0));
particleEffectPreviewGrid.DefineColor(lineCenter ? gridXColor : (lineSubdiv ? gridSubdivisionColor : gridColor));
}
lineOffset += scale;
}
particleEffectPreviewGrid.Commit();
}
void InitParticleEffectPreview()
{
particlePreviewScene = Scene("particlePreviewScene");
particlePreviewScene.CreateComponent("Octree");
Node@ zoneNode = particlePreviewScene.CreateChild("Zone");
Zone@ zone = zoneNode.CreateComponent("Zone");
zone.boundingBox = BoundingBox(-1000, 1000);
zone.ambientColor = Color(0.15, 0.15, 0.15);
zone.fogColor = Color(0, 0, 0);
zone.fogStart = 10.0;
zone.fogEnd = 1000.0;
particlePreviewCameraNode = particlePreviewScene.CreateChild("PreviewCamera");
particlePreviewCamera = particlePreviewCameraNode.CreateComponent("Camera");
particlePreviewCamera.nearClip = 0.1f;
particlePreviewCamera.farClip = 1000.0f;
particlePreviewCamera.fov = 45.0f;
particlePreviewLightNode = particlePreviewScene.CreateChild("particlePreviewLight");
particlePreviewLightNode.direction = Vector3(0.5, -0.5, 0.5);
particlePreviewLight = particlePreviewLightNode.CreateComponent("Light");
particlePreviewLight.lightType = LIGHT_DIRECTIONAL;
particlePreviewLight.specularIntensity = 0.5;
particleEffectPreviewNode = particlePreviewScene.CreateChild("PreviewEmitter");
particleEffectPreviewNode.rotation = Quaternion(0, 0, 0);
ResetCameraTransformation();
particleEffectPreviewGizmoNode = particlePreviewScene.CreateChild("Gizmo");
StaticModel@ gizmo = particleEffectPreviewGizmoNode.CreateComponent("StaticModel");
gizmo.model = cache.GetResource("Model", "Models/Editor/Axes.mdl");
gizmo.materials[0] = cache.GetResource("Material", "Materials/Editor/RedUnlit.xml");
gizmo.materials[1] = cache.GetResource("Material", "Materials/Editor/GreenUnlit.xml");
gizmo.materials[2] = cache.GetResource("Material", "Materials/Editor/BlueUnlit.xml");
gizmo.occludee = false;
particleEffectPreviewGridNode = particlePreviewScene.CreateChild("Grid");
particleEffectPreviewGrid = particleEffectPreviewGridNode.CreateComponent("CustomGeometry");
particleEffectPreviewGrid.numGeometries = 1;
particleEffectPreviewGrid.material = cache.GetResource("Material", "Materials/VColUnlit.xml");
particleEffectPreviewGrid.viewMask = 0x80000000; // Editor raycasts use viewmask 0x7fffffff
particleEffectPreviewGrid.occludee = false;
UpdateParticleEffectPreviewGrid();
particleEffectEmitter = particleEffectPreviewNode.CreateComponent("ParticleEmitter");
editParticleEffect = CreateNewParticleEffect();
particleEffectEmitter.effect = editParticleEffect;
particleEffectPreview = particleEffectWindow.GetChild("ParticleEffectPreview", true);
particleEffectPreview.SetView(particlePreviewScene, particlePreviewCamera);
particleEffectPreview.viewport.renderPath = renderPath;
SubscribeToEvent(particleEffectPreview, "DragMove", "NavigateParticleEffectPreview");
SubscribeToEvent(particleEffectPreview, "Resized", "ResizeParticleEffectPreview");
}
ParticleEffect@ CreateNewParticleEffect()
{
ParticleEffect@ effect = ParticleEffect();
Material@ res = cache.GetResource("Material", "Materials/Particle.xml");
if (res is null)
log.Error("Could not load default material for new particle effect.");
effect.material = res;
effect.AddColorTime(Color(1,1,1,1), 0.0f);
return effect;
}
void EditParticleEffect(ParticleEffect@ effect)
{
if (effect is null)
return;
if (editParticleEffect !is null)
UnsubscribeFromEvent(editParticleEffect, "ReloadFinished");
if (!effect.name.empty)
cache.ReloadResource(effect);
editParticleEffect = effect;
particleEffectEmitter.effect = editParticleEffect;
if (editParticleEffect !is null)
SubscribeToEvent(editParticleEffect, "ReloadFinished", "RefreshParticleEffectEditor");
ShowParticleEffectEditor();
}
void RefreshParticleEffectEditor()
{
inParticleEffectRefresh = true;
RefreshParticleEffectPreview();
RefreshParticleEffectName();
RefreshParticleEffectBasicAttributes();
RefreshParticleEffectMaterial();
RefreshParticleEffectColorFrames();
RefreshParticleEffectTextureFrames();
inParticleEffectRefresh = false;
}
void RefreshParticleEffectColorFrames()
{
if (editParticleEffect is null)
return;
editParticleEffect.SortColorFrames();
ListView@ lv = particleEffectWindow.GetChild("ColorFrameListView", true);
if (lv is null)
return;
lv.RemoveAllItems();
for (uint i = 0; i < editParticleEffect.numColorFrames; i++)
{
ColorFrame@ colorFrame = editParticleEffect.GetColorFrame(i);
Button@ container = Button();
lv.AddItem(container);
container.style = "Button";
container.imageRect = IntRect(18, 2, 30, 14);
container.minSize = IntVector2(0, 20);
container.maxSize = IntVector2(2147483647, 20);
container.layoutMode = LM_HORIZONTAL;
container.layoutBorder = IntRect(3,1,3,1);
container.layoutSpacing = 4;
UIElement@ labelContainer = UIElement();
container.AddChild(labelContainer);
labelContainer.style = "HorizontalPanel";
labelContainer.minSize = IntVector2(0, 16);
labelContainer.maxSize = IntVector2(2147483647, 16);
labelContainer.verticalAlignment = VA_CENTER;
{
LineEdit@ le = LineEdit();
labelContainer.AddChild(le);
le.name = "ColorTime";
le.vars["ColorFrame"] = i;
le.style = "LineEdit";
le.minSize = IntVector2(0, 16);
le.maxSize = IntVector2(40, 16);
le.text = colorFrame.time;
le.cursorPosition = 0;
CreateDragSlider(le);
SubscribeToEvent(le, "TextChanged", "EditParticleEffectColorFrame");
}
UIElement@ textContainer = UIElement();
labelContainer.AddChild(textContainer);
textContainer.minSize = IntVector2(0, 16);
textContainer.maxSize = IntVector2(2147483647, 16);
textContainer.verticalAlignment = VA_CENTER;
Text@ t = Text();
textContainer.AddChild(t);
t.style = "Text";
t.text = "Color";
t.autoLocalizable = true;
UIElement@ editContainer = UIElement();
container.AddChild(editContainer);
editContainer.style = "HorizontalPanel";
editContainer.minSize = IntVector2(0, 16);
editContainer.maxSize = IntVector2(2147483647, 16);
editContainer.verticalAlignment = VA_CENTER;
{
LineEdit@ le = LineEdit();
editContainer.AddChild(le);
le.name = "ColorR";
le.vars["ColorFrame"] = i;
le.style = "LineEdit";
le.text = colorFrame.color.r;
le.cursorPosition = 0;
CreateDragSlider(le);
SubscribeToEvent(le, "TextChanged", "EditParticleEffectColorFrame");
}
{
LineEdit@ le = LineEdit();
editContainer.AddChild(le);
le.name = "ColorG";
le.vars["ColorFrame"] = i;
le.style = "LineEdit";
le.text = colorFrame.color.g;
le.cursorPosition = 0;
CreateDragSlider(le);
SubscribeToEvent(le, "TextChanged", "EditParticleEffectColorFrame");
}
{
LineEdit@ le = LineEdit();
editContainer.AddChild(le);
le.name = "ColorB";
le.vars["ColorFrame"] = i;
le.style = "LineEdit";
le.text = colorFrame.color.b;
le.cursorPosition = 0;
CreateDragSlider(le);
SubscribeToEvent(le, "TextChanged", "EditParticleEffectColorFrame");
}
{
LineEdit@ le = LineEdit();
editContainer.AddChild(le);
le.name = "ColorA";
le.vars["ColorFrame"] = i;
le.style = "LineEdit";
le.text = colorFrame.color.a;
le.cursorPosition = 0;
CreateDragSlider(le);
SubscribeToEvent(le, "TextChanged", "EditParticleEffectColorFrame");
}
}
}
void RefreshParticleEffectTextureFrames()
{
if (editParticleEffect is null)
return;
editParticleEffect.SortTextureFrames();
ListView@ lv = particleEffectWindow.GetChild("TextureFrameListView", true);
if (lv is null)
return;
lv.RemoveAllItems();
for (uint i = 0; i < editParticleEffect.numTextureFrames; i++)
{
TextureFrame@ textureFrame = editParticleEffect.GetTextureFrame(i);
if (textureFrame is null)
continue;
Button@ container = Button();
lv.AddItem(container);
container.style = "Button";
container.imageRect = IntRect(18, 2, 30, 14);
container.minSize = IntVector2(0, 20);
container.maxSize = IntVector2(2147483647, 20);
container.layoutMode = LM_HORIZONTAL;
container.layoutBorder = IntRect(1,1,1,1);
container.layoutSpacing = 4;
UIElement@ labelContainer = UIElement();
container.AddChild(labelContainer);
labelContainer.style = "HorizontalPanel";
labelContainer.minSize = IntVector2(0, 16);
labelContainer.maxSize = IntVector2(2147483647, 16);
labelContainer.verticalAlignment = VA_CENTER;
{
LineEdit@ le = LineEdit();
labelContainer.AddChild(le);
le.name = "TextureTime";
le.vars["TextureFrame"] = i;
le.style = "LineEdit";
le.minSize = IntVector2(0, 16);
le.maxSize = IntVector2(40, 16);
le.text = textureFrame.time;
le.cursorPosition = 0;
CreateDragSlider(le);
SubscribeToEvent(le, "TextChanged", "EditParticleEffectTextureFrame");
}
UIElement@ textContainer = UIElement();
labelContainer.AddChild(textContainer);
textContainer.minSize = IntVector2(0, 16);
textContainer.maxSize = IntVector2(2147483647, 16);
textContainer.verticalAlignment = VA_CENTER;
Text@ t = Text();
textContainer.AddChild(t);
t.style = "Text";
t.text = "Texture";
t.autoLocalizable = true;
UIElement@ editContainer = UIElement();
container.AddChild(editContainer);
editContainer.style = "HorizontalPanel";
editContainer.minSize = IntVector2(0, 16);
editContainer.maxSize = IntVector2(2147483647, 16);
editContainer.verticalAlignment = VA_CENTER;
{
LineEdit@ le = LineEdit();
editContainer.AddChild(le);
le.name = "TextureMinX";
le.vars["TextureFrame"] = i;
le.style = "LineEdit";
le.text = textureFrame.uv.min.x;
le.cursorPosition = 0;
CreateDragSlider(le);
SubscribeToEvent(le, "TextChanged", "EditParticleEffectTextureFrame");
}
{
LineEdit@ le = LineEdit();
editContainer.AddChild(le);
le.name = "TextureMinY";
le.vars["TextureFrame"] = i;
le.style = "LineEdit";
le.text = textureFrame.uv.min.y;
le.cursorPosition = 0;
CreateDragSlider(le);
SubscribeToEvent(le, "TextChanged", "EditParticleEffectTextureFrame");
}
{
LineEdit@ le = LineEdit();
editContainer.AddChild(le);
le.name = "TextureMaxX";
le.vars["TextureFrame"] = i;
le.style = "LineEdit";
le.text = textureFrame.uv.max.x;
le.cursorPosition = 0;
CreateDragSlider(le);
SubscribeToEvent(le, "TextChanged", "EditParticleEffectTextureFrame");
}
{
LineEdit@ le = LineEdit();
editContainer.AddChild(le);
le.name = "TextureMaxY";
le.vars["TextureFrame"] = i;
le.style = "LineEdit";
le.text = textureFrame.uv.max.y;
le.cursorPosition = 0;
CreateDragSlider(le);
SubscribeToEvent(le, "TextChanged", "EditParticleEffectTextureFrame");
}
}
}
void EditParticleEffectColorFrame(StringHash eventType, VariantMap& eventData)
{
if (inParticleEffectRefresh)
return;
if (editParticleEffect is null)
return;
if (particleEffectEmitter is null)
return;
BeginParticleEffectEdit();
LineEdit@ element = eventData["Element"].GetPtr();
uint i = element.vars["ColorFrame"].GetInt();
ColorFrame@ cf = editParticleEffect.GetColorFrame(i);
if (element.name == "ColorTime")
cf.time = element.text.ToFloat();
if (element.name == "ColorR")
cf.color = Color(element.text.ToFloat(), cf.color.g, cf.color.b, cf.color.a);
if (element.name == "ColorG")
cf.color = Color(cf.color.r, element.text.ToFloat(), cf.color.b, cf.color.a);
if (element.name == "ColorB")
cf.color = Color(cf.color.r, cf.color.g, element.text.ToFloat(), cf.color.a);
if (element.name == "ColorA")
cf.color = Color(cf.color.r, cf.color.g, cf.color.b, element.text.ToFloat());
editParticleEffect.SetColorFrame(i, cf);
particleEffectEmitter.Reset();
EndParticleEffectEdit();
}
void EditParticleEffectTextureFrame(StringHash eventType, VariantMap& eventData)
{
if (inParticleEffectRefresh)
return;
if (editParticleEffect is null)
return;
if (particleEffectEmitter is null)
return;
BeginParticleEffectEdit();
LineEdit@ element = eventData["Element"].GetPtr();
uint i = element.vars["TextureFrame"].GetInt();
TextureFrame@ tf = editParticleEffect.GetTextureFrame(i);
if (element.name == "TextureTime")
tf.time = element.text.ToFloat();
if (element.name == "TextureMinX")
tf.uv = Rect(element.text.ToFloat(), tf.uv.min.y, tf.uv.max.x, tf.uv.max.y);
if (element.name == "TextureMinY")
tf.uv = Rect(tf.uv.min.x, element.text.ToFloat(), tf.uv.max.x, tf.uv.max.y);
if (element.name == "TextureMaxX")
tf.uv = Rect(tf.uv.min.x, tf.uv.min.y, element.text.ToFloat(), tf.uv.max.y);
if (element.name == "TextureMaxY")
tf.uv = Rect(tf.uv.min.x, tf.uv.min.y, tf.uv.max.x, element.text.ToFloat());
editParticleEffect.SetTextureFrame(i, tf);
particleEffectEmitter.Reset();
EndParticleEffectEdit();
}
void RefreshParticleEffectPreview()
{
if (particleEffectEmitter is null || editParticleEffect is null)
return;
cast<CheckBox>(particleEffectWindow.GetChild("ShowGrid", true)).checked = showParticlePreviewAxes;
particleEffectEmitter.effect = editParticleEffect;
particleEffectEmitter.Reset();
particleEffectPreview.QueueUpdate();
}
void RefreshParticleEffectName()
{
UIElement@ container = particleEffectWindow.GetChild("NameContainer", true);
if (container is null)
return;
container.RemoveAllChildren();
LineEdit@ nameEdit = CreateAttributeLineEdit(container, null, 0, 0);
if (editParticleEffect !is null)
nameEdit.text = editParticleEffect.name;
SubscribeToEvent(nameEdit, "TextFinished", "EditParticleEffectName");
Button@ pickButton = CreateResourcePickerButton(container, null, 0, 0, "smallButtonPick");
SubscribeToEvent(pickButton, "Released", "PickEditParticleEffect");
}
void RefreshParticleEffectBasicAttributes()
{
if (editParticleEffect is null)
return;
cast<LineEdit>(particleEffectWindow.GetChild("ConstantForceX", true)).text = editParticleEffect.constantForce.x;
cast<LineEdit>(particleEffectWindow.GetChild("ConstantForceY", true)).text = editParticleEffect.constantForce.y;
cast<LineEdit>(particleEffectWindow.GetChild("ConstantForceZ", true)).text = editParticleEffect.constantForce.z;
cast<LineEdit>(particleEffectWindow.GetChild("DirectionMinX", true)).text = editParticleEffect.minDirection.x;
cast<LineEdit>(particleEffectWindow.GetChild("DirectionMinY", true)).text = editParticleEffect.minDirection.y;
cast<LineEdit>(particleEffectWindow.GetChild("DirectionMinZ", true)).text = editParticleEffect.minDirection.z;
cast<LineEdit>(particleEffectWindow.GetChild("DirectionMaxX", true)).text = editParticleEffect.maxDirection.x;
cast<LineEdit>(particleEffectWindow.GetChild("DirectionMaxY", true)).text = editParticleEffect.maxDirection.y;
cast<LineEdit>(particleEffectWindow.GetChild("DirectionMaxZ", true)).text = editParticleEffect.maxDirection.z;
cast<LineEdit>(particleEffectWindow.GetChild("DampingForce", true)).text = editParticleEffect.dampingForce;
cast<LineEdit>(particleEffectWindow.GetChild("ActiveTime", true)).text = editParticleEffect.activeTime;
cast<LineEdit>(particleEffectWindow.GetChild("InactiveTime", true)).text = editParticleEffect.inactiveTime;
cast<LineEdit>(particleEffectWindow.GetChild("ParticleSizeMinX", true)).text = editParticleEffect.minParticleSize.x;
cast<LineEdit>(particleEffectWindow.GetChild("ParticleSizeMinY", true)).text = editParticleEffect.minParticleSize.y;
cast<LineEdit>(particleEffectWindow.GetChild("ParticleSizeMaxX", true)).text = editParticleEffect.maxParticleSize.x;
cast<LineEdit>(particleEffectWindow.GetChild("ParticleSizeMaxY", true)).text = editParticleEffect.maxParticleSize.y;
cast<LineEdit>(particleEffectWindow.GetChild("TimeToLiveMin", true)).text = editParticleEffect.minTimeToLive;
cast<LineEdit>(particleEffectWindow.GetChild("TimeToLiveMax", true)).text = editParticleEffect.maxTimeToLive;
cast<LineEdit>(particleEffectWindow.GetChild("VelocityMin", true)).text = editParticleEffect.minVelocity;
cast<LineEdit>(particleEffectWindow.GetChild("VelocityMax", true)).text = editParticleEffect.maxVelocity;
cast<LineEdit>(particleEffectWindow.GetChild("RotationMin", true)).text = editParticleEffect.minRotation;
cast<LineEdit>(particleEffectWindow.GetChild("RotationMax", true)).text = editParticleEffect.maxRotation;
cast<LineEdit>(particleEffectWindow.GetChild("RotationSpeedMin", true)).text = editParticleEffect.minRotationSpeed;
cast<LineEdit>(particleEffectWindow.GetChild("RotationSpeedMax", true)).text = editParticleEffect.maxRotationSpeed;
cast<LineEdit>(particleEffectWindow.GetChild("SizeAdd", true)).text = editParticleEffect.sizeAdd;
cast<LineEdit>(particleEffectWindow.GetChild("SizeMultiply", true)).text = editParticleEffect.sizeMul;
cast<LineEdit>(particleEffectWindow.GetChild("AnimationLodBias", true)).text = editParticleEffect.animationLodBias;
cast<LineEdit>(particleEffectWindow.GetChild("NumParticles", true)).text = editParticleEffect.numParticles;
cast<LineEdit>(particleEffectWindow.GetChild("EmitterSizeX", true)).text = editParticleEffect.emitterSize.x;
cast<LineEdit>(particleEffectWindow.GetChild("EmitterSizeY", true)).text = editParticleEffect.emitterSize.y;
cast<LineEdit>(particleEffectWindow.GetChild("EmitterSizeZ", true)).text = editParticleEffect.emitterSize.z;
cast<LineEdit>(particleEffectWindow.GetChild("EmissionRateMin", true)).text = editParticleEffect.minEmissionRate;
cast<LineEdit>(particleEffectWindow.GetChild("EmissionRateMax", true)).text = editParticleEffect.maxEmissionRate;
switch (editParticleEffect.emitterType)
{
case EMITTER_SPHERE:
cast<DropDownList>(particleEffectWindow.GetChild("EmitterShape", true)).selection = 0;
break;
case EMITTER_BOX:
cast<DropDownList>(particleEffectWindow.GetChild("EmitterShape", true)).selection = 1;
break;
case EMITTER_SPHEREVOLUME:
cast<DropDownList>(particleEffectWindow.GetChild("EmitterShape", true)).selection = 2;
break;
case EMITTER_CYLINDER:
cast<DropDownList>(particleEffectWindow.GetChild("EmitterShape", true)).selection = 3;
break;
case EMITTER_RING:
cast<DropDownList>(particleEffectWindow.GetChild("EmitterShape", true)).selection = 4;
break;
}
switch (editParticleEffect.faceCameraMode)
{
case FC_NONE:
cast<DropDownList>(particleEffectWindow.GetChild("FaceCameraMode", true)).selection = 0;
break;
case FC_ROTATE_XYZ:
cast<DropDownList>(particleEffectWindow.GetChild("FaceCameraMode", true)).selection = 1;
break;
case FC_ROTATE_Y:
cast<DropDownList>(particleEffectWindow.GetChild("FaceCameraMode", true)).selection = 2;
break;
case FC_LOOKAT_XYZ:
cast<DropDownList>(particleEffectWindow.GetChild("FaceCameraMode", true)).selection = 3;
break;
case FC_LOOKAT_Y:
cast<DropDownList>(particleEffectWindow.GetChild("FaceCameraMode", true)).selection = 4;
break;
case FC_DIRECTION:
cast<DropDownList>(particleEffectWindow.GetChild("FaceCameraMode", true)).selection = 5;
break;
}
cast<CheckBox>(particleEffectWindow.GetChild("Scaled", true)).checked = editParticleEffect.scaled;
cast<CheckBox>(particleEffectWindow.GetChild("Sorted", true)).checked = editParticleEffect.sorted;
cast<CheckBox>(particleEffectWindow.GetChild("Relative", true)).checked = editParticleEffect.relative;
cast<CheckBox>(particleEffectWindow.GetChild("FixedScreenSize", true)).checked = editParticleEffect.fixedScreenSize;
}
void RefreshParticleEffectMaterial()
{
UIElement@ container = particleEffectWindow.GetChild("ParticleMaterialContainer", true);
if (container is null)
return;
container.RemoveAllChildren();
LineEdit@ nameEdit = CreateAttributeLineEdit(container, null, 0, 0);
if (editParticleEffect !is null)
{
if (editParticleEffect.material !is null)
nameEdit.text = editParticleEffect.material.name;
else
{
nameEdit.text = "Materials/Particle.xml";
Material@ res = cache.GetResource("Material", "Materials/Particle.xml");
if (res !is null)
editParticleEffect.material = res;
}
}
SubscribeToEvent(nameEdit, "TextFinished", "EditParticleEffectMaterial");
Button@ pickButton = CreateResourcePickerButton(container, null, 0, 0, "smallButtonPick");
SubscribeToEvent(pickButton, "Released", "PickEditParticleEffectMaterial");
}
void NavigateParticleEffectPreview(StringHash eventType, VariantMap& eventData)
{
int dx = eventData["DX"].GetInt();
int dy = eventData["DY"].GetInt();
if (particleEffectPreview.height > 0 && particleEffectPreview.width > 0)
{
if (!input.keyDown[KEY_LSHIFT])
{
particleViewCamRot.x -= dy * 20 * time.timeStep;
particleViewCamRot.y += dx * 20 * time.timeStep;
particleViewCamRot.x = Clamp(particleViewCamRot.x, -89.5, 89.5);
}
else
{
particleViewCamDist += dy * 1.5 * time.timeStep;
particleViewCamDist -= dx * 1.5 * time.timeStep;
particleViewCamDist = Max(particleViewCamDist, 0.2);
}
particlePreviewCameraNode.position = particleEffectPreviewNode.position +
Quaternion(particleViewCamRot.x, particleViewCamRot.y, 0) * particleViewCamDir * particleViewCamDist;
particlePreviewCameraNode.LookAt(particleEffectPreviewNode.position);
SetGizmoPosition();
particleEffectPreview.QueueUpdate();
}
}
void ResizeParticleEffectPreview(StringHash eventType, VariantMap& eventData)
{
float width = float(particleEffectPreview.width);
float height = float(particleEffectPreview.height);
// Manually set aspect ratio because first frame is always returning aspect ratio of 1
float aspectRatio = width / height;
particlePreviewCamera.aspectRatio = aspectRatio;
gizmoOffsetX = gizmoOffset;
gizmoOffsetY = 1.0f - gizmoOffset * aspectRatio;
if(width > height)
{
aspectRatio = height / width;
gizmoOffsetY = 1.0f - gizmoOffset;
gizmoOffsetX = gizmoOffset * aspectRatio;
}
SetGizmoPosition();
particleEffectPreview.QueueUpdate();
}
void EditParticleEffectName(StringHash eventType, VariantMap& eventData)
{
LineEdit@ nameEdit = eventData["Element"].GetPtr();
String newParticleEffectName = nameEdit.text.Trimmed();
if (!newParticleEffectName.empty && !(editParticleEffect !is null && newParticleEffectName == editParticleEffect.name))
{
ParticleEffect@ newParticleEffect = cache.GetResource("ParticleEffect", newParticleEffectName);
if (newParticleEffect !is null)
EditParticleEffect(newParticleEffect);
}
}
void PickEditParticleEffect()
{
@resourcePicker = GetResourcePicker(StringHash("ParticleEffect"));
if (resourcePicker is null)
return;
String lastPath = resourcePicker.lastPath;
if (lastPath.empty)
lastPath = sceneResourcePath;
CreateFileSelector(localization.Get("Pick ") + resourcePicker.typeName, "OK", "Cancel", lastPath, resourcePicker.filters, resourcePicker.lastFilter, false);
SubscribeToEvent(uiFileSelector, "FileSelected", "PickEditParticleEffectDone");
}
void PickEditParticleEffectDone(StringHash eventType, VariantMap& eventData)
{
StoreResourcePickerPath();
CloseFileSelector();
if (!eventData["OK"].GetBool())
{
@resourcePicker = null;
return;
}
String resourceName = eventData["FileName"].GetString();
Resource@ res = GetPickedResource(resourceName);
if (res !is null)
EditParticleEffect(cast<ParticleEffect>(res));
@resourcePicker = null;
}
void NewParticleEffect()
{
BeginParticleEffectEdit();
EditParticleEffect(CreateNewParticleEffect());
EndParticleEffectEdit();
}
void RevertParticleEffect()
{
if (inParticleEffectRefresh)
return;
if (editParticleEffect is null)
return;
if (editParticleEffect.name.empty)
{
NewParticleEffect();
return;
}
BeginParticleEffectEdit();
cache.ReloadResource(editParticleEffect);
EndParticleEffectEdit();
RefreshParticleEffectEditor();
}
void SaveParticleEffect()
{
if (editParticleEffect is null || editParticleEffect.name.empty)
return;
String fullName = cache.GetResourceFileName(editParticleEffect.name);
if (fullName.empty)
return;
File saveFile(fullName, FILE_WRITE);
editParticleEffect.Save(saveFile);
}
void SaveParticleEffectAs()
{
if (editParticleEffect is null)
return;
@resourcePicker = GetResourcePicker(StringHash("ParticleEffect"));
if (resourcePicker is null)
return;
String lastPath = resourcePicker.lastPath;
if (lastPath.empty)
lastPath = sceneResourcePath;
CreateFileSelector("Save particle effect as", "Save", "Cancel", lastPath, resourcePicker.filters, resourcePicker.lastFilter);
SubscribeToEvent(uiFileSelector, "FileSelected", "SaveParticleEffectAsDone");
}
void SaveParticleEffectAsDone(StringHash eventType, VariantMap& eventData)
{
StoreResourcePickerPath();
CloseFileSelector();
@resourcePicker = null;
if (editParticleEffect is null)
return;
if (!eventData["OK"].GetBool())
{
@resourcePicker = null;
return;
}
String fullName = eventData["FileName"].GetString();
// Add default extension for saving if not specified
String filter = eventData["Filter"].GetString();
if (GetExtension(fullName).empty && filter != "*.*")
fullName = fullName + filter.Substring(1);
File saveFile(fullName, FILE_WRITE);
if (editParticleEffect.Save(saveFile))
{
saveFile.Close();
// Load the new resource to update the name in the editor
ParticleEffect@ newEffect = cache.GetResource("ParticleEffect", GetResourceNameFromFullName(fullName));
if (newEffect !is null)
EditParticleEffect(newEffect);
}
}
void BeginParticleEffectEdit()
{
if (editParticleEffect is null)
return;
inParticleEffectRefresh = true;
oldParticleEffectState = XMLFile();
XMLElement particleElem = oldParticleEffectState.CreateRoot("particleeffect");
editParticleEffect.Save(particleElem);
}
void EndParticleEffectEdit()
{
if (editParticleEffect is null)
return;
if (!dragEditAttribute)
{
EditParticleEffectAction@ action = EditParticleEffectAction();
action.Define(particleEffectEmitter, editParticleEffect, oldParticleEffectState);
SaveEditAction(action);
}
inParticleEffectRefresh = false;
particleEffectPreview.QueueUpdate();
}