/*
  plugin par iri - http://www.irizone.net
  date : may 2005
  name : iriparticles - part CLIENT

  name : dynparticles - part CLIENT
  date : february 2007
  auteur : iri pour I-Maginer (http://www.i-maginer.fr)
*/

typeof class = S;;

typeof initON = I;;	// lancement des particules automatiquement
typeof initColor = I;;	// couleur initiale
typeof initSize = [[F F] r1];;	// tailles en fonction de l'âge
typeof colorCycle = I;;	// activer un cycle de couleur (1) ou pas (0)
typeof sizeCycle = I;;	// activer un cycle de taille (1) ou pas (0)
typeof maxSize = I;;	// taille maximale
typeof typeFX = I;;	// effet : constant, électrique, magnétique, chaotique ou hélicoïdale
typeof typeVolEmitter = I;;	// volume dans lequel évoluent les particules
typeof typeMaskEmitter = I;;	// masque de l'emitter
typeof typeMaskParticle = I;;	// masque de la particule
typeof vectorVolA = [F F F];;	// vecteur A du volume
typeof vectorVolB = [F F F];;	// vecteur B du volume
typeof vectorFxA = [F F F];;	// vecteur A de l'effet
typeof vectorFxB = [F F F];;	// vecteur B de l'effet
typeof vectorFxC = [F F F];;	// vecteur C de l'effet
typeof life = F;;	// durée de vie
var masse = 0.0;;	// masse
var spin = 0.0;;	// spin (~ orientation)
var polarity = 0.0;;	// polarité

typeof h3dTopoPart = H3d;;
typeof hpart3dMain = [HPart3d r1];;
typeof hfx3dMain   = [HEffect3d r1];;
typeof hEmitter = H3d;;

typeof Objs = H3d;;	// objet supportant les particules


proto dynamicedit = fun [ObjWin H3d HMat3d S Ob] I;;	// édition en ligne


/*
	Initialise la liste des tailles selon l'âge
	
	l		-> [S r1] : tailles classées selon l'âge
	sizes	-> [[F F] r1] : liste à initialiser (devrait être à nil au départ)
	life	-> F : âge (devrait être à 0.0 au départ)
			<- [[F F] r1] : liste initialisée
*/
fun setInitSize(l, sizes, life)=
	if l == nil then
		sizes
	else
		(
		 set sizes = [atof hd l life]::sizes;
		 setInitSize tl l sizes life+.10.0
		);;


/*
	retourne le premier objet de l'ancre
*/
fun setObjs(l, o)=
  if l == nil then
    0
  else
    let match hd l with
          (objAnchor [h _ _ _] -> set Objs = h)
          |(_ -> nil)
        -> _ in
    0;; 

fun convSizesS2F(l, out, i)=
	if i >. 100.0 then
		out
	else
		(
		 set out = [atof (hd l) i] :: out;
		 convSizesS2F tl l out i+.10.0
		);; 
		
fun convVectorS2F(s)=
	let lineextr s -> l in
	[atof nth_list l 0 atof nth_list l 1 atof nth_list l 2];;	

// initialisation des données
fun initDatas(param)= 
	let strextr param -> l in
	(
	 let hd switchstr l "initcolor" -> tmp in
	 set initColor = if tmp == nil then 0xffffff else atoi tmp;
	 set colorCycle = atoi hd switchstr l "colorcycle";
	 set maxSize = atoi hd switchstr l "sizemax";
	 set initSize = convSizesS2F switchstr l "sizetime" nil 0.0;
	 let hd switchstr l "life" -> tmp in 
	 if (!strcmp tmp "PCL_INFINIT") || (!strcmp tmp "0") then
		(
		 set life = nil;
		 set typeMaskEmitter = PCL_INFINIT 
		)
	 else 
		(
		 set life = atof tmp;
		 set typeMaskEmitter = nil
		);		
	 let hd switchstr l "volume" -> tmp in let _fooS strcat "VOLLLL__" tmp -> _ in
	 set typeVolEmitter = if !strcmp tmp "VOLUME_CONE" then
							VOLUME_CONE
						else if !strcmp tmp "VOLUME_PLAN" then
							VOLUME_PLAN
						else if !strcmp tmp "VOLUME_LINE" then
							VOLUME_LINE
						else
							VOLUME_SPHERE;
	 set vectorVolA = convVectorS2F hd switchstr l "volA";
	 set vectorVolB = convVectorS2F hd switchstr l "volB";
	 let hd switchstr l "effect" -> tmp in
	 set typeFX = if !strcmp tmp "EFFECT_ELECTRIC" then
					EFFECT_ELECTRIC
				else if !strcmp tmp "EFFECT_MAGNETIC" then
					EFFECT_MAGNETIC
				else if !strcmp tmp "EFFECT_CHAOTIC0" then
					EFFECT_CHAOTIC0
				else if !strcmp tmp "EFFECT_CHAOTIC1" then
					EFFECT_CHAOTIC1
				else if !strcmp tmp "EFFECT_HELICOID" then
					EFFECT_HELICOID
				else
					EFFECT_CONSTANT;
	 set vectorFxA = convVectorS2F hd switchstr l "effectA";
	 set vectorFxB = convVectorS2F hd switchstr l "effectB";
	 set vectorFxC = convVectorS2F hd switchstr l "effectC";
	 let hd switchstr l "target" -> tmp in
	 set typeMaskParticle = if !strcmp tmp "PCL_BILLBOARD" then
							PCL_BILLBOARD
						else if !strcmp tmp "PCL_RAINBOW" then
							PCL_RAINBOW
						else
							nil;
	);;


/*
	Destruction des particules
	
	fx	-> HEffect3d
	part-> HPart3d
		<- I
*/
fun destroyParticles(fx, part)=
  if fx == nil then
    (
     set hfx3dMain = nil;  // reset
     set hpart3dMain = nil;  // reset
     0
    )
  else  // destroy each fx and particles
    (
     M3delEffect3d session hd fx;
     M3delPart3d session hd part;
     destroyParticles tl fx tl part
    );;
	
fun stopParticles()=
	destroyParticles hfx3dMain hpart3dMain;;


/*
	Création du système de particules
	Destruction de l'ancien système au préalable (s'il en existe un)
	
	o	-> Ob
		<- I
*/
fun startParticles(o)= 
	if Objs == nil then
		0
	else
		(
		 stopParticles;
		 M3load session "dms/3d/plugins/iriparticles/particles.m3d" nil;
		 set h3dTopoPart = M3meshGetTopology session (M3getObj session "Topo_Particle");
		 let hd initSize -> [taille _] in
		 set hpart3dMain = (M3createParticle session h3dTopoPart typeMaskParticle life 64.0 masse taille spin polarity)::hpart3dMain;
		 M3setParticleSizes session hd hpart3dMain initSize; 
		 M3setParticleSpins session hd hpart3dMain [0.2 0.0]::[0.5 30.0]::[0.2 100.0]::nil;
		 set hfx3dMain = (M3createEffect session typeFX vectorFxA vectorFxB vectorFxC)::hfx3dMain;
		 let M3createEmitter session typeMaskEmitter life [typeVolEmitter vectorVolA vectorVolB] -> h3dEmitter in
		 (
		  M3linkParticleList session h3dEmitter (hd hpart3dMain)::nil;
		  M3linkEffectList session h3dEmitter (hd hfx3dMain)::nil;
		  M3setEmitterState session h3dEmitter PCL_ENABLE;
		  set hEmitter = h3dEmitter;
		  M3link session h3dEmitter Objs;
		
		  UsendMessage ObUi o "started" nil;
		 )
		);;	


/*
	Série de callbacks des actions clientes via dms
	
	o		-> Ob
	from	-> DMI
	action	-> S
	param	-> S
	reply	-> S
			<- I
*/
// Démarre le système (inusité)
fun cbStart(o, from, action, param, reply)=
	setObjs ObAnchor o o;
	_DMSevent this (strcatn (ObName o)::".started"::nil) nil nil;;

// Arrêt des particules (stop)
fun cbClose(o, from, action, param, reply)=
	destroyParticles hfx3dMain hpart3dMain;
	_DMSevent this (strcatn (ObName o)::".stopped"::nil) nil nil;;

// Edition en ligne (edit)
fun cbEdit(o, from, action, param, reply)=
	dynamicedit nil Objs nil param o;
	0;;

