|
|
|
|
@ -57,39 +57,39 @@ ParticleEditor::ParticleEditor(const LLSD& key)
|
|
|
|
|
mObject(0),
|
|
|
|
|
mParticleScriptInventoryItem(0)
|
|
|
|
|
{
|
|
|
|
|
mPatternMap["drop"]=LLPartSysData::LL_PART_SRC_PATTERN_DROP;
|
|
|
|
|
mPatternMap["explode"]=LLPartSysData::LL_PART_SRC_PATTERN_EXPLODE;
|
|
|
|
|
mPatternMap["angle"]=LLPartSysData::LL_PART_SRC_PATTERN_ANGLE;
|
|
|
|
|
mPatternMap["angle_cone"]=LLPartSysData::LL_PART_SRC_PATTERN_ANGLE_CONE;
|
|
|
|
|
mPatternMap["angle_cone_empty"]=LLPartSysData::LL_PART_SRC_PATTERN_ANGLE_CONE_EMPTY;
|
|
|
|
|
mPatternMap["drop"] = LLPartSysData::LL_PART_SRC_PATTERN_DROP;
|
|
|
|
|
mPatternMap["explode"] = LLPartSysData::LL_PART_SRC_PATTERN_EXPLODE;
|
|
|
|
|
mPatternMap["angle"] = LLPartSysData::LL_PART_SRC_PATTERN_ANGLE;
|
|
|
|
|
mPatternMap["angle_cone"] = LLPartSysData::LL_PART_SRC_PATTERN_ANGLE_CONE;
|
|
|
|
|
mPatternMap["angle_cone_empty"] = LLPartSysData::LL_PART_SRC_PATTERN_ANGLE_CONE_EMPTY;
|
|
|
|
|
|
|
|
|
|
mScriptPatternMap["drop"]="PSYS_SRC_PATTERN_DROP";
|
|
|
|
|
mScriptPatternMap["explode"]="PSYS_SRC_PATTERN_EXPLODE";
|
|
|
|
|
mScriptPatternMap["angle"]="PSYS_SRC_PATTERN_ANGLE";
|
|
|
|
|
mScriptPatternMap["angle_cone"]="PSYS_SRC_PATTERN_ANGLE_CONE";
|
|
|
|
|
mScriptPatternMap["angle_cone_empty"]="PSYS_SRC_PATTERN_ANGLE_CONE_EMPTY";
|
|
|
|
|
mScriptPatternMap["drop"] = "PSYS_SRC_PATTERN_DROP";
|
|
|
|
|
mScriptPatternMap["explode"] = "PSYS_SRC_PATTERN_EXPLODE";
|
|
|
|
|
mScriptPatternMap["angle"] = "PSYS_SRC_PATTERN_ANGLE";
|
|
|
|
|
mScriptPatternMap["angle_cone"] = "PSYS_SRC_PATTERN_ANGLE_CONE";
|
|
|
|
|
mScriptPatternMap["angle_cone_empty"] = "PSYS_SRC_PATTERN_ANGLE_CONE_EMPTY";
|
|
|
|
|
|
|
|
|
|
mBlendMap["blend_one"]=LLPartData::LL_PART_BF_ONE;
|
|
|
|
|
mBlendMap["blend_zero"]=LLPartData::LL_PART_BF_ZERO;
|
|
|
|
|
mBlendMap["blend_dest_color"]=LLPartData::LL_PART_BF_DEST_COLOR;
|
|
|
|
|
mBlendMap["blend_src_color"]=LLPartData::LL_PART_BF_SOURCE_COLOR;
|
|
|
|
|
mBlendMap["blend_one_minus_dest_color"]=LLPartData::LL_PART_BF_ONE_MINUS_DEST_COLOR;
|
|
|
|
|
mBlendMap["blend_one_minus_src_color"]=LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_COLOR;
|
|
|
|
|
mBlendMap["blend_src_alpha"]=LLPartData::LL_PART_BF_SOURCE_ALPHA;
|
|
|
|
|
mBlendMap["blend_one_minus_src_alpha"]=LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA;
|
|
|
|
|
mBlendMap["blend_one"] = LLPartData::LL_PART_BF_ONE;
|
|
|
|
|
mBlendMap["blend_zero"] = LLPartData::LL_PART_BF_ZERO;
|
|
|
|
|
mBlendMap["blend_dest_color"] = LLPartData::LL_PART_BF_DEST_COLOR;
|
|
|
|
|
mBlendMap["blend_src_color"] = LLPartData::LL_PART_BF_SOURCE_COLOR;
|
|
|
|
|
mBlendMap["blend_one_minus_dest_color"] = LLPartData::LL_PART_BF_ONE_MINUS_DEST_COLOR;
|
|
|
|
|
mBlendMap["blend_one_minus_src_color"] = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_COLOR;
|
|
|
|
|
mBlendMap["blend_src_alpha"] = LLPartData::LL_PART_BF_SOURCE_ALPHA;
|
|
|
|
|
mBlendMap["blend_one_minus_src_alpha"] = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA;
|
|
|
|
|
|
|
|
|
|
mScriptBlendMap["blend_one"]="PSYS_PART_BF_ONE";
|
|
|
|
|
mScriptBlendMap["blend_zero"]="PSYS_PART_BF_ZERO";
|
|
|
|
|
mScriptBlendMap["blend_dest_color"]="PSYS_PART_BF_DEST_COLOR";
|
|
|
|
|
mScriptBlendMap["blend_src_color"]="PSYS_PART_BF_SOURCE_COLOR";
|
|
|
|
|
mScriptBlendMap["blend_one_minus_dest_color"]="PSYS_PART_BF_ONE_MINUS_DEST_COLOR";
|
|
|
|
|
mScriptBlendMap["blend_one_minus_src_color"]="PSYS_PART_BF_ONE_MINUS_SOURCE_COLOR";
|
|
|
|
|
mScriptBlendMap["blend_src_alpha"]="PSYS_PART_BF_SOURCE_ALPHA";
|
|
|
|
|
mScriptBlendMap["blend_one_minus_src_alpha"]="PSYS_PART_BF_ONE_MINUS_SOURCE_ALPHA";
|
|
|
|
|
mScriptBlendMap["blend_one"] = "PSYS_PART_BF_ONE";
|
|
|
|
|
mScriptBlendMap["blend_zero"] = "PSYS_PART_BF_ZERO";
|
|
|
|
|
mScriptBlendMap["blend_dest_color"] = "PSYS_PART_BF_DEST_COLOR";
|
|
|
|
|
mScriptBlendMap["blend_src_color"] = "PSYS_PART_BF_SOURCE_COLOR";
|
|
|
|
|
mScriptBlendMap["blend_one_minus_dest_color"] = "PSYS_PART_BF_ONE_MINUS_DEST_COLOR";
|
|
|
|
|
mScriptBlendMap["blend_one_minus_src_color"] = "PSYS_PART_BF_ONE_MINUS_SOURCE_COLOR";
|
|
|
|
|
mScriptBlendMap["blend_src_alpha"] = "PSYS_PART_BF_SOURCE_ALPHA";
|
|
|
|
|
mScriptBlendMap["blend_one_minus_src_alpha"] = "PSYS_PART_BF_ONE_MINUS_SOURCE_ALPHA";
|
|
|
|
|
|
|
|
|
|
// I don't really like referencing the particle texture name here, but it's being done
|
|
|
|
|
// like this all over the viewer, so this is apparently how it's meant to be. -Zi
|
|
|
|
|
mDefaultParticleTexture=LLViewerTextureManager::getFetchedTextureFromFile("pixiesmall.j2c");
|
|
|
|
|
mDefaultParticleTexture = LLViewerTextureManager::getFetchedTextureFromFile("pixiesmall.j2c");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ParticleEditor::~ParticleEditor()
|
|
|
|
|
@ -101,117 +101,117 @@ ParticleEditor::~ParticleEditor()
|
|
|
|
|
|
|
|
|
|
BOOL ParticleEditor::postBuild()
|
|
|
|
|
{
|
|
|
|
|
LLPanel* panel=getChild<LLPanel>("particle_editor_panel");
|
|
|
|
|
LLPanel* panel = getChild<LLPanel>("particle_editor_panel");
|
|
|
|
|
|
|
|
|
|
mMainPanel=panel;
|
|
|
|
|
mMainPanel = panel;
|
|
|
|
|
|
|
|
|
|
mPatternTypeCombo=panel->getChild<LLComboBox>("pattern_type_combo");
|
|
|
|
|
mTexturePicker=panel->getChild<LLTextureCtrl>("texture_picker");
|
|
|
|
|
mPatternTypeCombo = panel->getChild<LLComboBox>("pattern_type_combo");
|
|
|
|
|
mTexturePicker = panel->getChild<LLTextureCtrl>("texture_picker");
|
|
|
|
|
|
|
|
|
|
mBurstRateSpinner=panel->getChild<LLSpinCtrl>("burst_rate_spinner");
|
|
|
|
|
mBurstCountSpinner=panel->getChild<LLSpinCtrl>("burst_count_spinner");
|
|
|
|
|
mBurstRadiusSpinner=panel->getChild<LLSpinCtrl>("burst_radius_spinner");
|
|
|
|
|
mAngleBeginSpinner=panel->getChild<LLSpinCtrl>("angle_begin_spinner");
|
|
|
|
|
mAngleEndSpinner=panel->getChild<LLSpinCtrl>("angle_end_spinner");
|
|
|
|
|
mBurstSpeedMinSpinner=panel->getChild<LLSpinCtrl>("burst_speed_min_spinner");
|
|
|
|
|
mBurstSpeedMaxSpinner=panel->getChild<LLSpinCtrl>("burst_speed_max_spinner");
|
|
|
|
|
mStartAlphaSpinner=panel->getChild<LLSpinCtrl>("start_alpha_spinner");
|
|
|
|
|
mEndAlphaSpinner=panel->getChild<LLSpinCtrl>("end_alpha_spinner");
|
|
|
|
|
mScaleStartXSpinner=panel->getChild<LLSpinCtrl>("scale_start_x_spinner");
|
|
|
|
|
mScaleStartYSpinner=panel->getChild<LLSpinCtrl>("scale_start_y_spinner");
|
|
|
|
|
mScaleEndXSpinner=panel->getChild<LLSpinCtrl>("scale_end_x_spinner");
|
|
|
|
|
mScaleEndYSpinner=panel->getChild<LLSpinCtrl>("scale_end_y_spinner");
|
|
|
|
|
mSourceMaxAgeSpinner=panel->getChild<LLSpinCtrl>("source_max_age_spinner");
|
|
|
|
|
mParticlesMaxAgeSpinner=panel->getChild<LLSpinCtrl>("particles_max_age_spinner");
|
|
|
|
|
mStartGlowSpinner=panel->getChild<LLSpinCtrl>("start_glow_spinner");
|
|
|
|
|
mEndGlowSpinner=panel->getChild<LLSpinCtrl>("end_glow_spinner");
|
|
|
|
|
mBurstRateSpinner = panel->getChild<LLSpinCtrl>("burst_rate_spinner");
|
|
|
|
|
mBurstCountSpinner = panel->getChild<LLSpinCtrl>("burst_count_spinner");
|
|
|
|
|
mBurstRadiusSpinner = panel->getChild<LLSpinCtrl>("burst_radius_spinner");
|
|
|
|
|
mAngleBeginSpinner = panel->getChild<LLSpinCtrl>("angle_begin_spinner");
|
|
|
|
|
mAngleEndSpinner = panel->getChild<LLSpinCtrl>("angle_end_spinner");
|
|
|
|
|
mBurstSpeedMinSpinner = panel->getChild<LLSpinCtrl>("burst_speed_min_spinner");
|
|
|
|
|
mBurstSpeedMaxSpinner = panel->getChild<LLSpinCtrl>("burst_speed_max_spinner");
|
|
|
|
|
mStartAlphaSpinner = panel->getChild<LLSpinCtrl>("start_alpha_spinner");
|
|
|
|
|
mEndAlphaSpinner = panel->getChild<LLSpinCtrl>("end_alpha_spinner");
|
|
|
|
|
mScaleStartXSpinner = panel->getChild<LLSpinCtrl>("scale_start_x_spinner");
|
|
|
|
|
mScaleStartYSpinner = panel->getChild<LLSpinCtrl>("scale_start_y_spinner");
|
|
|
|
|
mScaleEndXSpinner = panel->getChild<LLSpinCtrl>("scale_end_x_spinner");
|
|
|
|
|
mScaleEndYSpinner = panel->getChild<LLSpinCtrl>("scale_end_y_spinner");
|
|
|
|
|
mSourceMaxAgeSpinner = panel->getChild<LLSpinCtrl>("source_max_age_spinner");
|
|
|
|
|
mParticlesMaxAgeSpinner = panel->getChild<LLSpinCtrl>("particles_max_age_spinner");
|
|
|
|
|
mStartGlowSpinner = panel->getChild<LLSpinCtrl>("start_glow_spinner");
|
|
|
|
|
mEndGlowSpinner = panel->getChild<LLSpinCtrl>("end_glow_spinner");
|
|
|
|
|
|
|
|
|
|
mBlendFuncSrcCombo=panel->getChild<LLComboBox>("blend_func_src_combo");
|
|
|
|
|
mBlendFuncDestCombo=panel->getChild<LLComboBox>("blend_func_dest_combo");
|
|
|
|
|
mBlendFuncSrcCombo = panel->getChild<LLComboBox>("blend_func_src_combo");
|
|
|
|
|
mBlendFuncDestCombo = panel->getChild<LLComboBox>("blend_func_dest_combo");
|
|
|
|
|
|
|
|
|
|
mBounceCheckBox=panel->getChild<LLCheckBoxCtrl>("bounce_checkbox");
|
|
|
|
|
mEmissiveCheckBox=panel->getChild<LLCheckBoxCtrl>("emissive_checkbox");
|
|
|
|
|
mFollowSourceCheckBox=panel->getChild<LLCheckBoxCtrl>("follow_source_checkbox");
|
|
|
|
|
mFollowVelocityCheckBox=panel->getChild<LLCheckBoxCtrl>("follow_velocity_checkbox");
|
|
|
|
|
mInterpolateColorCheckBox=panel->getChild<LLCheckBoxCtrl>("interpolate_color_checkbox");
|
|
|
|
|
mInterpolateScaleCheckBox=panel->getChild<LLCheckBoxCtrl>("interpolate_scale_checkbox");
|
|
|
|
|
mTargetPositionCheckBox=panel->getChild<LLCheckBoxCtrl>("target_position_checkbox");
|
|
|
|
|
mTargetLinearCheckBox=panel->getChild<LLCheckBoxCtrl>("target_linear_checkbox");
|
|
|
|
|
mWindCheckBox=panel->getChild<LLCheckBoxCtrl>("wind_checkbox");
|
|
|
|
|
mRibbonCheckBox=panel->getChild<LLCheckBoxCtrl>("ribbon_checkbox");
|
|
|
|
|
mBounceCheckBox = panel->getChild<LLCheckBoxCtrl>("bounce_checkbox");
|
|
|
|
|
mEmissiveCheckBox = panel->getChild<LLCheckBoxCtrl>("emissive_checkbox");
|
|
|
|
|
mFollowSourceCheckBox = panel->getChild<LLCheckBoxCtrl>("follow_source_checkbox");
|
|
|
|
|
mFollowVelocityCheckBox = panel->getChild<LLCheckBoxCtrl>("follow_velocity_checkbox");
|
|
|
|
|
mInterpolateColorCheckBox = panel->getChild<LLCheckBoxCtrl>("interpolate_color_checkbox");
|
|
|
|
|
mInterpolateScaleCheckBox = panel->getChild<LLCheckBoxCtrl>("interpolate_scale_checkbox");
|
|
|
|
|
mTargetPositionCheckBox = panel->getChild<LLCheckBoxCtrl>("target_position_checkbox");
|
|
|
|
|
mTargetLinearCheckBox = panel->getChild<LLCheckBoxCtrl>("target_linear_checkbox");
|
|
|
|
|
mWindCheckBox = panel->getChild<LLCheckBoxCtrl>("wind_checkbox");
|
|
|
|
|
mRibbonCheckBox = panel->getChild<LLCheckBoxCtrl>("ribbon_checkbox");
|
|
|
|
|
|
|
|
|
|
mTargetKeyInput=panel->getChild<LLLineEditor>("target_key_input");
|
|
|
|
|
mTargetKeyInput = panel->getChild<LLLineEditor>("target_key_input");
|
|
|
|
|
|
|
|
|
|
mAcellerationXSpinner=panel->getChild<LLSpinCtrl>("acceleration_x_spinner");
|
|
|
|
|
mAcellerationYSpinner=panel->getChild<LLSpinCtrl>("acceleration_y_spinner");
|
|
|
|
|
mAcellerationZSpinner=panel->getChild<LLSpinCtrl>("acceleration_z_spinner");
|
|
|
|
|
mAcellerationXSpinner = panel->getChild<LLSpinCtrl>("acceleration_x_spinner");
|
|
|
|
|
mAcellerationYSpinner = panel->getChild<LLSpinCtrl>("acceleration_y_spinner");
|
|
|
|
|
mAcellerationZSpinner = panel->getChild<LLSpinCtrl>("acceleration_z_spinner");
|
|
|
|
|
|
|
|
|
|
mOmegaXSpinner=panel->getChild<LLSpinCtrl>("omega_x_spinner");
|
|
|
|
|
mOmegaYSpinner=panel->getChild<LLSpinCtrl>("omega_y_spinner");
|
|
|
|
|
mOmegaZSpinner=panel->getChild<LLSpinCtrl>("omega_z_spinner");
|
|
|
|
|
mOmegaXSpinner = panel->getChild<LLSpinCtrl>("omega_x_spinner");
|
|
|
|
|
mOmegaYSpinner = panel->getChild<LLSpinCtrl>("omega_y_spinner");
|
|
|
|
|
mOmegaZSpinner = panel->getChild<LLSpinCtrl>("omega_z_spinner");
|
|
|
|
|
|
|
|
|
|
mStartColorSelector=panel->getChild<LLColorSwatchCtrl>("start_color_selector");
|
|
|
|
|
mEndColorSelector=panel->getChild<LLColorSwatchCtrl>("end_color_selector");
|
|
|
|
|
mStartColorSelector = panel->getChild<LLColorSwatchCtrl>("start_color_selector");
|
|
|
|
|
mEndColorSelector = panel->getChild<LLColorSwatchCtrl>("end_color_selector");
|
|
|
|
|
|
|
|
|
|
mCopyToLSLButton=panel->getChild<LLButton>("copy_button");
|
|
|
|
|
mCopyToLSLButton->setCommitCallback(boost::bind(&ParticleEditor::onCopyButtonClicked,this));
|
|
|
|
|
mCopyToLSLButton = panel->getChild<LLButton>("copy_button");
|
|
|
|
|
mCopyToLSLButton->setCommitCallback(boost::bind(&ParticleEditor::onCopyButtonClicked, this));
|
|
|
|
|
|
|
|
|
|
mInjectScriptButton=panel->getChild<LLButton>("inject_button");
|
|
|
|
|
mInjectScriptButton->setCommitCallback(boost::bind(&ParticleEditor::onInjectButtonClicked,this));
|
|
|
|
|
mInjectScriptButton = panel->getChild<LLButton>("inject_button");
|
|
|
|
|
mInjectScriptButton->setCommitCallback(boost::bind(&ParticleEditor::onInjectButtonClicked, this));
|
|
|
|
|
|
|
|
|
|
mClearTargetButton=panel->getChild<LLButton>("clear_target_button");
|
|
|
|
|
mClearTargetButton->setCommitCallback(boost::bind(&ParticleEditor::onClearTargetButtonClicked,this));
|
|
|
|
|
mClearTargetButton = panel->getChild<LLButton>("clear_target_button");
|
|
|
|
|
mClearTargetButton->setCommitCallback(boost::bind(&ParticleEditor::onClearTargetButtonClicked, this));
|
|
|
|
|
|
|
|
|
|
mPickTargetButton=panel->getChild<LLButton>("pick_target_button");
|
|
|
|
|
mPickTargetButton->setCommitCallback(boost::bind(&ParticleEditor::onTargetPickerButtonClicked,this));
|
|
|
|
|
mPickTargetButton = panel->getChild<LLButton>("pick_target_button");
|
|
|
|
|
mPickTargetButton->setCommitCallback(boost::bind(&ParticleEditor::onTargetPickerButtonClicked, this));
|
|
|
|
|
|
|
|
|
|
mPatternTypeCombo->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange,this));
|
|
|
|
|
mTexturePicker->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange,this));
|
|
|
|
|
mPatternTypeCombo->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange, this));
|
|
|
|
|
mTexturePicker->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange, this));
|
|
|
|
|
|
|
|
|
|
mBurstRateSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange,this));
|
|
|
|
|
mBurstCountSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange,this));
|
|
|
|
|
mBurstRadiusSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange,this));
|
|
|
|
|
mAngleBeginSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange,this));
|
|
|
|
|
mAngleEndSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange,this));
|
|
|
|
|
mBurstSpeedMinSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange,this));
|
|
|
|
|
mBurstSpeedMaxSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange,this));
|
|
|
|
|
mStartAlphaSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange,this));
|
|
|
|
|
mEndAlphaSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange,this));
|
|
|
|
|
mScaleStartXSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange,this));
|
|
|
|
|
mScaleStartYSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange,this));
|
|
|
|
|
mScaleEndXSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange,this));
|
|
|
|
|
mScaleEndYSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange,this));
|
|
|
|
|
mSourceMaxAgeSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange,this));
|
|
|
|
|
mParticlesMaxAgeSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange,this));
|
|
|
|
|
mStartGlowSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange,this));
|
|
|
|
|
mEndGlowSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange,this));
|
|
|
|
|
mBurstRateSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange, this));
|
|
|
|
|
mBurstCountSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange, this));
|
|
|
|
|
mBurstRadiusSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange, this));
|
|
|
|
|
mAngleBeginSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange, this));
|
|
|
|
|
mAngleEndSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange, this));
|
|
|
|
|
mBurstSpeedMinSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange, this));
|
|
|
|
|
mBurstSpeedMaxSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange, this));
|
|
|
|
|
mStartAlphaSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange, this));
|
|
|
|
|
mEndAlphaSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange, this));
|
|
|
|
|
mScaleStartXSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange, this));
|
|
|
|
|
mScaleStartYSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange, this));
|
|
|
|
|
mScaleEndXSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange, this));
|
|
|
|
|
mScaleEndYSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange, this));
|
|
|
|
|
mSourceMaxAgeSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange, this));
|
|
|
|
|
mParticlesMaxAgeSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange, this));
|
|
|
|
|
mStartGlowSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange, this));
|
|
|
|
|
mEndGlowSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange, this));
|
|
|
|
|
|
|
|
|
|
mBlendFuncSrcCombo->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange,this));
|
|
|
|
|
mBlendFuncDestCombo->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange,this));
|
|
|
|
|
mBlendFuncSrcCombo->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange, this));
|
|
|
|
|
mBlendFuncDestCombo->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange, this));
|
|
|
|
|
|
|
|
|
|
mBounceCheckBox->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange,this));
|
|
|
|
|
mEmissiveCheckBox->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange,this));
|
|
|
|
|
mFollowSourceCheckBox->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange,this));
|
|
|
|
|
mFollowVelocityCheckBox->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange,this));
|
|
|
|
|
mInterpolateColorCheckBox->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange,this));
|
|
|
|
|
mInterpolateScaleCheckBox->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange,this));
|
|
|
|
|
mTargetPositionCheckBox->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange,this));
|
|
|
|
|
mTargetLinearCheckBox->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange,this));
|
|
|
|
|
mWindCheckBox->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange,this));
|
|
|
|
|
mRibbonCheckBox->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange,this));
|
|
|
|
|
mBounceCheckBox->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange, this));
|
|
|
|
|
mEmissiveCheckBox->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange, this));
|
|
|
|
|
mFollowSourceCheckBox->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange, this));
|
|
|
|
|
mFollowVelocityCheckBox->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange, this));
|
|
|
|
|
mInterpolateColorCheckBox->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange, this));
|
|
|
|
|
mInterpolateScaleCheckBox->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange, this));
|
|
|
|
|
mTargetPositionCheckBox->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange, this));
|
|
|
|
|
mTargetLinearCheckBox->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange, this));
|
|
|
|
|
mWindCheckBox->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange, this));
|
|
|
|
|
mRibbonCheckBox->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange, this));
|
|
|
|
|
|
|
|
|
|
mTargetKeyInput->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange,this));
|
|
|
|
|
mTargetKeyInput->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange, this));
|
|
|
|
|
|
|
|
|
|
mAcellerationXSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange,this));
|
|
|
|
|
mAcellerationYSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange,this));
|
|
|
|
|
mAcellerationZSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange,this));
|
|
|
|
|
mAcellerationXSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange, this));
|
|
|
|
|
mAcellerationYSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange, this));
|
|
|
|
|
mAcellerationZSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange, this));
|
|
|
|
|
|
|
|
|
|
mOmegaXSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange,this));
|
|
|
|
|
mOmegaYSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange,this));
|
|
|
|
|
mOmegaZSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange,this));
|
|
|
|
|
mOmegaXSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange, this));
|
|
|
|
|
mOmegaYSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange, this));
|
|
|
|
|
mOmegaZSpinner->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange, this));
|
|
|
|
|
|
|
|
|
|
mStartColorSelector->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange,this));
|
|
|
|
|
mEndColorSelector->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange,this));
|
|
|
|
|
mStartColorSelector->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange, this));
|
|
|
|
|
mEndColorSelector->setCommitCallback(boost::bind(&ParticleEditor::onParameterChange, this));
|
|
|
|
|
|
|
|
|
|
mStartColorSelector->setCanApplyImmediately(TRUE);
|
|
|
|
|
mEndColorSelector->setCanApplyImmediately(TRUE);
|
|
|
|
|
@ -227,7 +227,7 @@ BOOL ParticleEditor::postBuild()
|
|
|
|
|
|
|
|
|
|
void ParticleEditor::clearParticles()
|
|
|
|
|
{
|
|
|
|
|
if(!mObject)
|
|
|
|
|
if (!mObject)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
LL_DEBUGS() << "clearing particles from " << mObject->getID() << LL_ENDL;
|
|
|
|
|
@ -237,11 +237,11 @@ void ParticleEditor::clearParticles()
|
|
|
|
|
|
|
|
|
|
void ParticleEditor::updateParticles()
|
|
|
|
|
{
|
|
|
|
|
if(!mObject)
|
|
|
|
|
if (!mObject)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
clearParticles();
|
|
|
|
|
LLPointer<LLViewerPartSourceScript> pss=LLViewerPartSourceScript::createPSS(mObject,mParticles);
|
|
|
|
|
LLPointer<LLViewerPartSourceScript> pss = LLViewerPartSourceScript::createPSS(mObject, mParticles);
|
|
|
|
|
|
|
|
|
|
pss->setOwnerUUID(mObject->getID());
|
|
|
|
|
pss->setImage(mTexture);
|
|
|
|
|
@ -251,9 +251,9 @@ void ParticleEditor::updateParticles()
|
|
|
|
|
|
|
|
|
|
void ParticleEditor::setObject(LLViewerObject* objectp)
|
|
|
|
|
{
|
|
|
|
|
if(objectp)
|
|
|
|
|
if (objectp)
|
|
|
|
|
{
|
|
|
|
|
mObject=objectp;
|
|
|
|
|
mObject = objectp;
|
|
|
|
|
|
|
|
|
|
LL_DEBUGS() << "adding particles to " << mObject->getID() << LL_ENDL;
|
|
|
|
|
|
|
|
|
|
@ -263,59 +263,61 @@ void ParticleEditor::setObject(LLViewerObject* objectp)
|
|
|
|
|
|
|
|
|
|
void ParticleEditor::onParameterChange()
|
|
|
|
|
{
|
|
|
|
|
mParticles.mPattern=mPatternMap[mPatternTypeCombo->getSelectedValue()];
|
|
|
|
|
mParticles.mPartImageID=mTexturePicker->getImageAssetID();
|
|
|
|
|
mParticles.mPattern = mPatternMap[mPatternTypeCombo->getSelectedValue()];
|
|
|
|
|
mParticles.mPartImageID = mTexturePicker->getImageAssetID();
|
|
|
|
|
|
|
|
|
|
// remember the selected texture here to give updateParticles() a UUID to work with
|
|
|
|
|
mTexture=LLViewerTextureManager::getFetchedTexture(mTexturePicker->getImageAssetID());
|
|
|
|
|
mTexture = LLViewerTextureManager::getFetchedTexture(mTexturePicker->getImageAssetID());
|
|
|
|
|
|
|
|
|
|
if(mTexture->getID()==IMG_DEFAULT || mTexture->getID().isNull())
|
|
|
|
|
mTexture=mDefaultParticleTexture;
|
|
|
|
|
if (mTexture->getID() == IMG_DEFAULT || mTexture->getID().isNull())
|
|
|
|
|
{
|
|
|
|
|
mTexture = mDefaultParticleTexture;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// limit burst rate to 0.01 to avoid internal freeze, script still gets the real value
|
|
|
|
|
mParticles.mBurstRate=llmax(0.01f,mBurstRateSpinner->getValueF32());
|
|
|
|
|
mParticles.mBurstPartCount=mBurstCountSpinner->getValue().asInteger();
|
|
|
|
|
mParticles.mBurstRadius=mBurstRadiusSpinner->getValueF32();
|
|
|
|
|
mParticles.mInnerAngle=mAngleBeginSpinner->getValueF32();
|
|
|
|
|
mParticles.mOuterAngle=mAngleEndSpinner->getValueF32();
|
|
|
|
|
mParticles.mBurstSpeedMin=mBurstSpeedMinSpinner->getValueF32();
|
|
|
|
|
mParticles.mBurstSpeedMax=mBurstSpeedMaxSpinner->getValueF32();
|
|
|
|
|
mParticles.mBurstRate = llmax(0.01f, mBurstRateSpinner->getValueF32());
|
|
|
|
|
mParticles.mBurstPartCount = mBurstCountSpinner->getValue().asInteger();
|
|
|
|
|
mParticles.mBurstRadius = mBurstRadiusSpinner->getValueF32();
|
|
|
|
|
mParticles.mInnerAngle = mAngleBeginSpinner->getValueF32();
|
|
|
|
|
mParticles.mOuterAngle = mAngleEndSpinner->getValueF32();
|
|
|
|
|
mParticles.mBurstSpeedMin = mBurstSpeedMinSpinner->getValueF32();
|
|
|
|
|
mParticles.mBurstSpeedMax = mBurstSpeedMaxSpinner->getValueF32();
|
|
|
|
|
mParticles.mPartData.setStartAlpha(mStartAlphaSpinner->getValueF32());
|
|
|
|
|
mParticles.mPartData.setEndAlpha(mEndAlphaSpinner->getValueF32());
|
|
|
|
|
mParticles.mPartData.setStartScale(mScaleStartXSpinner->getValueF32(),mScaleStartYSpinner->getValueF32());
|
|
|
|
|
mParticles.mPartData.setEndScale(mScaleEndXSpinner->getValueF32(),mScaleEndYSpinner->getValueF32());
|
|
|
|
|
mParticles.mMaxAge=mSourceMaxAgeSpinner->getValueF32();
|
|
|
|
|
mParticles.mPartData.setStartScale(mScaleStartXSpinner->getValueF32(), mScaleStartYSpinner->getValueF32());
|
|
|
|
|
mParticles.mPartData.setEndScale(mScaleEndXSpinner->getValueF32(), mScaleEndYSpinner->getValueF32());
|
|
|
|
|
mParticles.mMaxAge = mSourceMaxAgeSpinner->getValueF32();
|
|
|
|
|
mParticles.mPartData.setMaxAge(mParticlesMaxAgeSpinner->getValueF32());
|
|
|
|
|
|
|
|
|
|
// different way to set values here, ask Linden Lab why -Zi
|
|
|
|
|
mParticles.mPartData.mStartGlow=mStartGlowSpinner->getValueF32();
|
|
|
|
|
mParticles.mPartData.mEndGlow=mEndGlowSpinner->getValueF32();
|
|
|
|
|
mParticles.mPartData.mStartGlow = mStartGlowSpinner->getValueF32();
|
|
|
|
|
mParticles.mPartData.mEndGlow = mEndGlowSpinner->getValueF32();
|
|
|
|
|
|
|
|
|
|
mParticles.mPartData.mBlendFuncSource=mBlendMap[mBlendFuncSrcCombo->getSelectedValue()];
|
|
|
|
|
mParticles.mPartData.mBlendFuncDest=mBlendMap[mBlendFuncDestCombo->getSelectedValue()];
|
|
|
|
|
mParticles.mPartData.mBlendFuncSource = mBlendMap[mBlendFuncSrcCombo->getSelectedValue()];
|
|
|
|
|
mParticles.mPartData.mBlendFuncDest = mBlendMap[mBlendFuncDestCombo->getSelectedValue()];
|
|
|
|
|
|
|
|
|
|
U32 flags=0;
|
|
|
|
|
if(mBounceCheckBox->getValue().asBoolean()) flags|=LLPartData::LL_PART_BOUNCE_MASK;
|
|
|
|
|
if(mEmissiveCheckBox->getValue().asBoolean()) flags|=LLPartData::LL_PART_EMISSIVE_MASK;
|
|
|
|
|
if(mFollowSourceCheckBox->getValue().asBoolean()) flags|=LLPartData::LL_PART_FOLLOW_SRC_MASK;
|
|
|
|
|
if(mFollowVelocityCheckBox->getValue().asBoolean()) flags|=LLPartData::LL_PART_FOLLOW_VELOCITY_MASK;
|
|
|
|
|
if(mInterpolateColorCheckBox->getValue().asBoolean()) flags|=LLPartData::LL_PART_INTERP_COLOR_MASK;
|
|
|
|
|
if(mInterpolateScaleCheckBox->getValue().asBoolean()) flags|=LLPartData::LL_PART_INTERP_SCALE_MASK;
|
|
|
|
|
if(mTargetPositionCheckBox->getValue().asBoolean()) flags|=LLPartData::LL_PART_TARGET_POS_MASK;
|
|
|
|
|
if(mTargetLinearCheckBox->getValue().asBoolean()) flags|=LLPartData::LL_PART_TARGET_LINEAR_MASK;
|
|
|
|
|
if(mWindCheckBox->getValue().asBoolean()) flags|=LLPartData::LL_PART_WIND_MASK;
|
|
|
|
|
if(mRibbonCheckBox->getValue().asBoolean()) flags|=LLPartData::LL_PART_RIBBON_MASK;
|
|
|
|
|
U32 flags = 0;
|
|
|
|
|
if (mBounceCheckBox->getValue().asBoolean()) flags |= LLPartData::LL_PART_BOUNCE_MASK;
|
|
|
|
|
if (mEmissiveCheckBox->getValue().asBoolean()) flags |= LLPartData::LL_PART_EMISSIVE_MASK;
|
|
|
|
|
if (mFollowSourceCheckBox->getValue().asBoolean()) flags |= LLPartData::LL_PART_FOLLOW_SRC_MASK;
|
|
|
|
|
if (mFollowVelocityCheckBox->getValue().asBoolean()) flags |= LLPartData::LL_PART_FOLLOW_VELOCITY_MASK;
|
|
|
|
|
if (mInterpolateColorCheckBox->getValue().asBoolean()) flags |= LLPartData::LL_PART_INTERP_COLOR_MASK;
|
|
|
|
|
if (mInterpolateScaleCheckBox->getValue().asBoolean()) flags |= LLPartData::LL_PART_INTERP_SCALE_MASK;
|
|
|
|
|
if (mTargetPositionCheckBox->getValue().asBoolean()) flags |= LLPartData::LL_PART_TARGET_POS_MASK;
|
|
|
|
|
if (mTargetLinearCheckBox->getValue().asBoolean()) flags |= LLPartData::LL_PART_TARGET_LINEAR_MASK;
|
|
|
|
|
if (mWindCheckBox->getValue().asBoolean()) flags |= LLPartData::LL_PART_WIND_MASK;
|
|
|
|
|
if (mRibbonCheckBox->getValue().asBoolean()) flags |= LLPartData::LL_PART_RIBBON_MASK;
|
|
|
|
|
mParticles.mPartData.setFlags(flags);
|
|
|
|
|
|
|
|
|
|
mParticles.mTargetUUID=mTargetKeyInput->getValue().asUUID();
|
|
|
|
|
mParticles.mTargetUUID = mTargetKeyInput->getValue().asUUID();
|
|
|
|
|
|
|
|
|
|
mParticles.mPartAccel=LLVector3(mAcellerationXSpinner->getValueF32(),mAcellerationYSpinner->getValueF32(),mAcellerationZSpinner->getValueF32());
|
|
|
|
|
mParticles.mAngularVelocity=LLVector3(mOmegaXSpinner->getValueF32(),mOmegaYSpinner->getValueF32(),mOmegaZSpinner->getValueF32());
|
|
|
|
|
mParticles.mPartAccel = LLVector3(mAcellerationXSpinner->getValueF32(), mAcellerationYSpinner->getValueF32(), mAcellerationZSpinner->getValueF32());
|
|
|
|
|
mParticles.mAngularVelocity = LLVector3(mOmegaXSpinner->getValueF32(), mOmegaYSpinner->getValueF32(), mOmegaZSpinner->getValueF32());
|
|
|
|
|
|
|
|
|
|
LLColor4 color=mStartColorSelector->get();
|
|
|
|
|
mParticles.mPartData.setStartColor(LLVector3(color.mV[0],color.mV[1],color.mV[2]));
|
|
|
|
|
color=mEndColorSelector->get();
|
|
|
|
|
mParticles.mPartData.setEndColor(LLVector3(color.mV[0],color.mV[1],color.mV[2]));
|
|
|
|
|
LLColor4 color = mStartColorSelector->get();
|
|
|
|
|
mParticles.mPartData.setStartColor(LLVector3(color.mV[VX], color.mV[VY], color.mV[VZ]));
|
|
|
|
|
color = mEndColorSelector->get();
|
|
|
|
|
mParticles.mPartData.setEndColor(LLVector3(color.mV[VX], color.mV[VY], color.mV[VZ]));
|
|
|
|
|
|
|
|
|
|
updateUI();
|
|
|
|
|
updateParticles();
|
|
|
|
|
@ -323,20 +325,20 @@ void ParticleEditor::onParameterChange()
|
|
|
|
|
|
|
|
|
|
void ParticleEditor::updateUI()
|
|
|
|
|
{
|
|
|
|
|
U8 pattern=mPatternMap[mPatternTypeCombo->getValue()];
|
|
|
|
|
BOOL dropPattern=(pattern==LLPartSysData::LL_PART_SRC_PATTERN_DROP);
|
|
|
|
|
BOOL explodePattern=(pattern==LLPartSysData::LL_PART_SRC_PATTERN_EXPLODE);
|
|
|
|
|
BOOL targetLinear=mTargetLinearCheckBox->getValue();
|
|
|
|
|
BOOL interpolateColor=mInterpolateColorCheckBox->getValue();
|
|
|
|
|
BOOL interpolateScale=mInterpolateScaleCheckBox->getValue();
|
|
|
|
|
BOOL targetEnabled=targetLinear | (mTargetPositionCheckBox->getValue().asBoolean() ? TRUE : FALSE);
|
|
|
|
|
U8 pattern = mPatternMap[mPatternTypeCombo->getValue()];
|
|
|
|
|
BOOL dropPattern = (pattern == LLPartSysData::LL_PART_SRC_PATTERN_DROP);
|
|
|
|
|
BOOL explodePattern = (pattern == LLPartSysData::LL_PART_SRC_PATTERN_EXPLODE);
|
|
|
|
|
BOOL targetLinear = mTargetLinearCheckBox->getValue();
|
|
|
|
|
BOOL interpolateColor = mInterpolateColorCheckBox->getValue();
|
|
|
|
|
BOOL interpolateScale = mInterpolateScaleCheckBox->getValue();
|
|
|
|
|
BOOL targetEnabled = targetLinear | (mTargetPositionCheckBox->getValue().asBoolean() ? TRUE : FALSE);
|
|
|
|
|
|
|
|
|
|
mBurstRadiusSpinner->setEnabled(!(targetLinear | (mFollowSourceCheckBox->getValue().asBoolean() ? TRUE : FALSE) | dropPattern));
|
|
|
|
|
mBurstSpeedMinSpinner->setEnabled(!(targetLinear | dropPattern));
|
|
|
|
|
mBurstSpeedMaxSpinner->setEnabled(!(targetLinear | dropPattern));
|
|
|
|
|
|
|
|
|
|
// disabling a color swatch does nothing visually, so we also set alpha
|
|
|
|
|
LLColor4 endColor=mEndColorSelector->get();
|
|
|
|
|
LLColor4 endColor = mEndColorSelector->get();
|
|
|
|
|
endColor.setAlpha(interpolateColor ? 1.0f : 0.0f);
|
|
|
|
|
|
|
|
|
|
mEndAlphaSpinner->setEnabled(interpolateColor);
|
|
|
|
|
@ -380,38 +382,38 @@ void ParticleEditor::onTargetPickerButtonClicked()
|
|
|
|
|
// static
|
|
|
|
|
void ParticleEditor::startPicking(void* userdata)
|
|
|
|
|
{
|
|
|
|
|
ParticleEditor* self =(ParticleEditor*) userdata;
|
|
|
|
|
LLToolObjPicker::getInstance()->setExitCallback(ParticleEditor::onTargetPicked,self);
|
|
|
|
|
ParticleEditor* self = (ParticleEditor*) userdata;
|
|
|
|
|
LLToolObjPicker::getInstance()->setExitCallback(ParticleEditor::onTargetPicked, self);
|
|
|
|
|
LLToolMgr::getInstance()->setTransientTool(LLToolObjPicker::getInstance());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// static
|
|
|
|
|
void ParticleEditor::onTargetPicked(void* userdata)
|
|
|
|
|
{
|
|
|
|
|
ParticleEditor* self=(ParticleEditor*) userdata;
|
|
|
|
|
ParticleEditor* self = (ParticleEditor*)userdata;
|
|
|
|
|
|
|
|
|
|
LLUUID picked=LLToolObjPicker::getInstance()->getObjectID();
|
|
|
|
|
LLUUID picked = LLToolObjPicker::getInstance()->getObjectID();
|
|
|
|
|
|
|
|
|
|
LLToolMgr::getInstance()->clearTransientTool();
|
|
|
|
|
|
|
|
|
|
self->mPickTargetButton->setEnabled(TRUE);
|
|
|
|
|
self->mPickTargetButton->setToggleState(FALSE);
|
|
|
|
|
|
|
|
|
|
if(picked.notNull())
|
|
|
|
|
if (picked.notNull())
|
|
|
|
|
{
|
|
|
|
|
self->mTargetKeyInput->setValue(picked.asString());
|
|
|
|
|
self->onParameterChange();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string ParticleEditor::lslVector(F32 x,F32 y,F32 z)
|
|
|
|
|
std::string ParticleEditor::lslVector(F32 x, F32 y, F32 z)
|
|
|
|
|
{
|
|
|
|
|
return llformat("<%f,%f,%f>",x,y,z);
|
|
|
|
|
return llformat("<%f,%f,%f>", x, y, z);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string ParticleEditor::lslColor(const LLColor4& color)
|
|
|
|
|
{
|
|
|
|
|
return lslVector(color.mV[0],color.mV[1],color.mV[2]);
|
|
|
|
|
return lslVector(color.mV[VX], color.mV[VY], color.mV[VZ]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string ParticleEditor::createScript()
|
|
|
|
|
@ -454,67 +456,71 @@ default\n\
|
|
|
|
|
}\n\
|
|
|
|
|
}\n";
|
|
|
|
|
|
|
|
|
|
LLUUID targetKey=mTargetKeyInput->getValue().asUUID();
|
|
|
|
|
std::string keyString="llGetKey()";
|
|
|
|
|
LLUUID targetKey = mTargetKeyInput->getValue().asUUID();
|
|
|
|
|
std::string keyString = "llGetKey()";
|
|
|
|
|
|
|
|
|
|
if(!targetKey.isNull() && targetKey!=mObject->getID())
|
|
|
|
|
keyString="(key) \""+targetKey.asString()+"\"";
|
|
|
|
|
if (targetKey.notNull() && targetKey != mObject->getID())
|
|
|
|
|
{
|
|
|
|
|
keyString="(key) \"" + targetKey.asString() + "\"";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LLUUID textureKey=mTexture->getID();
|
|
|
|
|
LLUUID textureKey = mTexture->getID();
|
|
|
|
|
std::string textureString;
|
|
|
|
|
if(!textureKey.isNull() && textureKey!=IMG_DEFAULT && textureKey!=mDefaultParticleTexture->getID())
|
|
|
|
|
textureString=textureKey.asString();
|
|
|
|
|
if (textureKey.notNull() && textureKey != IMG_DEFAULT && textureKey != mDefaultParticleTexture->getID())
|
|
|
|
|
{
|
|
|
|
|
textureString = textureKey.asString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LLStringUtil::replaceString(script,"[PATTERN]",mScriptPatternMap[mPatternTypeCombo->getValue()]);
|
|
|
|
|
LLStringUtil::replaceString(script,"[BURST_RADIUS]",mBurstRadiusSpinner->getValue().asString());
|
|
|
|
|
LLStringUtil::replaceString(script,"[ANGLE_BEGIN]",mAngleBeginSpinner->getValue().asString());
|
|
|
|
|
LLStringUtil::replaceString(script,"[ANGLE_END]",mAngleEndSpinner->getValue().asString());
|
|
|
|
|
LLStringUtil::replaceString(script,"[TARGET_KEY]",keyString);
|
|
|
|
|
LLStringUtil::replaceString(script,"[START_COLOR]",lslColor(mStartColorSelector->get()));
|
|
|
|
|
LLStringUtil::replaceString(script,"[END_COLOR]",lslColor(mEndColorSelector->get()));
|
|
|
|
|
LLStringUtil::replaceString(script,"[START_ALPHA]",mStartAlphaSpinner->getValue().asString());
|
|
|
|
|
LLStringUtil::replaceString(script,"[END_ALPHA]",mEndAlphaSpinner->getValue().asString());
|
|
|
|
|
LLStringUtil::replaceString(script,"[START_GLOW]",mStartGlowSpinner->getValue().asString());
|
|
|
|
|
LLStringUtil::replaceString(script,"[END_GLOW]",mEndGlowSpinner->getValue().asString());
|
|
|
|
|
LLStringUtil::replaceString(script,"[START_SCALE]",lslVector(mScaleStartXSpinner->getValueF32(),mScaleStartYSpinner->getValueF32(),0.0f));
|
|
|
|
|
LLStringUtil::replaceString(script,"[END_SCALE]",lslVector(mScaleEndXSpinner->getValueF32(),mScaleEndYSpinner->getValueF32(),0.0f));
|
|
|
|
|
LLStringUtil::replaceString(script,"[TEXTURE]",textureString);
|
|
|
|
|
LLStringUtil::replaceString(script,"[SOURCE_MAX_AGE]",mSourceMaxAgeSpinner->getValue().asString());
|
|
|
|
|
LLStringUtil::replaceString(script,"[PART_MAX_AGE]",mParticlesMaxAgeSpinner->getValue().asString());
|
|
|
|
|
LLStringUtil::replaceString(script,"[BURST_RATE]",mBurstRateSpinner->getValue().asString());
|
|
|
|
|
LLStringUtil::replaceString(script,"[BURST_COUNT]",mBurstCountSpinner->getValue());
|
|
|
|
|
LLStringUtil::replaceString(script,"[ACCELERATION]",lslVector(mAcellerationXSpinner->getValueF32(),mAcellerationYSpinner->getValueF32(),mAcellerationZSpinner->getValueF32()));
|
|
|
|
|
LLStringUtil::replaceString(script,"[OMEGA]",lslVector(mOmegaXSpinner->getValueF32(),mOmegaYSpinner->getValueF32(),mOmegaZSpinner->getValueF32()));
|
|
|
|
|
LLStringUtil::replaceString(script,"[BURST_SPEED_MIN]",mBurstSpeedMinSpinner->getValue().asString());
|
|
|
|
|
LLStringUtil::replaceString(script,"[BURST_SPEED_MAX]",mBurstSpeedMaxSpinner->getValue().asString());
|
|
|
|
|
LLStringUtil::replaceString(script,"[BLEND_FUNC_SOURCE]",mScriptBlendMap[mBlendFuncSrcCombo->getValue().asString()]);
|
|
|
|
|
LLStringUtil::replaceString(script,"[BLEND_FUNC_DEST]",mScriptBlendMap[mBlendFuncDestCombo->getValue().asString()]);
|
|
|
|
|
LLStringUtil::replaceString(script,"[PATTERN]", mScriptPatternMap[mPatternTypeCombo->getValue()]);
|
|
|
|
|
LLStringUtil::replaceString(script,"[BURST_RADIUS]", mBurstRadiusSpinner->getValue().asString());
|
|
|
|
|
LLStringUtil::replaceString(script,"[ANGLE_BEGIN]", mAngleBeginSpinner->getValue().asString());
|
|
|
|
|
LLStringUtil::replaceString(script,"[ANGLE_END]", mAngleEndSpinner->getValue().asString());
|
|
|
|
|
LLStringUtil::replaceString(script,"[TARGET_KEY]", keyString);
|
|
|
|
|
LLStringUtil::replaceString(script,"[START_COLOR]", lslColor(mStartColorSelector->get()));
|
|
|
|
|
LLStringUtil::replaceString(script,"[END_COLOR]", lslColor(mEndColorSelector->get()));
|
|
|
|
|
LLStringUtil::replaceString(script,"[START_ALPHA]", mStartAlphaSpinner->getValue().asString());
|
|
|
|
|
LLStringUtil::replaceString(script,"[END_ALPHA]", mEndAlphaSpinner->getValue().asString());
|
|
|
|
|
LLStringUtil::replaceString(script,"[START_GLOW]", mStartGlowSpinner->getValue().asString());
|
|
|
|
|
LLStringUtil::replaceString(script,"[END_GLOW]", mEndGlowSpinner->getValue().asString());
|
|
|
|
|
LLStringUtil::replaceString(script,"[START_SCALE]", lslVector(mScaleStartXSpinner->getValueF32(), mScaleStartYSpinner->getValueF32(), 0.0f));
|
|
|
|
|
LLStringUtil::replaceString(script,"[END_SCALE]", lslVector(mScaleEndXSpinner->getValueF32(), mScaleEndYSpinner->getValueF32(), 0.0f));
|
|
|
|
|
LLStringUtil::replaceString(script,"[TEXTURE]", textureString);
|
|
|
|
|
LLStringUtil::replaceString(script,"[SOURCE_MAX_AGE]", mSourceMaxAgeSpinner->getValue().asString());
|
|
|
|
|
LLStringUtil::replaceString(script,"[PART_MAX_AGE]", mParticlesMaxAgeSpinner->getValue().asString());
|
|
|
|
|
LLStringUtil::replaceString(script,"[BURST_RATE]", mBurstRateSpinner->getValue().asString());
|
|
|
|
|
LLStringUtil::replaceString(script,"[BURST_COUNT]", mBurstCountSpinner->getValue());
|
|
|
|
|
LLStringUtil::replaceString(script,"[ACCELERATION]", lslVector(mAcellerationXSpinner->getValueF32(), mAcellerationYSpinner->getValueF32(), mAcellerationZSpinner->getValueF32()));
|
|
|
|
|
LLStringUtil::replaceString(script,"[OMEGA]", lslVector(mOmegaXSpinner->getValueF32(), mOmegaYSpinner->getValueF32(), mOmegaZSpinner->getValueF32()));
|
|
|
|
|
LLStringUtil::replaceString(script,"[BURST_SPEED_MIN]", mBurstSpeedMinSpinner->getValue().asString());
|
|
|
|
|
LLStringUtil::replaceString(script,"[BURST_SPEED_MAX]", mBurstSpeedMaxSpinner->getValue().asString());
|
|
|
|
|
LLStringUtil::replaceString(script,"[BLEND_FUNC_SOURCE]", mScriptBlendMap[mBlendFuncSrcCombo->getValue().asString()]);
|
|
|
|
|
LLStringUtil::replaceString(script,"[BLEND_FUNC_DEST]", mScriptBlendMap[mBlendFuncDestCombo->getValue().asString()]);
|
|
|
|
|
|
|
|
|
|
std::string delimiter=" |\n ";
|
|
|
|
|
std::string delimiter = " |\n ";
|
|
|
|
|
std::string flagsString;
|
|
|
|
|
|
|
|
|
|
if(mBounceCheckBox->getValue())
|
|
|
|
|
flagsString+=delimiter+"PSYS_PART_BOUNCE_MASK";
|
|
|
|
|
if(mEmissiveCheckBox->getValue())
|
|
|
|
|
flagsString+=delimiter+"PSYS_PART_EMISSIVE_MASK";
|
|
|
|
|
if(mFollowSourceCheckBox->getValue())
|
|
|
|
|
flagsString+=delimiter+"PSYS_PART_FOLLOW_SRC_MASK";
|
|
|
|
|
if(mFollowVelocityCheckBox->getValue())
|
|
|
|
|
flagsString+=delimiter+"PSYS_PART_FOLLOW_VELOCITY_MASK";
|
|
|
|
|
if(mInterpolateColorCheckBox->getValue())
|
|
|
|
|
flagsString+=delimiter+"PSYS_PART_INTERP_COLOR_MASK";
|
|
|
|
|
if(mInterpolateScaleCheckBox->getValue())
|
|
|
|
|
flagsString+=delimiter+"PSYS_PART_INTERP_SCALE_MASK";
|
|
|
|
|
if(mTargetLinearCheckBox->getValue())
|
|
|
|
|
flagsString+=delimiter+"PSYS_PART_TARGET_LINEAR_MASK";
|
|
|
|
|
if(mTargetPositionCheckBox->getValue())
|
|
|
|
|
flagsString+=delimiter+"PSYS_PART_TARGET_POS_MASK";
|
|
|
|
|
if(mWindCheckBox->getValue())
|
|
|
|
|
flagsString+=delimiter+"PSYS_PART_WIND_MASK";
|
|
|
|
|
if(mRibbonCheckBox->getValue())
|
|
|
|
|
flagsString+=delimiter+"PSYS_PART_RIBBON_MASK";
|
|
|
|
|
if (mBounceCheckBox->getValue())
|
|
|
|
|
flagsString += delimiter + "PSYS_PART_BOUNCE_MASK";
|
|
|
|
|
if (mEmissiveCheckBox->getValue())
|
|
|
|
|
flagsString += delimiter + "PSYS_PART_EMISSIVE_MASK";
|
|
|
|
|
if (mFollowSourceCheckBox->getValue())
|
|
|
|
|
flagsString += delimiter + "PSYS_PART_FOLLOW_SRC_MASK";
|
|
|
|
|
if (mFollowVelocityCheckBox->getValue())
|
|
|
|
|
flagsString += delimiter + "PSYS_PART_FOLLOW_VELOCITY_MASK";
|
|
|
|
|
if (mInterpolateColorCheckBox->getValue())
|
|
|
|
|
flagsString += delimiter + "PSYS_PART_INTERP_COLOR_MASK";
|
|
|
|
|
if (mInterpolateScaleCheckBox->getValue())
|
|
|
|
|
flagsString += delimiter + "PSYS_PART_INTERP_SCALE_MASK";
|
|
|
|
|
if (mTargetLinearCheckBox->getValue())
|
|
|
|
|
flagsString += delimiter + "PSYS_PART_TARGET_LINEAR_MASK";
|
|
|
|
|
if (mTargetPositionCheckBox->getValue())
|
|
|
|
|
flagsString += delimiter + "PSYS_PART_TARGET_POS_MASK";
|
|
|
|
|
if (mWindCheckBox->getValue())
|
|
|
|
|
flagsString += delimiter + "PSYS_PART_WIND_MASK";
|
|
|
|
|
if (mRibbonCheckBox->getValue())
|
|
|
|
|
flagsString += delimiter + "PSYS_PART_RIBBON_MASK";
|
|
|
|
|
|
|
|
|
|
LLStringUtil::replaceString(script,"[FLAGS]",flagsString);
|
|
|
|
|
LLStringUtil::replaceString(script, "[FLAGS]", flagsString);
|
|
|
|
|
LL_DEBUGS() << "\n" << script << LL_ENDL;
|
|
|
|
|
|
|
|
|
|
return script;
|
|
|
|
|
@ -522,8 +528,8 @@ default\n\
|
|
|
|
|
|
|
|
|
|
void ParticleEditor::onCopyButtonClicked()
|
|
|
|
|
{
|
|
|
|
|
std::string script=createScript();
|
|
|
|
|
if(!script.empty())
|
|
|
|
|
std::string script = createScript();
|
|
|
|
|
if (!script.empty())
|
|
|
|
|
{
|
|
|
|
|
getWindow()->copyTextToClipboard(utf8str_to_wstring(script));
|
|
|
|
|
LLNotificationsUtil::add("ParticleScriptCopiedToClipboard");
|
|
|
|
|
@ -536,21 +542,23 @@ void ParticleEditor::onInjectButtonClicked()
|
|
|
|
|
LLUUID categoryID;
|
|
|
|
|
|
|
|
|
|
// first try to find the #Firestorm folder
|
|
|
|
|
categoryID=gInventory.findCategoryByName(ROOT_FIRESTORM_FOLDER);
|
|
|
|
|
categoryID = gInventory.findCategoryByName(ROOT_FIRESTORM_FOLDER);
|
|
|
|
|
|
|
|
|
|
// if no #Firestorm folder was found, create one
|
|
|
|
|
if(categoryID.isNull())
|
|
|
|
|
categoryID=gInventory.createNewCategory(gInventory.getRootFolderID(),LLFolderType::FT_NONE,ROOT_FIRESTORM_FOLDER);
|
|
|
|
|
if (categoryID.isNull())
|
|
|
|
|
{
|
|
|
|
|
categoryID = gInventory.createNewCategory(gInventory.getRootFolderID(), LLFolderType::FT_NONE, ROOT_FIRESTORM_FOLDER);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if still no #Firestorm folder was found, try to find the default "Scripts" folder
|
|
|
|
|
if(categoryID.isNull())
|
|
|
|
|
if (categoryID.isNull())
|
|
|
|
|
{
|
|
|
|
|
std::string scriptFolderName=LLFolderType::lookup(LLFolderType::FT_LSL_TEXT);
|
|
|
|
|
std::string scriptFolderName = LLFolderType::lookup(LLFolderType::FT_LSL_TEXT);
|
|
|
|
|
gInventory.findCategoryByName(scriptFolderName);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if still no valid folder found bail out and complain
|
|
|
|
|
if(categoryID.isNull())
|
|
|
|
|
if (categoryID.isNull())
|
|
|
|
|
{
|
|
|
|
|
LLNotificationsUtil::add("ParticleScriptFindFolderFailed");
|
|
|
|
|
return;
|
|
|
|
|
@ -558,21 +566,21 @@ void ParticleEditor::onInjectButtonClicked()
|
|
|
|
|
|
|
|
|
|
// setup permissions
|
|
|
|
|
LLPermissions perm;
|
|
|
|
|
perm.init(gAgent.getID(),gAgent.getID(),LLUUID::null,LLUUID::null);
|
|
|
|
|
perm.initMasks(PERM_ALL,PERM_ALL,PERM_ALL,PERM_ALL,PERM_ALL);
|
|
|
|
|
perm.init(gAgentID, gAgentID, LLUUID::null, LLUUID::null);
|
|
|
|
|
perm.initMasks(PERM_ALL, PERM_ALL, PERM_ALL, PERM_ALL, PERM_ALL);
|
|
|
|
|
|
|
|
|
|
// create new script inventory item and wait for it to come back (callback)
|
|
|
|
|
LLPointer<LLInventoryCallback> callback=new ParticleScriptCreationCallback(this);
|
|
|
|
|
LLPointer<LLInventoryCallback> callback = new ParticleScriptCreationCallback(this);
|
|
|
|
|
create_inventory_item(
|
|
|
|
|
gAgent.getID(),
|
|
|
|
|
gAgent.getSessionID(),
|
|
|
|
|
gAgentID,
|
|
|
|
|
gAgentSessionID,
|
|
|
|
|
categoryID,
|
|
|
|
|
LLTransactionID::tnull,
|
|
|
|
|
PARTICLE_SCRIPT_NAME,
|
|
|
|
|
"",
|
|
|
|
|
LLAssetType::AT_LSL_TEXT,
|
|
|
|
|
LLTransactionID::tnull,
|
|
|
|
|
PARTICLE_SCRIPT_NAME,
|
|
|
|
|
"",
|
|
|
|
|
LLAssetType::AT_LSL_TEXT,
|
|
|
|
|
LLInventoryType::IT_LSL,
|
|
|
|
|
NOT_WEARABLE,
|
|
|
|
|
NOT_WEARABLE,
|
|
|
|
|
perm.getMaskNextOwner(),
|
|
|
|
|
callback);
|
|
|
|
|
|
|
|
|
|
@ -583,34 +591,34 @@ void ParticleEditor::callbackReturned(const LLUUID& inventoryItemID)
|
|
|
|
|
{
|
|
|
|
|
setCanClose(TRUE);
|
|
|
|
|
|
|
|
|
|
if(inventoryItemID.isNull())
|
|
|
|
|
if (inventoryItemID.isNull())
|
|
|
|
|
{
|
|
|
|
|
LLNotificationsUtil::add("ParticleScriptCreationFailed");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mParticleScriptInventoryItem=gInventory.getItem(inventoryItemID);
|
|
|
|
|
if(!mParticleScriptInventoryItem)
|
|
|
|
|
mParticleScriptInventoryItem = gInventory.getItem(inventoryItemID);
|
|
|
|
|
if (!mParticleScriptInventoryItem)
|
|
|
|
|
{
|
|
|
|
|
LLNotificationsUtil::add("ParticleScriptNotFound");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
gInventory.updateItem(mParticleScriptInventoryItem);
|
|
|
|
|
gInventory.notifyObservers();
|
|
|
|
|
gInventory.updateItem(mParticleScriptInventoryItem);
|
|
|
|
|
gInventory.notifyObservers();
|
|
|
|
|
|
|
|
|
|
//caps import
|
|
|
|
|
std::string url=gAgent.getRegion()->getCapability("UpdateScriptAgent");
|
|
|
|
|
std::string url = gAgent.getRegion()->getCapability("UpdateScriptAgent");
|
|
|
|
|
|
|
|
|
|
if(!url.empty())
|
|
|
|
|
if (!url.empty())
|
|
|
|
|
{
|
|
|
|
|
std::string script=createScript();
|
|
|
|
|
std::string script = createScript();
|
|
|
|
|
|
|
|
|
|
std::string tempFileName=gDirUtilp->getExpandedFilename(LL_PATH_CACHE,"particle_script.lsltxt");
|
|
|
|
|
std::string tempFileName = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "particle_script.lsltxt");
|
|
|
|
|
|
|
|
|
|
std::ofstream tempFile;
|
|
|
|
|
|
|
|
|
|
tempFile.open(tempFileName.c_str());
|
|
|
|
|
if(!tempFile.is_open())
|
|
|
|
|
if (!tempFile.is_open())
|
|
|
|
|
{
|
|
|
|
|
LLNotificationsUtil::add("ParticleScriptCreateTempFileFailed");
|
|
|
|
|
return;
|
|
|
|
|
@ -620,13 +628,13 @@ void ParticleEditor::callbackReturned(const LLUUID& inventoryItemID)
|
|
|
|
|
tempFile.close();
|
|
|
|
|
|
|
|
|
|
LLSD body;
|
|
|
|
|
body["task_id"]=mObject->getID(); // probably has no effect
|
|
|
|
|
body["item_id"]=inventoryItemID;
|
|
|
|
|
body["target"]="mono";
|
|
|
|
|
body["is_script_running"]=true;
|
|
|
|
|
body["task_id"] = mObject->getID(); // probably has no effect
|
|
|
|
|
body["item_id"] = inventoryItemID;
|
|
|
|
|
body["target"] = "mono";
|
|
|
|
|
body["is_script_running"] = true;
|
|
|
|
|
|
|
|
|
|
// responder will alert us when the job is done
|
|
|
|
|
LLHTTPClient::post(url,body,new ParticleScriptUploadResponder(body,tempFileName,LLAssetType::AT_LSL_TEXT,this));
|
|
|
|
|
LLHTTPClient::post(url, body, new ParticleScriptUploadResponder(body, tempFileName, LLAssetType::AT_LSL_TEXT, this));
|
|
|
|
|
|
|
|
|
|
mMainPanel->setEnabled(FALSE);
|
|
|
|
|
setCanClose(FALSE);
|
|
|
|
|
@ -643,15 +651,15 @@ void ParticleEditor::scriptInjectReturned(const LLSD& content)
|
|
|
|
|
setCanClose(TRUE);
|
|
|
|
|
|
|
|
|
|
// play it safe, because some time may have passed
|
|
|
|
|
LLViewerObject* object=gObjectList.findObject(mObject->getID());
|
|
|
|
|
if(!object)
|
|
|
|
|
LLViewerObject* object = gObjectList.findObject(mObject->getID());
|
|
|
|
|
if (!object)
|
|
|
|
|
{
|
|
|
|
|
LL_DEBUGS() << "object went away!" << LL_ENDL;
|
|
|
|
|
mMainPanel->setEnabled(TRUE);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mObject->saveScript(mParticleScriptInventoryItem,TRUE,FALSE);
|
|
|
|
|
mObject->saveScript(mParticleScriptInventoryItem, TRUE, FALSE);
|
|
|
|
|
LLNotificationsUtil::add("ParticleScriptInjected");
|
|
|
|
|
|
|
|
|
|
delete this;
|
|
|
|
|
@ -661,7 +669,7 @@ void ParticleEditor::scriptInjectReturned(const LLSD& content)
|
|
|
|
|
|
|
|
|
|
ParticleScriptCreationCallback::ParticleScriptCreationCallback(ParticleEditor* editor)
|
|
|
|
|
{
|
|
|
|
|
mEditor=editor;
|
|
|
|
|
mEditor = editor;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ParticleScriptCreationCallback::~ParticleScriptCreationCallback()
|
|
|
|
|
@ -680,9 +688,9 @@ ParticleScriptUploadResponder::ParticleScriptUploadResponder(const LLSD& post_da
|
|
|
|
|
LLAssetType::EType asset_type,
|
|
|
|
|
ParticleEditor* editor
|
|
|
|
|
) :
|
|
|
|
|
LLUpdateAgentInventoryResponder(post_data,file_name,asset_type)
|
|
|
|
|
LLUpdateAgentInventoryResponder(post_data, file_name, asset_type)
|
|
|
|
|
{
|
|
|
|
|
mEditor=editor;
|
|
|
|
|
mEditor = editor;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ParticleScriptUploadResponder::uploadComplete(const LLSD& content)
|
|
|
|
|
|