#include "stdafx.h" #include "EmitterWindow.h" #include "MaterialWindow.h" #include using namespace std; EmitterWindow::EmitterWindow(wiGUI* gui) : GUI(gui) { assert(GUI && "Invalid GUI!"); object = nullptr; materialWnd = nullptr; float screenW = (float)wiRenderer::GetDevice()->GetScreenWidth(); float screenH = (float)wiRenderer::GetDevice()->GetScreenHeight(); emitterWindow = new wiWindow(GUI, "Emitter Window"); emitterWindow->SetSize(XMFLOAT2(760, 800)); emitterWindow->SetEnabled(false); GUI->AddWidget(emitterWindow); float x = 150; float y = 10; float step = 35; emitterComboBox = new wiComboBox("Emitter: "); emitterComboBox->SetPos(XMFLOAT2(x, y += step)); emitterComboBox->SetSize(XMFLOAT2(360, 25)); emitterComboBox->OnSelect([&](wiEventArgs args) { if (object != nullptr && args.iValue >= 0) { SetObject(object); } }); emitterComboBox->SetEnabled(false); emitterComboBox->SetTooltip("Choose an emitter associated with the selected object"); emitterWindow->AddWidget(emitterComboBox); shaderTypeComboBox = new wiComboBox("ShaderType: "); shaderTypeComboBox->SetPos(XMFLOAT2(x, y += step)); shaderTypeComboBox->SetSize(XMFLOAT2(200, 25)); shaderTypeComboBox->AddItem("SOFT"); shaderTypeComboBox->AddItem("SOFT + DISTORTION"); shaderTypeComboBox->AddItem("SIMPLEST"); shaderTypeComboBox->OnSelect([&](wiEventArgs args) { auto emitter = GetEmitter(); if (emitter != nullptr) { emitter->shaderType = (wiEmittedParticle::PARTICLESHADERTYPE)args.iValue; } }); shaderTypeComboBox->SetEnabled(false); shaderTypeComboBox->SetTooltip("Choose a shader type for the particles. This is responsible of how they will be rendered."); emitterWindow->AddWidget(shaderTypeComboBox); sortCheckBox = new wiCheckBox("Sorting Enabled: "); sortCheckBox->SetPos(XMFLOAT2(x, y += step)); sortCheckBox->OnClick([&](wiEventArgs args) { auto emitter = GetEmitter(); if (emitter != nullptr) { emitter->SORTING = args.bValue; } }); sortCheckBox->SetCheck(false); sortCheckBox->SetTooltip("Enable sorting of the particles. This might slow down performance."); emitterWindow->AddWidget(sortCheckBox); depthCollisionsCheckBox = new wiCheckBox("Depth Buffer Collisions Enabled: "); depthCollisionsCheckBox->SetPos(XMFLOAT2(x + 250, y)); depthCollisionsCheckBox->OnClick([&](wiEventArgs args) { auto emitter = GetEmitter(); if (emitter != nullptr) { emitter->DEPTHCOLLISIONS = args.bValue; } }); depthCollisionsCheckBox->SetCheck(false); depthCollisionsCheckBox->SetTooltip("Enable particle collisions with the depth buffer."); emitterWindow->AddWidget(depthCollisionsCheckBox); debugCheckBox = new wiCheckBox("DEBUG: "); debugCheckBox->SetPos(XMFLOAT2(x + 350, y)); debugCheckBox->OnClick([&](wiEventArgs args) { auto emitter = GetEmitter(); if (emitter != nullptr) { emitter->DEBUG = args.bValue; } }); debugCheckBox->SetCheck(false); debugCheckBox->SetTooltip("Enable debug info for the emitter. This involves reading back GPU data, so rendering can slow down."); emitterWindow->AddWidget(debugCheckBox); infoLabel = new wiLabel("EmitterInfo"); infoLabel->SetSize(XMFLOAT2(380, 140)); infoLabel->SetPos(XMFLOAT2(x, y += step)); emitterWindow->AddWidget(infoLabel); maxParticlesSlider = new wiSlider(100.0f, 1000000.0f, 10000, 100000, "Max particle count: "); maxParticlesSlider->SetSize(XMFLOAT2(360, 30)); maxParticlesSlider->SetPos(XMFLOAT2(x, y += step + 140)); maxParticlesSlider->OnSlide([&](wiEventArgs args) { auto emitter = GetEmitter(); if (emitter != nullptr) { emitter->SetMaxParticleCount((uint32_t)args.iValue); } }); maxParticlesSlider->SetEnabled(false); maxParticlesSlider->SetTooltip("Set the maximum amount of particles this system can handle. This has an effect on the memory budget."); emitterWindow->AddWidget(maxParticlesSlider); y += 30; ////////////////////////////////////////////////////////////////////////////////////////////////// emitCountSlider = new wiSlider(0.0f, 10000.0f, 1.0f, 100000, "Emit count per sec: "); emitCountSlider->SetSize(XMFLOAT2(360, 30)); emitCountSlider->SetPos(XMFLOAT2(x, y += step)); emitCountSlider->OnSlide([&](wiEventArgs args) { auto emitter = GetEmitter(); if (emitter != nullptr) { emitter->count = args.fValue; } }); emitCountSlider->SetEnabled(false); emitCountSlider->SetTooltip("Set the number of particles to emit per second."); emitterWindow->AddWidget(emitCountSlider); emitSizeSlider = new wiSlider(0.01f, 10.0f, 1.0f, 100000, "Size: "); emitSizeSlider->SetSize(XMFLOAT2(360, 30)); emitSizeSlider->SetPos(XMFLOAT2(x, y += step)); emitSizeSlider->OnSlide([&](wiEventArgs args) { auto emitter = GetEmitter(); if (emitter != nullptr) { emitter->size = args.fValue; } }); emitSizeSlider->SetEnabled(false); emitSizeSlider->SetTooltip("Set the size of the emitted particles."); emitterWindow->AddWidget(emitSizeSlider); emitRotationSlider = new wiSlider(0.0f, 1.0f, 0.0f, 100000, "Rotation: "); emitRotationSlider->SetSize(XMFLOAT2(360, 30)); emitRotationSlider->SetPos(XMFLOAT2(x, y += step)); emitRotationSlider->OnSlide([&](wiEventArgs args) { auto emitter = GetEmitter(); if (emitter != nullptr) { emitter->rotation = args.fValue; } }); emitRotationSlider->SetEnabled(false); emitRotationSlider->SetTooltip("Set the rotation velocity of the emitted particles."); emitterWindow->AddWidget(emitRotationSlider); emitNormalSlider = new wiSlider(0.0f, 100.0f, 1.0f, 100000, "Normal factor: "); emitNormalSlider->SetSize(XMFLOAT2(360, 30)); emitNormalSlider->SetPos(XMFLOAT2(x, y += step)); emitNormalSlider->OnSlide([&](wiEventArgs args) { auto emitter = GetEmitter(); if (emitter != nullptr) { emitter->normal_factor = args.fValue; } }); emitNormalSlider->SetEnabled(false); emitNormalSlider->SetTooltip("Set the velocity of the emitted particles based on the normal vector of the emitter surface."); emitterWindow->AddWidget(emitNormalSlider); emitScalingSlider = new wiSlider(0.0f, 100.0f, 1.0f, 100000, "Scaling: "); emitScalingSlider->SetSize(XMFLOAT2(360, 30)); emitScalingSlider->SetPos(XMFLOAT2(x, y += step)); emitScalingSlider->OnSlide([&](wiEventArgs args) { auto emitter = GetEmitter(); if (emitter != nullptr) { emitter->scaleX = args.fValue; } }); emitScalingSlider->SetEnabled(false); emitScalingSlider->SetTooltip("Set the scaling of the particles based on their lifetime."); emitterWindow->AddWidget(emitScalingSlider); emitLifeSlider = new wiSlider(0.0f, 1000.0f, 1.0f, 100000, "Life span: "); emitLifeSlider->SetSize(XMFLOAT2(360, 30)); emitLifeSlider->SetPos(XMFLOAT2(x, y += step)); emitLifeSlider->OnSlide([&](wiEventArgs args) { auto emitter = GetEmitter(); if (emitter != nullptr) { emitter->life = args.fValue; } }); emitLifeSlider->SetEnabled(false); emitLifeSlider->SetTooltip("Set the lifespan of the emitted particles."); emitterWindow->AddWidget(emitLifeSlider); emitRandomnessSlider = new wiSlider(0.0f, 1.0f, 1.0f, 100000, "Randomness: "); emitRandomnessSlider->SetSize(XMFLOAT2(360, 30)); emitRandomnessSlider->SetPos(XMFLOAT2(x, y += step)); emitRandomnessSlider->OnSlide([&](wiEventArgs args) { auto emitter = GetEmitter(); if (emitter != nullptr) { emitter->random_factor = args.fValue; } }); emitRandomnessSlider->SetEnabled(false); emitRandomnessSlider->SetTooltip("Set the general randomness of the emitter."); emitterWindow->AddWidget(emitRandomnessSlider); emitLifeRandomnessSlider = new wiSlider(0.0f, 2.0f, 0.0f, 100000, "Life randomness: "); emitLifeRandomnessSlider->SetSize(XMFLOAT2(360, 30)); emitLifeRandomnessSlider->SetPos(XMFLOAT2(x, y += step)); emitLifeRandomnessSlider->OnSlide([&](wiEventArgs args) { auto emitter = GetEmitter(); if (emitter != nullptr) { emitter->random_life = args.fValue; } }); emitLifeRandomnessSlider->SetEnabled(false); emitLifeRandomnessSlider->SetTooltip("Set the randomness of lifespans for the emitted particles."); emitterWindow->AddWidget(emitLifeRandomnessSlider); emitMotionBlurSlider = new wiSlider(0.0f, 1.0f, 1.0f, 100000, "Motion blur: "); emitMotionBlurSlider->SetSize(XMFLOAT2(360, 30)); emitMotionBlurSlider->SetPos(XMFLOAT2(x, y += step)); emitMotionBlurSlider->OnSlide([&](wiEventArgs args) { auto emitter = GetEmitter(); if (emitter != nullptr) { emitter->motionBlurAmount = args.fValue; } }); emitMotionBlurSlider->SetEnabled(false); emitMotionBlurSlider->SetTooltip("Set the motion blur amount for the particle system."); emitterWindow->AddWidget(emitMotionBlurSlider); materialSelectButton = new wiButton("Select Material"); materialSelectButton->SetPos(XMFLOAT2(x, y += step)); materialSelectButton->SetSize(XMFLOAT2(150, 30)); materialSelectButton->OnClick([&](wiEventArgs args) { if (materialWnd != nullptr) { auto emitter = GetEmitter(); if (emitter != nullptr) { materialWnd->SetMaterial(emitter->material); } } }); materialSelectButton->SetTooltip("Select corresponding material in the Material Window."); emitterWindow->AddWidget(materialSelectButton); emitterWindow->Translate(XMFLOAT3(200, 50, 0)); emitterWindow->SetVisible(false); SetObject(nullptr); } EmitterWindow::~EmitterWindow() { emitterWindow->RemoveWidgets(true); GUI->RemoveWidget(emitterWindow); SAFE_DELETE(emitterWindow); } void EmitterWindow::SetObject(Object* obj) { if (this->object == obj) return; // first try to turn off any debug readbacks for emitters: if (GetEmitter() != nullptr) { GetEmitter()->DEBUG = false; } debugCheckBox->SetCheck(false); object = obj; emitterComboBox->ClearItems(); if (object != nullptr) { for (auto& x : object->eParticleSystems) { emitterComboBox->AddItem(x->name); emitterComboBox->SetEnabled(true); } auto emitter = GetEmitter(); if (emitter != nullptr) { sortCheckBox->SetCheck(emitter->SORTING); depthCollisionsCheckBox->SetCheck(emitter->DEPTHCOLLISIONS); maxParticlesSlider->SetValue((float)emitter->GetMaxParticleCount()); emitCountSlider->SetValue(emitter->count); emitSizeSlider->SetValue(emitter->size); emitRotationSlider->SetValue(emitter->rotation); emitNormalSlider->SetValue(emitter->normal_factor); emitScalingSlider->SetValue(emitter->scaleX); emitLifeSlider->SetValue(emitter->life); emitRandomnessSlider->SetValue(emitter->random_factor); emitLifeRandomnessSlider->SetValue(emitter->random_life); emitMotionBlurSlider->SetValue(emitter->motionBlurAmount); } emitterWindow->SetEnabled(true); } else { infoLabel->SetText("No emitter object selected."); emitterWindow->SetEnabled(false); } } void EmitterWindow::SetMaterialWnd(MaterialWindow* wnd) { materialWnd = wnd; } wiEmittedParticle* EmitterWindow::GetEmitter() { if (object == nullptr) { return nullptr; } int sel = emitterComboBox->GetSelected(); if (sel < 0) { return nullptr; } if ((int)object->eParticleSystems.size() > sel) { return object->eParticleSystems[sel]; } return nullptr; } void EmitterWindow::UpdateData() { auto emitter = GetEmitter(); if (emitter == nullptr) { return; } stringstream ss(""); ss.precision(2); ss << "Emitter name: " << emitter->name << endl; ss << "Emitter Object: " << (emitter->object != nullptr ? emitter->object->name : "ERROR: NO EMITTER OBJECT") << endl; ss << "Emitter Material: " << (emitter->material != nullptr ? emitter->material->name : "ERROR: NO EMITTER MATERIAL") << endl; ss << "Memort Budget: " << emitter->GetMemorySizeInBytes() / 1024.0f / 1024.0f << " MB" << endl; ss << endl; if (emitter->DEBUG) { auto data = emitter->GetDebugData(); ss << "Alive Particle Count = " << data.aliveCount << endl; ss << "Dead Particle Count = " << data.deadCount << endl; ss << "GPU Emit count = " << data.realEmitCount << endl; } else { ss << "For additional data, enable [DEBUG]" << endl; } infoLabel->SetText(ss.str()); }