// Register du client (register)
fun cbRegister(o, from, action, param, reply)=
	UsendMessage ObUi o "register" itoa initON;;

// Unregister du client (unregister)
fun cbUnregister(o, from, action, param, reply)=
	UsendMessage ObUi o "unregister" nil;;



/*
	Callbacks Ob
*/
// Lorsque le client clique sur un objet, celui-ci est enregistré en vue d'une éventuelle utilisation par le plugin
// fun [Ob [H3d HMat3d I]] I
fun cbClick(o, p)=
	let p -> [h m btn] in
	set Objs = h;
	0;;

// Exécutée après chaque rendu (pour d'éventuelles animations sur les couleurs ou les tailles par exemple)
// fun [Ob [ObjSurface [I I]]] I
fun cbRender(o, p)=
	0;;



/*
	Communication serveur / cient
	
	ui		-> UserI
	action	-> S : nom de l'action venant du srv
	param	-> S : paramètre de l'action
	o		-> Ob
			<- I
*/
fun cbcomm(ui, action, param, o)=
	if !strcmp action "start" then
		(
		 stopParticles; 
		 initDatas param;
		 startParticles o;
		 0
		)
	else if !strcmp action "stop" then
		stopParticles
	else
		0;;

/*
	Création de l'instance correspondante
	
	o	-> Ob
		<- I
*/
fun newOb(o)=
	/* set initON = if !strcmpi hd UgetParam ObUi o "init" "on" then 1 else 0;
	set initColor = atoi hd UgetParam ObUi o "initColor";
	set initSize = setInitSize hd strextr hd UgetParam ObUi o "initSizes" nil 0.0;
	set colorCycle = if !strcmpi hd UgetParam ObUi o "colorCycle" "on" then 1 else 0;
	set sizeCycle = if !strcmpi hd UgetParam ObUi o "sizeCycle" "on" then 1 else 0;
	set maxSize = atoi hd UgetParam ObUi o "maxSize";
	let hd UgetParam ObUi o "typeFX" -> tmp in
	set typeFX = if !strcmp tmp "EFFECT_ELECTRIC" then
					EFFECT_ELECTRIC
				else if !strcmp tmp "EFFECT_MAGNETIC" then
					EFFECT_MAGNETIC
				else if !strcmp tmp "EFFECT_CHAOTIC0" then
					EFFECT_CHAOTIC0
				else if !strcmp tmp "EFFECT_CHAOTIC1" then
					EFFECT_CHAOTIC1
				else if !strcmp tmp "EFFECT_HELICOID" then
					EFFECT_HELICOID
				else
					EFFECT_CONSTANT;
	let hd UgetParam ObUi o "typeVolEmitter" -> tmp in
	set typeVolEmitter = if !strcmp tmp "VOLUME_CONE" then
							VOLUME_CONE
						else if !strcmp tmp "VOLUME_PLAN" then
							VOLUME_PLAN
						else if !strcmp tmp "VOLUME_LINE" then
							VOLUME_LINE
						else
							VOLUME_SPHERE;
	let hd UgetParam ObUi o "typeMaskEmitter" -> tmp in
	set typeMaskEmitter = if (!strcmp tmp "PCL_INFINIT") || (!strcmp tmp "0") then
							PCL_INFINIT 
						else 
							nil;
	let hd UgetParam ObUi o "typeParticle" -> tmp in
	set typeMaskParticle = if !strcmp tmp "PCL_BILLBOARD" then
							PCL_BILLBOARD
						else if !strcmp tmp "PCL_RAINBOW" then
							PCL_RAINBOW
						else
							nil;
	set vectorFxA = setVector hd strextr hd UgetParam ObUi o "vectorA";
	set vectorFxB = setVector hd strextr hd UgetParam ObUi o "vectorB";
	set vectorFxC = setVector hd strextr hd UgetParam ObUi o "vectorC";
	set vectorVolA = setVector hd strextr hd UgetParam ObUi o "vectorA";
	set vectorVolB = setVector hd strextr hd UgetParam ObUi o "vectorB"; */
	
	setObjs ObAnchor o o;
	UcbComm this ObUi o mkfun4 @cbcomm o;
	UsendMessage ObUi o "register" nil;
	
	
  // startParticles o;
  // set listObjs = setObjs2 ObAnchor o;
	ObCbControlClick o @cbClick;
	ObRegisterAction o (strcatn (ObName o)::".start"::nil) @cbStart;	// Obsolète
	ObRegisterAction o (strcatn (ObName o)::".stop"::nil) @cbClose;
	ObRegisterAction o (strcatn (ObName o)::".edit"::nil) @cbEdit;
	ObRegisterAction o (strcatn (ObName o)::".register"::nil) @cbRegister;
	ObRegisterAction o (strcatn (ObName o)::".unregister"::nil) @cbUnregister;
	ObCbPostRender o @cbRender;
  
  /* if initON then
    setObjs ObAnchor o o
  else
    nil;*/
  0;;

/*
	initialisation du plugin auprès du c3d3
	
	file 	-> S : fichier *.plug
			<- I
*/
fun IniPlug(file)=
	set class = getInfo strextr _getpack _checkpack file "name";
	let if !strcmp _getress "DefaultLanguage" "French" then "french" else "english" -> lang in
	_load strcatn "dms/3d/plugins/dynparticles/lang/" :: lang :: ".lang" :: nil;
	PLUGsetinfo thisplug PLUGIN_OBJECT|PLUGIN_RESERVED; // |PLUGIN_ONLINE_EDITING;
	// PLUGdefineEditor thisplug mkfun5 @dynamicedit VAR_DYNEDITOR;
	PlugRegister class @newOb nil;
	0;;





/* *********************************



	EDITION EN LIGNE
	
	
	
********************************* */



typeof bmpcolor = ObjBitmap;;
typeof winColor = ObjWin;;
typeof font = ObjFont;;
typeof sliColorAlpha = ObjSlider;;
typeof txtAlphaValue = ObjText;;
typeof cColorCycle = ObjCheck;;
typeof txtSizeMax = ObjText;;
typeof cSizeConst = ObjCheck;;
typeof winSize = ObjWin;;
typeof txtExpertInfinit = ObjText;;
typeof cmExpertVolume = ObjBox;;
typeof txtExpertVolumeSphereRadiusMsg = ObjText;;
typeof txtExpertVolumeSphereRadius = ObjText;;
typeof txtExpertVolumeConeMsg = ObjText;;
typeof txtExpertVolumeConeLong = ObjText;;
typeof txtExpertVolumeConeLarg = ObjText;;
typeof txtExpertVolumeConeHaut = ObjText;;
typeof txtExpertVolumePlanMsg = ObjText;;
typeof txtExpertVolumePlanLong = ObjText;;
typeof txtExpertVolumePlanLarg = ObjText;;
typeof txtExpertVolumeLineMsg = ObjText;;
typeof txtExpertVolumeLineLong = ObjText;;
typeof cmExpertEffect = ObjBox;;
typeof txtExpertEffectConstantMsg = ObjText;;
typeof txtExpertEffectConstantX = ObjText;;
typeof txtExpertEffectConstantY = ObjText;;
typeof txtExpertEffectConstantZ = ObjText;;
typeof txtExpertEffectElectricMsg = ObjText;;
typeof txtExpertEffectElectricAX = ObjText;;
typeof txtExpertEffectElectricAY = ObjText;;
typeof txtExpertEffectElectricAZ = ObjText;;
typeof txtExpertEffectElectricBX = ObjText;;
typeof txtExpertEffectMagneticMsg = ObjText;;
typeof txtExpertEffectMagneticAX = ObjText;;
typeof txtExpertEffectMagneticAY = ObjText;;
typeof txtExpertEffectMagneticAZ = ObjText;;
typeof txtExpertEffectMagneticBX = ObjText;;
typeof txtExpertEffectChaotic0Msg = ObjText;;
typeof txtExpertEffectChaotic0AX = ObjText;;
typeof txtExpertEffectChaotic0AY = ObjText;;
typeof txtExpertEffectChaotic0AZ = ObjText;;
typeof txtExpertEffectChaotic0BX = ObjText;;
typeof txtExpertEffectChaotic0BY = ObjText;;
typeof txtExpertEffectChaotic0BZ = ObjText;;
typeof txtExpertEffectChaotic1Msg = ObjText;;
typeof txtExpertEffectChaotic1AX = ObjText;;
typeof txtExpertEffectChaotic1AY = ObjText;;
typeof txtExpertEffectChaotic1AZ = ObjText;;
typeof txtExpertEffectChaotic1BX = ObjText;;
typeof txtExpertEffectChaotic1BY = ObjText;;
typeof txtExpertEffectChaotic1BZ = ObjText;;
typeof txtExpertEffectHelicoidMsg = ObjText;;
typeof txtExpertEffectHelicoidAX = ObjText;;
typeof txtExpertEffectHelicoidAY = ObjText;;
typeof txtExpertEffectHelicoidAZ = ObjText;;
typeof txtExpertEffectHelicoidBX = ObjText;;
typeof txtExpertEffectHelicoidBY = ObjText;;
typeof txtExpertEffectHelicoidBZ = ObjText;;
typeof cExpertBillboard = ObjCheck;;
typeof cExpertRainbow = ObjCheck;;
typeof txtExpertMasse = ObjText;;
typeof cExpertAllClients = ObjCheck;;
typeof cExpertUploadSrv = ObjCheck;;
typeof winHelp = ObjWin;;

typeof listSizes = [[F F] r1];;
typeof listSizesOld = [[F F] r1];;
typeof colorInit = S;;
typeof colorInitClick = I;;



proto plugloc = fun [S] S;;
proto plughelp = fun [S] S;;



/*
	MISC.
*/

/*
	Retourne la valeur de durée de vie en fonction de l'abscisse du clic
	
	l	-> [[I I] r1] : listSizes
	w	-> I : largeur de la fenêtre du graph
	x	-> I : pos x du clic
	m	-> I : marge autour de la position réelle pour acceptation
		<- I : valeur de la durée de vie
*/
fun getLifeByX(l, w, x, m)=
	if l == nil then
		nil
	else
		let hd l -> [vie _] in
		let 25+((ftoi vie)*((w-30)/100)) -> v in
		if x >= (v-m) && x < (v+m) then
			ftoi vie
		else
			getLifeByX tl l w x m;;

fun replaceTailleInListSizes(l, vie, taille)=
	if l == nil then
		nil
	else
		let hd l -> [v t] in
		if v == vie then
			[vie taille] :: (tl l)
		else
			(hd l) :: replaceTailleInListSizes tl l vie taille;;


/*
	SIZE
*/

fun getSizes(l, out)=
	if l == nil then
		linebuild out
	else
		let hd l -> [_ taille] in
		(
		 set out = (ftoa taille) :: out;
		 getSizes tl l out
		);;

fun size_initList(m)=
	let itof m -> m in
	set listSizes = [0.0 m] :: [10.0 m] :: [20.0 m] :: [30.0 m] :: [40.0 m] :: [50.0 m] :: [60.0 m] :: [70.0 m] :: [80.0 m] :: [90.0 m] :: [100.0 m] :: nil;;
	
/*
	Création du graph des tailles en fonction de la durée de vie des particules
*/
fun size_winCrGraph(w, h, m, l)=
	if l == nil then
		0
	else
		let hd l -> [vie taille] in
		let hd tl l -> [vie2 taille2] in
		let ftoi vie -> vie in
		let ftoi taille -> taille in
		let ftoi vie2 -> vie2 in
		let ftoi taille2 -> taille2 in
		let 25+(m-taille)*(h-20-25)/m -> y in
		let 25+(m-taille2)*(h-20-25)/m -> y2 in
		let 25+(vie*((w-30)/100)) -> x in
		let 25+(vie2*((w-30)/100)) -> x2 in
		(
		 _PAINTcircle winSize x y 4 DRAW_INVISIBLE 0 0 DRAW_SOLID 0x00ff00;
		 if vie2 != nil then
			_PAINTline winSize x y x2 y2 DRAW_SOLID 1 0x00ff00
		 else
			nil;
		 size_winCrGraph w h m tl l
		);;

/*
	Création des axes et des labels du graph
	fun [] I
*/
fun size_winCrAxes()=
	let _GETwindowSizePosition winSize -> [w h _ _] in
	let atoi _GETtext txtSizeMax -> m in
	(
	 _CLRwindow winSize;
	 _PAINTline winSize 25 20 25 h-15 DRAW_SOLID 1 0;
	 _PAINTline winSize 20 h-20 w-50 h-20 DRAW_SOLID 1 0;
	 _TXTout winSize font 200 5 TD_LEFT|TD_TOP 0 plugloc "SIZE_CONF";
	 _TXTout winSize font 1 25 TD_LEFT|TD_BASELINE 0 "100%";
	 _TXTout winSize font 10 h-5 TD_LEFT|TD_BASELINE 0 "0";
	 _TXTout winSize font w-70 h-5 TD_LEFT|TD_BASELINE 0 "100%";
	 _TXTout winSize font 10 3 TD_LEFT|TD_TOP 0 plugloc "SIZELINE";
	 _TXTout winSize font (w/2) h-5 TD_CENTER|TD_BASELINE 0 plugloc "TIMELINE";
	 _TXTout winSize font w-2 h-60 TD_RIGHT|TD_BASELINE 0xff0000 "UNDO";
	 _TXTout winSize font w-2 h-40 TD_RIGHT|TD_BASELINE 0xff0000 "REDO";
	 _TXTout winSize font w-2 h-20 TD_RIGHT|TD_BASELINE 0xff0000 "RESET";
	 if (_GETcheck cSizeConst) then
		nil
	else
		_TXTout winSize font w/2 h/2 TD_CENTER|TD_BASELINE 0xff0000 plugloc "SIZEWIN_DISABLED";
	 size_winCrGraph w h m listSizes;
	);;
	
fun size_sizeConst(obj, u, state)=
	size_winCrAxes;
	_ENwindow winSize state;;

fun size_winPaint(obj, u)=
	size_winCrAxes;;
	
/*
	clic dans le graph. 5 zones sont définies :
	- le graph lui-même (le rectangle matérialisé par les deux axes)
	- le bouton undo (annuler)
	- le bouton redo (rétablir)
	- le bouton de réinitialisation (reset)
	- le reste de la fenêtre
*/
fun size_winClick(obj, o, x, y, btn)= 
	let _GETwindowSizePosition winSize -> [w h _ _] in
	let atoi _GETtext txtSizeMax -> m in
	let getLifeByX listSizes w x (w-70)/10 -> vie in
	if x > (w-35) && y > (h-68) && y < (h-52) then // undo
		let listSizes -> old in		
		(
		 set listSizes = listSizesOld;
		 set listSizesOld = old;
		 size_winCrAxes
		)
	else if x > (w-35) && y > (h-48) && y < (h-32) then	// redo
		let listSizesOld -> new in
		(
		 set listSizesOld = listSizes;
		 set listSizes = new;
		 size_winCrAxes
		)
	else if x > (w-35) && y > (h-28) && y < (h-12) then	// reset
		let listSizes -> old in	
		(
 		 set listSizes = size_initList m;
		 set listSizesOld = old;
		 size_winCrAxes
		)
	else if y > 25 && y < (h-20) && vie != nil then	// graph
		let m-ftoi(((itof(y-25))/.99.0)*.(itof m)) -> taille in
		let if taille > m then m else taille -> taille in
		(
		 set listSizesOld = listSizes;
		 set listSizes = replaceTailleInListSizes listSizes itof vie itof taille;
		 size_winCrAxes;
		 UsendMessage ObUi o "size_newSize" linebuild nil;
		)
	else
		0;;


/*
	COLOR
*/

// l'état d'activation du cycle de couleur a été modifié
fun color_cycleColor(obj, o, state)=
	UsendMessage ObUi o "color_cycleColor" itoa state;;

// le curseur du slide de réglage de la composante alpha a été modifié
fun color_alphaClick(obj, l, r, o)=
	_SETtext txtAlphaValue strcat ftoa l " %";
	UsendMessage ObUi o "color_chgAlpha" ftoa (l *. 1.27);;

// un clic a eulieu dans la map de couleurs
fun color_winClick(obj, u, x, y, btn)=
	set colorInitClick = _GETpixel24 bmpcolor x y;
	let u -> [win o] in
	(
	 UsendMessage ObUi o "color_chgColor" itoa colorInitClick;
	 _PAINTwindow win
	);;
	
fun color_winPaint(obj, u)=
	_BLTbitmap winColor bmpcolor 0 0;;

fun color_winEnd(obj, u)=
	_DSbitmap bmpcolor;;
	
/*
	EXPERT
*/

// la durée de vie est changée : la nouvelle donnée est envoyée au serveur
fun expert_infinit(obj, o)=
	let _GETtext obj -> vie in
	UsendMessage ObUi o "expert_infinit" vie;; 

// le rayon de la sphère dans laquelle évoluent les particules a changé : la nouvelle donnée est envoyée au serveur
fun expert_volumeSphereRadius(obj, o)=
	let _GETtext obj -> r in
	UsendMessage ObUi o "expert_volSphreRadius" r;;

// une dimension du cône dans lequel évoluent les particules a changé : la nouvelle donnée est envoyée au serveur
fun expert_volumeCone(obj, u)=
	let u -> [o n] in
	let _GETtext obj -> c in
	UsendMessage ObUi o "expert_volCone" linebuild (itoa n) :: c :: nil;;

// une dimension du plan dans lequel évoluent les particules a changé : la nouvelle donnée est envoyée au serveur
fun expert_volumePlan(obj, u)=
	let u -> [o n] in
	let _GETtext obj -> c in
	UsendMessage ObUi o "expert_volPlan" linebuild (itoa n) :: c :: nil;;

// le segment de la ligne dans lequel évoluent les particules a changé : la nouvelle donnée est envoyée au serveur
fun expert_volumeLine(obj, o)=
	let _GETtext obj -> c in
	UsendMessage ObUi o "expert_volLine" c;;

// le volume a été changé. Seuls les champs de données correspondant au volume sélectionné sont montrés. 
// Le nouveau volume est envoyé au serveur
// fun [ObjBox Ob I S] I
fun expert_volumeChoice(obj, o, i, s)=
	_SHOWtext txtExpertVolumeSphereRadius WINDOW_HIDDEN;
	_SHOWtext txtExpertVolumeSphereRadiusMsg WINDOW_HIDDEN;
	_SHOWtext txtExpertVolumeConeMsg WINDOW_HIDDEN;
	_SHOWtext txtExpertVolumeConeLong WINDOW_HIDDEN;
	_SHOWtext txtExpertVolumeConeLarg WINDOW_HIDDEN;
	_SHOWtext txtExpertVolumeConeHaut WINDOW_HIDDEN;
	_SHOWtext txtExpertVolumePlanMsg WINDOW_HIDDEN;
	_SHOWtext txtExpertVolumePlanLong WINDOW_HIDDEN;
	_SHOWtext txtExpertVolumePlanLarg WINDOW_HIDDEN;
	_SHOWtext txtExpertVolumeLineMsg WINDOW_HIDDEN;
	_SHOWtext txtExpertVolumeLineLong WINDOW_HIDDEN;
	if !strcmp s plugloc "EXPERT_VOLUME_SPHERE" then
		(
		 _SHOWtext txtExpertVolumeSphereRadius WINDOW_UNHIDDEN;
		 _SHOWtext txtExpertVolumeSphereRadiusMsg WINDOW_UNHIDDEN;
		 expert_volumeSphereRadius txtExpertVolumeSphereRadius o
		)
	else if !strcmp s plugloc "EXPERT_VOLUME_CONE" then
		(
		 _SHOWtext txtExpertVolumeConeMsg WINDOW_UNHIDDEN;
		 _SHOWtext txtExpertVolumeConeLong WINDOW_UNHIDDEN;
		 _SHOWtext txtExpertVolumeConeLarg WINDOW_UNHIDDEN;
		 _SHOWtext txtExpertVolumeConeHaut WINDOW_UNHIDDEN;
		 expert_volumeCone txtExpertVolumeConeLong [o 1];
		 expert_volumeCone txtExpertVolumeConeLarg [o 2];
		 expert_volumeCone txtExpertVolumeConeHaut [o 3]
		)
	else if !strcmp s plugloc "EXPERT_VOLUME_PLAN" then
		(
		 _SHOWtext txtExpertVolumePlanMsg WINDOW_UNHIDDEN;
		 _SHOWtext txtExpertVolumePlanLong WINDOW_UNHIDDEN;
		 _SHOWtext txtExpertVolumePlanLarg WINDOW_UNHIDDEN;
		 expert_volumePlan txtExpertVolumePlanLong [o 1];
		 expert_volumePlan txtExpertVolumePlanLarg [o 2]
		)
	else if !strcmp s plugloc "EXPERT_VOLUME_LINE" then
		(
		 _SHOWtext txtExpertVolumeLineMsg WINDOW_UNHIDDEN;
		 _SHOWtext txtExpertVolumeLineLong WINDOW_UNHIDDEN;
		 expert_volumeLine txtExpertVolumeLineLong o
		)
	else
		0;;

// les vecteurs de l'effet ' CONSTANT ' ont été modifiés : la nouvelle donnée est envoyée au serveur
fun expert_effectConstant(obj, o)=
	let _GETtext txtExpertEffectConstantX -> x in
	let _GETtext txtExpertEffectConstantY -> y in
	let _GETtext txtExpertEffectConstantZ -> z in
	UsendMessage ObUi o "expert_effectConstant" linebuild x :: y :: z :: nil;;

// les vecteurs de l'effet ' ELECTRIC ' ont été modifiés : la nouvelle donnée est envoyée au serveur
fun expert_effectElectric(obj, o)=
	let _GETtext txtExpertEffectElectricAX -> ax in
	let _GETtext txtExpertEffectElectricAY -> ay in
	let _GETtext txtExpertEffectElectricAZ -> az in
	let _GETtext txtExpertEffectElectricBX -> bx in
	UsendMessage ObUi o "expert_effectElectric" linebuild ax :: ay :: az :: bx :: nil;;

// les vecteurs de l'effet ' MAGNETIC ' ont été modifiés : la nouvelle donnée est envoyée au serveur
fun expert_effectMagnetic(obj, o)=
	let _GETtext txtExpertEffectMagneticAX -> ax in
	let _GETtext txtExpertEffectMagneticAY -> ay in
	let _GETtext txtExpertEffectMagneticAZ -> az in
	let _GETtext txtExpertEffectMagneticBX -> bx in
	UsendMessage ObUi o "expert_effectMagnetic" linebuild ax :: ay :: az :: bx :: nil;;

// les vecteurs de l'effet ' CHAOTIC0 ' ont été modifiés : la nouvelle donnée est envoyée au serveur
fun expert_effectChaotic0(obj, o)=
	let _GETtext txtExpertEffectChaotic0AX -> ax in
	let _GETtext txtExpertEffectChaotic0AY -> ay in
	let _GETtext txtExpertEffectChaotic0AZ -> az in
	let _GETtext txtExpertEffectChaotic0BX -> bx in
	let _GETtext txtExpertEffectChaotic0BX -> by in
	let _GETtext txtExpertEffectChaotic0BX -> bz in
	UsendMessage ObUi o "expert_effectChotic0" linebuild ax :: ay :: az :: bx :: by ::bz :: nil;;

// les vecteurs de l'effet ' CHAOTIC1 ' ont été modifiés : la nouvelle donnée est envoyée au serveur
fun expert_effectChaotic1(obj, o)=
	let _GETtext txtExpertEffectChaotic1AX -> ax in
	let _GETtext txtExpertEffectChaotic1AY -> ay in
	let _GETtext txtExpertEffectChaotic1AZ -> az in
	let _GETtext txtExpertEffectChaotic1BX -> bx in
	let _GETtext txtExpertEffectChaotic1BX -> by in
	let _GETtext txtExpertEffectChaotic1BX -> bz in
	UsendMessage ObUi o "expert_effectChotic1" linebuild ax :: ay :: az :: bx :: by ::bz :: nil;;

// les vecteurs de l'effet ' HELICOIDAL ' ont été modifiés : la nouvelle donnée est envoyée au serveur
fun expert_effectHelicoid(obj, o)=
	let _GETtext txtExpertEffectHelicoidAX -> ax in
	let _GETtext txtExpertEffectHelicoidAY -> ay in
	let _GETtext txtExpertEffectHelicoidAZ -> az in
	let _GETtext txtExpertEffectHelicoidBX -> bx in
	let _GETtext txtExpertEffectHelicoidBX -> by in
	let _GETtext txtExpertEffectHelicoidBX -> bz in
	UsendMessage ObUi o "expert_effectHelicoid" linebuild ax :: ay :: az :: bx :: by ::bz :: nil;;

// l'effet a été changé. Seuls les champs de données correspondant à l'effet sélectionné sont montrés. 
// Le nouvel effet est envoyé au serveur
// fun [ObjBox Ob I S] I
fun expert_effectChoice(obj, o, i, s)=
	_SHOWtext txtExpertEffectConstantMsg WINDOW_HIDDEN;
	_SHOWtext txtExpertEffectConstantX WINDOW_HIDDEN;
	_SHOWtext txtExpertEffectConstantY WINDOW_HIDDEN;
	_SHOWtext txtExpertEffectConstantZ WINDOW_HIDDEN;
	_SHOWtext txtExpertEffectElectricMsg WINDOW_HIDDEN;
	_SHOWtext txtExpertEffectElectricAX WINDOW_HIDDEN;
	_SHOWtext txtExpertEffectElectricAY WINDOW_HIDDEN;
	_SHOWtext txtExpertEffectElectricAZ WINDOW_HIDDEN;
	_SHOWtext txtExpertEffectElectricBX WINDOW_HIDDEN;
	_SHOWtext txtExpertEffectMagneticMsg WINDOW_HIDDEN;
	_SHOWtext txtExpertEffectMagneticAX WINDOW_HIDDEN;
	_SHOWtext txtExpertEffectMagneticAY WINDOW_HIDDEN;
	_SHOWtext txtExpertEffectMagneticAZ WINDOW_HIDDEN;
	_SHOWtext txtExpertEffectMagneticBX WINDOW_HIDDEN;
	_SHOWtext txtExpertEffectChaotic0Msg WINDOW_HIDDEN;
	_SHOWtext txtExpertEffectChaotic0AX WINDOW_HIDDEN;
	_SHOWtext txtExpertEffectChaotic0AY WINDOW_HIDDEN;
	_SHOWtext txtExpertEffectChaotic0AZ WINDOW_HIDDEN;
	_SHOWtext txtExpertEffectChaotic0BX WINDOW_HIDDEN;
	_SHOWtext txtExpertEffectChaotic0BY WINDOW_HIDDEN;
	_SHOWtext txtExpertEffectChaotic0BZ WINDOW_HIDDEN;
	_SHOWtext txtExpertEffectChaotic1Msg WINDOW_HIDDEN;
	_SHOWtext txtExpertEffectChaotic1AX WINDOW_HIDDEN;
	_SHOWtext txtExpertEffectChaotic1AY WINDOW_HIDDEN;
	_SHOWtext txtExpertEffectChaotic1AZ WINDOW_HIDDEN;
	_SHOWtext txtExpertEffectChaotic1BX WINDOW_HIDDEN;
	_SHOWtext txtExpertEffectChaotic1BY WINDOW_HIDDEN;
	_SHOWtext txtExpertEffectChaotic1BZ WINDOW_HIDDEN;
	_SHOWtext txtExpertEffectHelicoidMsg WINDOW_HIDDEN;
	_SHOWtext txtExpertEffectHelicoidAX WINDOW_HIDDEN;
	_SHOWtext txtExpertEffectHelicoidAY WINDOW_HIDDEN;
	_SHOWtext txtExpertEffectHelicoidAZ WINDOW_HIDDEN;
	_SHOWtext txtExpertEffectHelicoidBX WINDOW_HIDDEN;
	_SHOWtext txtExpertEffectHelicoidBY WINDOW_HIDDEN;
	_SHOWtext txtExpertEffectHelicoidBZ WINDOW_HIDDEN;
	if !strcmp s plugloc "EXPERT_EFFECT_CONSTANT" then
		(
		 _SHOWtext txtExpertEffectConstantMsg WINDOW_UNHIDDEN;
		 _SHOWtext txtExpertEffectConstantX WINDOW_UNHIDDEN;
		 _SHOWtext txtExpertEffectConstantY WINDOW_UNHIDDEN;
		 _SHOWtext txtExpertEffectConstantZ WINDOW_UNHIDDEN;
		 expert_effectConstant nil o
		)
	else if !strcmp s plugloc "EXPERT_EFFECT_ELECTRIC" then
		(
		 _SHOWtext txtExpertEffectElectricMsg WINDOW_UNHIDDEN;
		 _SHOWtext txtExpertEffectElectricAX WINDOW_UNHIDDEN;
		 _SHOWtext txtExpertEffectElectricAY WINDOW_UNHIDDEN;
		 _SHOWtext txtExpertEffectElectricAZ WINDOW_UNHIDDEN;
		 _SHOWtext txtExpertEffectElectricBX WINDOW_UNHIDDEN;
		 expert_effectElectric nil o
		)
	else if !strcmp s plugloc "EXPERT_EFFECT_MAGNETIC" then
		(
		 _SHOWtext txtExpertEffectMagneticMsg WINDOW_UNHIDDEN;
		 _SHOWtext txtExpertEffectMagneticAX WINDOW_UNHIDDEN;
		 _SHOWtext txtExpertEffectMagneticAY WINDOW_UNHIDDEN;
		 _SHOWtext txtExpertEffectMagneticAZ WINDOW_UNHIDDEN;
		 _SHOWtext txtExpertEffectMagneticBX WINDOW_UNHIDDEN;
		 expert_effectMagnetic nil o
		)
	else if !strcmp s plugloc "EXPERT_EFFECT_CHAOTIC0" then
		(
		 _SHOWtext txtExpertEffectChaotic0Msg WINDOW_UNHIDDEN;
		 _SHOWtext txtExpertEffectChaotic0AX WINDOW_UNHIDDEN;
		 _SHOWtext txtExpertEffectChaotic0AY WINDOW_UNHIDDEN;
		 _SHOWtext txtExpertEffectChaotic0AZ WINDOW_UNHIDDEN;
		 _SHOWtext txtExpertEffectChaotic0BX WINDOW_UNHIDDEN;
		 _SHOWtext txtExpertEffectChaotic0BY WINDOW_UNHIDDEN;
		 _SHOWtext txtExpertEffectChaotic0BZ WINDOW_UNHIDDEN;
		 expert_effectChaotic0 nil o
		)
	else if !strcmp s plugloc "EXPERT_EFFECT_CHAOTIC1" then
		(
		 _SHOWtext txtExpertEffectChaotic1Msg WINDOW_UNHIDDEN;
		 _SHOWtext txtExpertEffectChaotic1AX WINDOW_UNHIDDEN;
		 _SHOWtext txtExpertEffectChaotic1AY WINDOW_UNHIDDEN;
		 _SHOWtext txtExpertEffectChaotic1AZ WINDOW_UNHIDDEN;
		 _SHOWtext txtExpertEffectChaotic1BX WINDOW_UNHIDDEN;
		 _SHOWtext txtExpertEffectChaotic1BY WINDOW_UNHIDDEN;
		 _SHOWtext txtExpertEffectChaotic1BZ WINDOW_UNHIDDEN;
		 expert_effectChaotic1 nil o
		)
	else if !strcmp s plugloc "EXPERT_EFFECT_HELICOID" then
		(
		 _SHOWtext txtExpertEffectHelicoidMsg WINDOW_UNHIDDEN;
		 _SHOWtext txtExpertEffectHelicoidAX WINDOW_UNHIDDEN;
		 _SHOWtext txtExpertEffectHelicoidAY WINDOW_UNHIDDEN;
		 _SHOWtext txtExpertEffectHelicoidAZ WINDOW_UNHIDDEN;
		 _SHOWtext txtExpertEffectHelicoidBX WINDOW_UNHIDDEN;
		 _SHOWtext txtExpertEffectHelicoidBY WINDOW_UNHIDDEN;
		 _SHOWtext txtExpertEffectHelicoidBZ WINDOW_UNHIDDEN;
		 expert_effectHelicoid nil o
		)
	else
		0;;
		
fun expert_billboard(obj, o, state)=
	UsendMessage ObUi o "expert_billboard" itoa state;;
	
fun expert_rainbow(obj, o, state)=
	UsendMessage ObUi o "expert_rainbow" itoa state;;
	
fun expert_masse(obj, o)=
	let _GETtext obj -> m in
	UsendMessage ObUi o "expert_masse" m;;
		
// les changements doivent être appliqués (état = 1) ou non (état = 0) à tous les clients enregistrés auprès du plugin.
// cet état est envoyé au serveur
fun expert_allClients(obj, o, state)=
	UsendMessage ObUi o "expert_allClients" itoa state;;

// les changements doivent être sauvegardés sur le serveur (fichier *.dms) si l'état vaut 1 sinon ils seront perdus auprochain redémarrage du serveur
// cet état est envoyé au serveur
fun expert_uploadSrv(obj, o, state)=
	UsendMessage ObUi o "expert_upload" itoa state;;


/*
	OTHERS
*/
// Suppression des particules
fun plugin_suppr(obj, o)=
	UsendMessage ObUi o "plugin_stop" nil;;

fun help_end(obj, u)=
	set winHelp = nil;;
	
fun plugin_help(obj, u)=
	let u -> [win h] in
	if winHelp == nil then
		(
		 set winHelp = _CRwindow _channel win 0 0 400 400 WN_MENU|WN_MINBOX/* |WN_NOSCOL */ " HELP !";
		 _CBwinDestroy winHelp @help_end 0;
		 _CRtext _channel winHelp 5 5 390 390 ET_VSCROLL plughelp M3objName session h
		)
	else
		nil;;



/*
	MAIN
*/

fun win_paint(obj, u)=
	_PAINTrectangle obj 155 30 20 20 DRAW_SOLID 1 0 DRAW_SOLID colorInitClick;;

// création de la fenêtre d'édition en ligne
// fun [ObjWin H3d HMat3d S Ob] I
fun dynamicedit(win, obj, mat, param, o)=
	if obj == nil then
		nil
	else
		let strextr param -> l in
		let _GETwindowSizePosition win -> [_ _ x y] in
		let [500 760] -> [w h] in
		let if win == nil then
				_CRwindow _channel DMSwin 0 0 w h WN_MENU strcat plugloc "TITLE" M3objName session obj
			else
				win
			-> win in
		(
		 // misc.
		 _SIZEwindow win w h x y;
		 _CLRwindow win;
		 _CBwinPaint win @win_paint 0;
		 set bmpcolor = _LDbitmap _channel _checkpack "dms/3d/plugins/dynparticles/_colormap.bmp";
		 set font = _CRfont _channel 14 0 0 "Arial";
	 
		 // _CRtext _channel win 5 5 w-10 20 ET_BORDER strcat plugloc "TITLE" M3objName session obj;
	 
		 // Couleurs
		 _CRtext _channel win 5 5 w-10 20 ET_BORDER plugloc "TITLE_COLOR";
		 _CRtext _channel win 5 30 145 20 0 plugloc "TITLE_COLOR_INIT";
		 set winColor = _CRwindow _channel win 5 55 170 78 WN_CHILDINSIDE|WN_NOCAPTION nil;
		 _CBwinPaint winColor @color_winPaint 0;
		 _CBwinDestroy winColor @color_winEnd 0;
		 _CBwinClick winColor @color_winClick [win o];
	 
		 _CRtext _channel win (w/2)+5 30 (w/2)-40 20 0 plugloc "TITLE_COLOR_ALPHA";
		 set txtAlphaValue = _CRtext _channel win w-30 30 25 20 ET_ALIGN_RIGHT "100 %";
		 set sliColorAlpha = _CRslider _channel win _GETdefaultFont (w/2)+5 55 (w/2)-10 20 10 0.0 100.0 100.0 100.0 mkfun4 @color_alphaClick o SLIDER_INTER_FIXED|SLIDER_BUTTON;
		 _SETsliderBackColor sliColorAlpha 0xffffff;
		 _SETsliderPrecisionStep sliColorAlpha 1.0;
		 _SETsliderColor sliColorAlpha 0x00ff00;
		 _SETsliderCursorColor sliColorAlpha 0xff0000;
		 _SETsliderPrecisionMark sliColorAlpha 0;
		 
		 set cColorCycle = _CRcheck _channel win (w/2)+5 90 (w/2)-10 20 CH_LEFT plugloc "TITLE_COLOR_CYCLE";
		 _CBcheck cColorCycle @color_cycleColor o;
		 _CRtext _channel win (w/2)+5 110 (w/2)-10 25 0 plugloc "TITLE_COLOR_CYCLEMSG";
		 
		 // Tailles
		 _CRtext _channel win 5 140 w-10 20 ET_BORDER plugloc "TITLE_SIZE";
		 _CRtext _channel win 5 165 (w/2)-55 20 0 plugloc "TITLE_SIZE_MAX";
		 set txtSizeMax = _CReditLine _channel win (w/2)-45 165 40 20 ET_DOWN|ET_NUMBER "10";
		 set cSizeConst = _CRcheck _channel win (w/2)+5 165 (w/2)-10 20 CH_LEFT plugloc "TITLE_SIZE_CONST";
		 _CBcheck cSizeConst @size_sizeConst 0;
		 
		 let atoi _GETtext txtSizeMax -> m in
		 size_initList m;
		 set listSizesOld = listSizes;
		 
		 set winSize = _CRwindow _channel win 5 190 w-10 145 WN_CHILDINSIDE|WN_NOCAPTION|WN_DOWN nil;
		 _ENwindow winSize _GETcheck cSizeConst;
		 _CBwinPaint winSize @size_winPaint 0;
		 _CBwinClick winSize @size_winClick o;
		 size_winCrAxes;
		 
		 // Paramètres avancés
		 _CRtext _channel win 5 340 w-10 20 ET_BORDER plugloc "TITLE_EXPERT";
		 
		 // PCL_INFINIT
		 _CRtext _channel win 5 365 w-60 20 0 plugloc "EXPERT_INFINIT";
		 set txtExpertInfinit = _CReditLine _channel win w-50 365 45 20 ET_DOWN|ET_ALIGN_RIGHT|ET_NUMBER "96";
		 _CBtext txtExpertInfinit @expert_infinit o;
		 
		 // VOLUME
		 _CRtext _channel win 5 390 w-120 20 0 plugloc "EXPERT_VOLUME";
		 set cmExpertVolume = _CRcombo _channel win w-110 390 105 90 CB_NOEDIT|ET_ALIGN_RIGHT nil;
		 _ADDcombo cmExpertVolume 0 plugloc "EXPERT_VOLUME_SPHERE";
		 _ADDcombo cmExpertVolume 1 plugloc "EXPERT_VOLUME_CONE";
		 _ADDcombo cmExpertVolume 2 plugloc "EXPERT_VOLUME_PLAN";
		 _ADDcombo cmExpertVolume 3 plugloc "EXPERT_VOLUME_LINE";
		 _SELcombo cmExpertVolume 0;
		 _CBcombo cmExpertVolume @expert_volumeChoice o;
		 // VOLUME SPHERE
		 set txtExpertVolumeSphereRadiusMsg = _CRtext _channel win 5 415 w-120 20 0 plugloc "EXPERT_VOLUME_SPHERE_RADIUS";
		 set txtExpertVolumeSphereRadius = _CReditLine _channel win w-110 415 105 20 ET_DOWN|ET_ALIGN_RIGHT|ET_NUMBER "100";
		 _CBtext txtExpertVolumeSphereRadius @expert_volumeSphereRadius o;
		 // VOLUME CÔNE
		 set txtExpertVolumeConeMsg = _CRtext _channel win 5 415 w-120 40 0 plugloc "EXPERT_VOLUME_CONE_DIMENSIONS";
		 set txtExpertVolumeConeLong = _CReditLine _channel win w-110 415 105 20 ET_DOWN|ET_ALIGN_RIGHT|ET_NUMBER "500";
		 set txtExpertVolumeConeLarg = _CReditLine _channel win w-110 440 105 20 ET_DOWN|ET_ALIGN_RIGHT|ET_NUMBER "300";
		 set txtExpertVolumeConeHaut = _CReditLine _channel win w-110 465 105 20 ET_DOWN|ET_ALIGN_RIGHT|ET_NUMBER "1000";
		 _CBtext txtExpertVolumeConeLong @expert_volumeCone [o 1];
		 _CBtext txtExpertVolumeConeLarg @expert_volumeCone [o 2];
		 _CBtext txtExpertVolumeConeHaut @expert_volumeCone [o 3];
		 _SHOWtext txtExpertVolumeConeMsg WINDOW_HIDDEN;
		 _SHOWtext txtExpertVolumeConeLong WINDOW_HIDDEN;
		 _SHOWtext txtExpertVolumeConeLarg WINDOW_HIDDEN;
		 _SHOWtext txtExpertVolumeConeHaut WINDOW_HIDDEN;
		 // VOLUME PLAN
		 set txtExpertVolumePlanMsg = _CRtext _channel win 5 415 w-120 40 0 plugloc "EXPERT_VOLUME_PLAN_DIMENSIONS";
		 set txtExpertVolumePlanLong = _CReditLine _channel win w-110 415 105 20 ET_DOWN|ET_ALIGN_RIGHT|ET_NUMBER "500";
		 set txtExpertVolumePlanLarg = _CReditLine _channel win w-110 440 105 20 ET_DOWN|ET_ALIGN_RIGHT|ET_NUMBER "300";
		 _CBtext txtExpertVolumePlanLong @expert_volumePlan [o 1];
		 _CBtext txtExpertVolumePlanLarg @expert_volumePlan [o 2];
		 _SHOWtext txtExpertVolumePlanMsg WINDOW_HIDDEN;
		 _SHOWtext txtExpertVolumePlanLong WINDOW_HIDDEN;
		 _SHOWtext txtExpertVolumePlanLarg WINDOW_HIDDEN;
		 // VOLUME LIGNE
		 set txtExpertVolumeLineMsg = _CRtext _channel win 5 415 w-120 20 0 plugloc "EXPERT_VOLUME_LINE_DIMENSIONS";
		 set txtExpertVolumeLineLong = _CReditLine _channel win w-110 415 105 20 ET_DOWN|ET_ALIGN_RIGHT|ET_NUMBER "500";
		 _CBtext txtExpertVolumeLineLong @expert_volumeLine o;
		 _SHOWtext txtExpertVolumeLineMsg WINDOW_HIDDEN;
		 _SHOWtext txtExpertVolumeLineLong WINDOW_HIDDEN;
		 
		 // EFFETS
		 _CRtext _channel win 5 490 w-120 20 0 plugloc "EXPERT_EFFECT";
		 set cmExpertEffect = _CRcombo _channel win w-110 490 105 130 CB_NOEDIT|ET_ALIGN_RIGHT nil;
		 _ADDcombo cmExpertEffect 0 plugloc "EXPERT_EFFECT_CONSTANT";
		 _ADDcombo cmExpertEffect 1 plugloc "EXPERT_EFFECT_ELECTRIC";
		 _ADDcombo cmExpertEffect 2 plugloc "EXPERT_EFFECT_MAGNETIC";
		 _ADDcombo cmExpertEffect 3 plugloc "EXPERT_EFFECT_CHAOTIC0";
		 _ADDcombo cmExpertEffect 4 plugloc "EXPERT_EFFECT_CHAOTIC1";
		 _ADDcombo cmExpertEffect 5 plugloc "EXPERT_EFFECT_HELICOID";
		 _SELcombo cmExpertEffect 0;
		 _CBcombo cmExpertEffect @expert_effectChoice o;
		 // EFFET CONSTANT
		 set txtExpertEffectConstantMsg = _CRtext _channel win 5 515 w-10 20 0 plugloc "EXPERT_EFECT_CONSTANT_MSG";
		 set txtExpertEffectConstantX = _CReditLine _channel win w-295 540 90 20 ET_DOWN|ET_ALIGN_RIGHT|ET_NUMBER "0";
		 set txtExpertEffectConstantY = _CReditLine _channel win w-195 540 90 20 ET_DOWN|ET_ALIGN_RIGHT|ET_NUMBER "5";
		 set txtExpertEffectConstantZ = _CReditLine _channel win w-95 540 90 20 ET_DOWN|ET_ALIGN_RIGHT|ET_NUMBER "10";
		 _CBtext txtExpertEffectConstantX @expert_effectConstant o;
		 _CBtext txtExpertEffectConstantX @expert_effectConstant o;
		 _CBtext txtExpertEffectConstantX @expert_effectConstant o;
		 // EFFET ELECTRIQUE
		 set txtExpertEffectElectricMsg = _CRtext _channel win 5 515 w-10 40 0 plugloc "EXPERT_EFECT_ELECTRIC_MSG";
		 set txtExpertEffectElectricAX = _CReditLine _channel win w-295 560 90 20 ET_DOWN|ET_ALIGN_RIGHT|ET_NUMBER "30";
		 set txtExpertEffectElectricAY = _CReditLine _channel win w-195 560 90 20 ET_DOWN|ET_ALIGN_RIGHT|ET_NUMBER "20";
		 set txtExpertEffectElectricAZ = _CReditLine _channel win w-95 560 90 20 ET_DOWN|ET_ALIGN_RIGHT|ET_NUMBER "15";
		 set txtExpertEffectElectricBX = _CReditLine _channel win w-95 585 90 20 ET_DOWN|ET_ALIGN_RIGHT|ET_NUMBER "5";
		 _CBtext txtExpertEffectElectricAX @expert_effectElectric o;
		 _CBtext txtExpertEffectElectricAY @expert_effectElectric o;
		 _CBtext txtExpertEffectElectricAZ @expert_effectElectric o;
		 _CBtext txtExpertEffectElectricBX @expert_effectElectric o;
		 _SHOWtext txtExpertEffectElectricMsg WINDOW_HIDDEN;
		 _SHOWtext txtExpertEffectElectricAX WINDOW_HIDDEN;
		 _SHOWtext txtExpertEffectElectricAY WINDOW_HIDDEN;
		 _SHOWtext txtExpertEffectElectricAZ WINDOW_HIDDEN;
		 _SHOWtext txtExpertEffectElectricBX WINDOW_HIDDEN;
		 // EFFET MAGNETIQUE
		 set txtExpertEffectMagneticMsg = _CRtext _channel win 5 515 w-10 40 0 plugloc "EXPERT_EFECT_MAGNETIC_MSG";
		 set txtExpertEffectMagneticAX = _CReditLine _channel win w-295 560 90 20 ET_DOWN|ET_ALIGN_RIGHT|ET_NUMBER "30";
		 set txtExpertEffectMagneticAY = _CReditLine _channel win w-195 560 90 20 ET_DOWN|ET_ALIGN_RIGHT|ET_NUMBER "15";
		 set txtExpertEffectMagneticAZ = _CReditLine _channel win w-95 560 90 20 ET_DOWN|ET_ALIGN_RIGHT|ET_NUMBER "20";
		 set txtExpertEffectMagneticBX = _CReditLine _channel win w-95 585 90 20 ET_DOWN|ET_ALIGN_RIGHT|ET_NUMBER "1";
		 _CBtext txtExpertEffectMagneticAX @expert_effectMagnetic o;
		 _CBtext txtExpertEffectMagneticAY @expert_effectMagnetic o;
		 _CBtext txtExpertEffectMagneticAZ @expert_effectMagnetic o;
		 _CBtext txtExpertEffectMagneticBX @expert_effectMagnetic o;
		 _SHOWtext txtExpertEffectMagneticMsg WINDOW_HIDDEN;
		 _SHOWtext txtExpertEffectMagneticAX WINDOW_HIDDEN;
		 _SHOWtext txtExpertEffectMagneticAY WINDOW_HIDDEN;
		 _SHOWtext txtExpertEffectMagneticAZ WINDOW_HIDDEN;
		 _SHOWtext txtExpertEffectMagneticBX WINDOW_HIDDEN;
		 // EFFET CHAOTIQUE 0
		 set txtExpertEffectChaotic0Msg = _CRtext _channel win 5 515 w-10 40 0 plugloc "EXPERT_EFECT_CHAOTIC0_MSG";
		 set txtExpertEffectChaotic0AX = _CReditLine _channel win w-295 560 90 20 ET_DOWN|ET_ALIGN_RIGHT|ET_NUMBER "30";
		 set txtExpertEffectChaotic0AY = _CReditLine _channel win w-195 560 90 20 ET_DOWN|ET_ALIGN_RIGHT|ET_NUMBER "15";
		 set txtExpertEffectChaotic0AZ = _CReditLine _channel win w-95 560 90 20 ET_DOWN|ET_ALIGN_RIGHT|ET_NUMBER "20";
		 set txtExpertEffectChaotic0BX = _CReditLine _channel win w-295 585 90 20 ET_DOWN|ET_ALIGN_RIGHT|ET_NUMBER "1";
		 set txtExpertEffectChaotic0BY = _CReditLine _channel win w-195 585 90 20 ET_DOWN|ET_ALIGN_RIGHT|ET_NUMBER "15";
		 set txtExpertEffectChaotic0BZ = _CReditLine _channel win w-95 585 90 20 ET_DOWN|ET_ALIGN_RIGHT|ET_NUMBER "20";
		 _CBtext txtExpertEffectChaotic0AX @expert_effectChaotic0 o;
		 _CBtext txtExpertEffectChaotic0AY @expert_effectChaotic0 o;
		 _CBtext txtExpertEffectChaotic0AZ @expert_effectChaotic0 o;
		 _CBtext txtExpertEffectChaotic0BX @expert_effectChaotic0 o;
		 _CBtext txtExpertEffectChaotic0BY @expert_effectChaotic0 o;
		 _CBtext txtExpertEffectChaotic0BZ @expert_effectChaotic0 o;
		 _SHOWtext txtExpertEffectChaotic0Msg WINDOW_HIDDEN;
		 _SHOWtext txtExpertEffectChaotic0AX WINDOW_HIDDEN;
		 _SHOWtext txtExpertEffectChaotic0AY WINDOW_HIDDEN;
		 _SHOWtext txtExpertEffectChaotic0AZ WINDOW_HIDDEN;
		 _SHOWtext txtExpertEffectChaotic0BX WINDOW_HIDDEN;
		 _SHOWtext txtExpertEffectChaotic0BY WINDOW_HIDDEN;
		 _SHOWtext txtExpertEffectChaotic0BZ WINDOW_HIDDEN;
		 // EFFET CHAOTIQUE 1
		 set txtExpertEffectChaotic1Msg = _CRtext _channel win 5 515 w-10 40 0 plugloc "EXPERT_EFECT_CHAOTIC1_MSG";
		 set txtExpertEffectChaotic1AX = _CReditLine _channel win w-295 560 90 20 ET_DOWN|ET_ALIGN_RIGHT|ET_NUMBER "30";
		 set txtExpertEffectChaotic1AY = _CReditLine _channel win w-195 560 90 20 ET_DOWN|ET_ALIGN_RIGHT|ET_NUMBER "15";
		 set txtExpertEffectChaotic1AZ = _CReditLine _channel win w-95 560 90 20 ET_DOWN|ET_ALIGN_RIGHT|ET_NUMBER "20";
		 set txtExpertEffectChaotic1BX = _CReditLine _channel win w-295 585 90 20 ET_DOWN|ET_ALIGN_RIGHT|ET_NUMBER "1";
		 set txtExpertEffectChaotic1BY = _CReditLine _channel win w-195 585 90 20 ET_DOWN|ET_ALIGN_RIGHT|ET_NUMBER "15";
		 set txtExpertEffectChaotic1BZ = _CReditLine _channel win w-95 585 90 20 ET_DOWN|ET_ALIGN_RIGHT|ET_NUMBER "20";
		 _CBtext txtExpertEffectChaotic1AX @expert_effectChaotic1 o;
		 _CBtext txtExpertEffectChaotic1AY @expert_effectChaotic1 o;
		 _CBtext txtExpertEffectChaotic1AZ @expert_effectChaotic1 o;
		 _CBtext txtExpertEffectChaotic1BX @expert_effectChaotic1 o;
		 _CBtext txtExpertEffectChaotic1BY @expert_effectChaotic1 o;
		 _CBtext txtExpertEffectChaotic1BZ @expert_effectChaotic1 o;
		 _SHOWtext txtExpertEffectChaotic1Msg WINDOW_HIDDEN;
		 _SHOWtext txtExpertEffectChaotic1AX WINDOW_HIDDEN;
		 _SHOWtext txtExpertEffectChaotic1AY WINDOW_HIDDEN;
		 _SHOWtext txtExpertEffectChaotic1AZ WINDOW_HIDDEN;
		 _SHOWtext txtExpertEffectChaotic1BX WINDOW_HIDDEN;
		 _SHOWtext txtExpertEffectChaotic1BY WINDOW_HIDDEN;
		 _SHOWtext txtExpertEffectChaotic1BZ WINDOW_HIDDEN;
		 // EFFET HELICOÏDAL
		 set txtExpertEffectHelicoidMsg = _CRtext _channel win 5 515 w-10 40 0 plugloc "EXPERT_EFECT_HELICOID_MSG";
		 set txtExpertEffectHelicoidAX = _CReditLine _channel win w-295 560 90 20 ET_DOWN|ET_ALIGN_RIGHT|ET_NUMBER "30";
		 set txtExpertEffectHelicoidAY = _CReditLine _channel win w-195 560 90 20 ET_DOWN|ET_ALIGN_RIGHT|ET_NUMBER "15";
		 set txtExpertEffectHelicoidAZ = _CReditLine _channel win w-95 560 90 20 ET_DOWN|ET_ALIGN_RIGHT|ET_NUMBER "20";
		 set txtExpertEffectHelicoidBX = _CReditLine _channel win w-295 585 90 20 ET_DOWN|ET_ALIGN_RIGHT|ET_NUMBER "1";
		 set txtExpertEffectHelicoidBY = _CReditLine _channel win w-195 585 90 20 ET_DOWN|ET_ALIGN_RIGHT|ET_NUMBER "15";
		 set txtExpertEffectHelicoidBZ = _CReditLine _channel win w-95 585 90 20 ET_DOWN|ET_ALIGN_RIGHT|ET_NUMBER "20";
		 _CBtext txtExpertEffectHelicoidAX @expert_effectHelicoid o;
		 _CBtext txtExpertEffectHelicoidAY @expert_effectHelicoid o;
		 _CBtext txtExpertEffectHelicoidAZ @expert_effectHelicoid o;
		 _CBtext txtExpertEffectHelicoidBX @expert_effectHelicoid o;
		 _CBtext txtExpertEffectHelicoidBY @expert_effectHelicoid o;
		 _CBtext txtExpertEffectHelicoidBZ @expert_effectHelicoid o;
		 _SHOWtext txtExpertEffectHelicoidMsg WINDOW_HIDDEN;
		 _SHOWtext txtExpertEffectHelicoidAX WINDOW_HIDDEN;
		 _SHOWtext txtExpertEffectHelicoidAY WINDOW_HIDDEN;
		 _SHOWtext txtExpertEffectHelicoidAZ WINDOW_HIDDEN;
		 _SHOWtext txtExpertEffectHelicoidBX WINDOW_HIDDEN;
		 _SHOWtext txtExpertEffectHelicoidBY WINDOW_HIDDEN;
		 _SHOWtext txtExpertEffectHelicoidBZ WINDOW_HIDDEN;
		 
		 // PCL_BILLBOARD & PCL_RAINBOW
		 set cExpertBillboard = _CRcheck _channel win 5 610 w-10 20 CH_LEFT plugloc "EXPERT_BILLBOARD";
		 _CBcheck cExpertBillboard @expert_billboard o;
		 set cExpertRainbow = _CRcheck _channel win 5 635 w-10 20 CH_LEFT plugloc "EXPERT_RAINBOW";
		 _CBcheck cExpertRainbow @expert_rainbow o;
		 
		 // MASSE
		 _CRtext _channel win 5 660 w-60 20 0 plugloc "EXPERT_MASSE";
		 set txtExpertMasse = _CReditLine _channel win w-50 660 45 20 ET_DOWN|ET_ALIGN_RIGHT "0";
		 _CBtext txtExpertMasse @expert_masse o;
		 
		 // Affecter à tous les clients enregistrés ?
		 set cExpertAllClients = _CRcheck _channel win 5 685 w-10 20 CH_LEFT plugloc "EXPERT_ALLCLIENTS";
		 _CBcheck cExpertAllClients @expert_allClients o;
		 
		 // Sauvegarde sur le serveur ?
		 set cExpertUploadSrv = _CRcheck _channel win 5 710 w-10 20 CH_LEFT plugloc "EXPERT_UPLOADSRV";
		 _CBcheck cExpertUploadSrv @expert_uploadSrv o;
		 
		 // BTN SUPPRIMER & HELP
		 _CBbutton _CRbutton _channel win 5 735 (w/2)-10 20 0 plugloc "HELP" @plugin_help [win Objs];
		 _CBbutton _CRbutton _channel win (w/2)+5 735 (w/2)-10 20 0 plugloc "SUPPR" @plugin_suppr 0;
		 
		 0
		);;