Hello guys!
I'ver already posted that question on cgtalk, but no response so far.
I have a serious problem. Here is it:
A have a scene with multiple animated objects/meshes. Now I would like to attach them to one single mesh, whereas the animation of every single mesh should be preserved? It it possible? I found a script on scriptspot called Attach and Preserve Animation, but it seems that it's not working (I get an error, although all objects are Editable Meshes and vertex baked before with "Bake" by John Burnett as required). I would like to use the attached mesh as an ObjSrc Emitter for FumeFX.
Or if it is a possibility to automatically define multiple objects (around 100 pieces and more) as emitters with instanced Smoke, Velocity etc. values, much better!
Any help is appreciated!
Thanks!
Greets
Emil
if you post on cgfluids , youll get proper professionnal answers..
- atach ? you can link them to a parent that has an Attachment controller on it .. that will keep your animation per object intact while still following the movement of another object.. thats 1 way .. their is just alot of ways..
- Write a script .. i have my own for doing that ( somewhere deep in my drive backups ) .. the script can basicly create FFx Source instances , pick in each one an object array of your selection , randomize fume values and add them to the grid ( that part in earlier ffx version had to be done manually if i remember right..) ..
cheers,
I have seen soo much posts on cgtalk that give wrong ideas as of the real behaviors .. Some allan mckay wrong tutorials or some Chineese Fume Fx dvds that are showing that smoke quality = 9 is the best way to get nice smoke from fume Witch is also fundementally wrong ..i would stick to the official FFx Suport forum ( right here) or Cgfluids for getting your questions well answered..
my 2 cents..
<!-- w --><a class="postlink" href="http://www.cgfluids.com">http://www.cgfluids.com</a><!-- w -->
Rif Wrote:- atach ? you can link them to a parent that has an Attachment controller on it .. that will keep your animation per object intact while still following the movement of another object.. thats 1 way .. their is just alot of ways..
Yes, but still I would have multiple meshes, which I have to define as emitters manually, wouldn't I?
Greets
emil_vfx
Ahh , well you could pick the objects using a script as i said..
The Best way and the one i always use is to use Tp and Make your objects beeing particles.. Then with the Group as Object Function , you only have to pick 1 Group in 1 Single Fume Fx Source and you get emition from face normals etc..
if you cant do that , the scripting Adding object to respective source should be the way i think..
<!-- w --><a class="postlink" href="http://www.cgfluids.com">http://www.cgfluids.com</a><!-- w -->
Thanks.
But TP is not an option :-( If you find that script, I will be extraordinary happy if you could share it
Greets
emil_vfx
Rif Wrote:I have seen soo much posts on cgtalk that give wrong ideas as of the real behaviors ..
Sorry for off-topic
I hope I am not one of those posters :oops: (I try to be as correct as possible)
Would love to see some tut's from you rif I remeber the conversation went around a little while back. Would luv to have tut's from the masters!
blower of smoke ..ooOO
for the tutorials , i do want to do some at one point but i always have way too much work ! but in the eventuallity that i finnally get to it , it would be posted on cgfluids and most importantly it would be free for legit users of the respective products..
<!-- w --><a class="postlink" href="http://www.cgfluids.com">http://www.cgfluids.com</a><!-- w -->
ok so i cant find the script i had just now but heres the key functions youll need to script something for doing this.. so the goal is first to get the Sources objects copied , thats the standart copy() function .. ( for the purpose let say : For foo in "arrayofmeshes.count" do copy Ffxobjectsource1)..
then let say you dump those copied FFxobjectSource into "SourceArray"
the second goal is for each of those Object sources , you want to assign them each 1 of the meshes avalaible for emiting from right ? so something like : for foo in SourceArray Do append Arrayofmeshes[foo] SourceArray[foo].object .. that will add 1 of your mesh in 1 of your object sources ..
then you just open the ffx ui and pick add and select all your sources in the list ..
i didnt instance them ( instead of copy() , instance() ) as instance sources dont allow you to pick different objects.. maybe they should ..
So , because they are copies , that means youll also want to controll their changes all together ... So Use the SourceArray to to expose all the parameters of each source and to change them .. i suggest you create yourself shortcut functions .. something like that :
Fn AdjFuel =
(
for foo in Sourcearrsources do foo.fuel = Random 0 0
)
Fn AdjTemp=
(
for foo in Sourcearrsources do foo.temperature = Random 50 100
)
Fn AdjDensSm =
(
for foo in Sourcearrsources do foo.SmokeDensity = Random 2.00 3.00
)
etc..etc..
this way you can not only put all of them the same values but also add some randomness controlled ..
cheers,
<!-- w --><a class="postlink" href="http://www.cgfluids.com">http://www.cgfluids.com</a><!-- w -->
I have just about finished a script that does pretty much exactly what you're looking for (and probably what you already have rif)-- we have this issue all the time-- it's called Fume Source Manager. It can duplicate an object source to selected geometry (sets the object in the src) and then it has rollouts for all of the parameters of an object source. Then, based on the sources you have selected (will probably change this to a dropdown of selection sets or something instead) you can change all of the settings at once to all of the sources selected (with variation as well)... The main problem I'm having right now is the *fume*.addsource method. I would like the script to automatically add the sources to the fume grid chosen in the ui, but for some reason i keep getting "unknown system exception" can anybody else confirm issues with .addsource??? If i do it through the listener it occasionally crashes max...
Also: just wondering rif, if you know of a way to add / append an object to an object source without it already having something defined...?
Emil: if you're interested I can post what I have so far, minus the part with adding the duplicated source to the fumegrid for you if you want.
that part should be fixed on 1.1 solitude, if it has been reported ! their is a bunch of new Functions List added now ...
<!-- w --><a class="postlink" href="http://www.cgfluids.com">http://www.cgfluids.com</a><!-- w -->
thanks rif! Which part, the object source array? or the the addsource? I'll poke around some more in the other forum.
It's wierd though -- the addsource is very bitchy -- sometimes it works, sometimes it doesn't! =)
@ Solitude: If it's not too much work, you can post it, that would be great. Meanwhile I found a workaround: I just created a PFlow, which puts locked-on-emitter-particles on the meshes (they are selected as emitters within the Position Object Rollout), and then I created a Particle Src with the PFlow selected. Voila! ;-)
Best regards and thanks for the ideas, guys!
Emil
emil_vfx Wrote:@ Solitude: If it's not too much work, you can post it, that would be great. Meanwhile I found a workaround: I just created a PFlow, which puts locked-on-emitter-particles on the meshes (they are selected as emitters within the Position Object Rollout), and then I created a Particle Src with the PFlow selected. Voila! ;-)
Best regards and thanks for the ideas, guys!
Emil
If you're using the particle src, you're not really emitting from the geometry... you're emitting from a circle around the particle... so if it doesn't matter, then cool! otherwise (and it might be a bit long) go to maxscript -> newscript -> paste all this stuff, then select it all and drag it onto a toolbar. It's not complete -- i commented out the fumegrid button... so ignore that empty space at the top. If you have any questions let me know. When it's done I'll prob post it on scriptspot and put links in the appropriate forums.
Code: /*!
\file FumeSrcManager.ms
\remarks
\author Ian Farnsworth
\author Email: you wish =)
\author Company: Blur Studio
\date 01/30/08
*/
rollout ObjSrcDup "Source Duplication" width:152 height:296
(
local _objects = #()
fn fumegrid_filt obj = classof obj == FumeFX
fn objsrc_filt obj = classof obj == Object_Src
--pickbutton btn_fumegrid "Select Fume Grid" pos:[8,24] width:137 height:27 message:"Select FumeGrid" autoDisplay:true filter:fumegrid_filt
label lbl1 "Fume Grid:" pos:[8,8] width:133 height:16
pickbutton btn_objsrc "Select Object Src" pos:[8,80] width:137 height:27 message:"Select FumeGrid" autoDisplay:true filter:objsrc_filt
label lbl2 "Object Src to Copy" pos:[8,64] width:133 height:16
listbox listbx1 "Objects to be Sources" pos:[8,112] width:136 height:6
button btn_add "Add Selection to List" pos:[8,216] width:136 height:24
button btn_doit "Do It!" pos:[8,248] width:136 height:34
fn isValidObj obj = (
local valid = false
if ( superclassof obj == GeometryClass ) then (
if ( classof obj != FumeFx ) then (
valid = true
)
)
valid
)
on btn_add pressed do (
objSrcDup._objects = for obj in selection as array where isValidObj obj collect obj
listbx1.items = for obj in objSrcDup._objects collect obj.name
)
on btn_doit pressed do (
local src = btn_objsrc.object
-- local fg = btn_fumegrid.object
if ( src != undefined ) then (
if ( src.object.count != 0 ) then (
-- if ( fg != undefined ) then (
if ( objSrcDup._objects.count > 0 ) then (
for obj in objSrcDup._objects do(
SrcCopy = copy src
SrcCopy.pos = obj.center -- copy and move objectsrc to source object
SrcCopy.object = #(obj) -- selection has to be an array
SrcCopy.parent = obj -- parent object src to source object
--fg.addsource $SrcCopy -- add to fumegrid list
)
)
else messageBox "Please Select some Geometry"
--)
-- else messageBox "Fume grid not selected"
)
else messageBox "Object Src needs object picked"
)
else messageBox "Object Source not selected"
)
)
rollout srcparam "Parameters" width:160 height:88
(
checkbox chk_freeflow "Free Flow" pos:[80,8] width:64 height:16 enabled:true
spinner spn_IconSize "Icon Size:" pos:[24,32] width:120 height:16 range:[0,100000,0] scale:0.1
spinner spn_mapchan "Map Channel:" pos:[24,56] width:120 height:16 range:[0,100000,0] scale:1 fieldwidth:30 type:#integer
on srcparam open do
(
spn_Iconsize.value = 10
)
on chk_freeflow changed stat do
(
for obj in selection where classof obj == Object_Src do
(
if chk_freeflow.state == false then obj.FreeFlow = off
if chk_freeflow.state == true then obj.Freeflow = on
)
)
on spn_IconSize changed val do
(
for obj in selection where classof obj == Object_Src do obj.iconSize = spn_Iconsize.value
)
on spn_mapchan changed val do
(
for obj in selection where classof obj == Object_Src do obj.mapchannel = spn_mapchan.value
)
)
rollout srcfuelparam "Fuel" width:160 height:296
(
radiobuttons rdo_ftype "Type:" pos:[16,88] width:128 height:46 labels:#("Disabled", "Add", "Set") default:3 columns:2
button btn_updateftype "Update Fuel Type" pos:[24,136] width:112 height:24
spinner spn_famount "Amount" pos:[24,8] width:120 height:16 range:[0,100,0] scale:0.01
spinner spn_famountvar "Variation" pos:[24,32] width:120 height:16 range:[0,100,0] scale:0.01
button btn_updatefamounts "Update Amounts" pos:[24,56] width:112 height:24
mapButton btn_fmap "None" pos:[48,232] width:96 height:24
label lbl_fmap "Map:" pos:[16,232] width:24 height:24
radiobuttons rdo_fmapemit "Map Emission:" pos:[16,168] width:128 height:62 labels:#("Disabled", "Red", "Green", "Blue", "Intensity") default:1 columns:2
button brn_updatefmap "Update Fuel Map Info" pos:[16,264] width:128 height:24
on srcfuelparam open do
(
spn_famount.value = 100
)
on rdo_ftype changed stat do
(
for obj in selection where classof obj == Object_Src do
(
if rdo_ftype.state == 1 then obj.fueltype = 0
if rdo_ftype.state == 2 then obj.fueltype = 1
if rdo_ftype.state == 3 then obj.fueltype = 2
)
)
on btn_updateftype pressed do
(
for obj in selection where classof obj == Object_Src do
(
if rdo_ftype.state == 1 then obj.fueltype = 0
if rdo_ftype.state == 2 then obj.fueltype = 1
if rdo_ftype.state == 3 then obj.fueltype = 2
)
)
on spn_famount changed val do
(
for obj in selection where classof obj == Object_Src do
obj.Fire___Fuel = random (spn_famount.value - spn_famountvar.value) (spn_famount.value + spn_famountvar.value)
)
on btn_updatefamounts pressed do
(
for obj in selection where classof obj == Object_Src do
obj.Fire___Fuel = random (spn_famount.value - spn_famountvar.value) (spn_famount.value + spn_famountvar.value)
)
on btn_fmap picked mtl do
(
for obj in selection where classof obj == Object_Src do
obj.fuelmap = btn_fmap.map
btn_fmap.caption = btn_fmap.map as string
)
on rdo_fmapemit changed state do
(
for obj in selection where classof obj == Object_Src do
(
if rdo_fmapemit.state == 1 then obj.vcfuel = 0
if rdo_fmapemit.state == 2 then obj.vcfuel = 1
if rdo_fmapemit.state == 3 then obj.vcfuel = 2
if rdo_fmapemit.state == 4 then obj.vcfuel = 3
if rdo_fmapemit.state == 5 then obj.vcfuel = 4
)
)
on btn_updatefmap pressed do
(
for obj in selection where classof obj == Object_Src do
(
if rdo_fmapemit.state == 1 then obj.vcfuel = 0
if rdo_fmapemit.state == 2 then obj.vcfuel = 1
if rdo_fmapemit.state == 3 then obj.vcfuel = 2
if rdo_fmapemit.state == 4 then obj.vcfuel = 3
if rdo_fmapemit.state == 5 then obj.vcfuel = 4
obj.fuelmap = btn_fmap.map
btn_fmap.caption = btn_fmap.map as string
)
)
)
rollout srcsmokeparam "Smoke" width:160 height:296
(
radiobuttons rdo_stype "Type:" pos:[16,88] width:128 height:46 labels:#("Disabled", "Add", "Set") default:3 columns:2
button btn_updatestype "Update Smoke Type" pos:[25,136] width:112 height:24
spinner spn_Samount "Amount" pos:[24,8] width:120 height:16 range:[0,100000,0] scale:0.01
spinner spn_samountvar "Variation" pos:[24,32] width:120 height:16 range:[0,100000,0] scale:0.01
button btn_updatesamounts "Update Amounts" pos:[24,56] width:112 height:24
mapButton btn_smap "None" pos:[48,232] width:96 height:24
label lbl4 "Map:" pos:[16,232] width:24 height:24
radiobuttons rdo_smapemit "Map Emission:" pos:[16,168] width:128 height:62 labels:#("Disabled", "Red", "Green", "Blue", "Intensity") default:1 columns:2
button btn_updatesmap "Update Smoke Map Info" pos:[17,264] width:128 height:24
on srcsmokeparam open do
(
spn_samount.value = 2
)
on rdo_stype changed stat do
(
for obj in selection where classof obj == Object_Src do
(
if rdo_stype.state == 1 then obj.smoketype = 0
if rdo_stype.state == 2 then obj.smoketype = 1
if rdo_stype.state == 3 then obj.smoketype = 2
)
)
on btn_updatestype pressed do
(
for obj in selection where classof obj == Object_Src do
(
if rdo_stype.state == 1 then obj.smoketype = 0
if rdo_stype.state == 2 then obj.smoketype = 1
if rdo_stype.state == 3 then obj.smoketype = 2
)
)
on spn_Samount changed val do
(
for obj in selection where classof obj == Object_Src do
obj.Smoke___Density = random (spn_samount.value - spn_samountvar.value) (spn_samount.value + spn_samountvar.value)
)
on btn_updatesamounts pressed do
(
for obj in selection where classof obj == Object_Src do
obj.Smoke___Density = random (spn_samount.value - spn_samountvar.value) (spn_samount.value + spn_samountvar.value)
)
on btn_smap picked texmap do
(
for obj in selection where classof obj == Object_Src do
obj.densmap = btn_smap.map
btn_smap.caption = btn_smap.map as string
)
on rdo_smapemit changed stat do
(
for obj in selection where classof obj == Object_Src do
(
if rdo_smapemit.state == 1 then obj.vcdens = 0
if rdo_smapemit.state == 2 then obj.vcdens = 1
if rdo_smapemit.state == 3 then obj.vcdens = 2
if rdo_smapemit.state == 4 then obj.vcdens = 3
if rdo_smapemit.state == 5 then obj.vcdens = 4
)
)
on btn_updatesmap pressed do
(
for obj in selection where classof obj == Object_Src do
(
if rdo_smapemit.state == 1 then obj.vcdens = 0
if rdo_smapemit.state == 2 then obj.vcdens = 1
if rdo_smapemit.state == 3 then obj.vcdens = 2
if rdo_smapemit.state == 4 then obj.vcdens = 3
if rdo_smapemit.state == 5 then obj.vcdens = 4
obj.densmap = btn_smap.map
btn_smap.caption = btn_smap.map as string
)
)
)
rollout srctempparam "Temperature" width:160 height:296
(
radiobuttons rdo_ttype "Type:" pos:[16,88] width:128 height:46 labels:#("Disabled", "Add", "Set") default:3 columns:2
button btn_updatettype "Update Temp Type" pos:[17,136] width:128 height:24
spinner spn_tamount "Amount" pos:[25,10] width:120 height:16 range:[0,100000,0] scale:0.01
spinner spn_tamountvar "Variation" pos:[24,32] width:120 height:16 range:[0,100000,0] scale:0.01
button btn_updatetamounts "Update Amounts" pos:[16,56] width:128 height:24
mapButton btn_tmap "None" pos:[48,232] width:96 height:24
label lbl7 "Map:" pos:[16,232] width:24 height:24
radiobuttons rdo_tmapemit "Map Emission:" pos:[16,168] width:128 height:62 labels:#("Disabled", "Red", "Green", "Blue", "Intensity") default:1 columns:2
button btn_updatetmap "Update Temp Map Info" pos:[17,264] width:128 height:24
on srctempparam open do
(
spn_tamount.value = 300
)
on rdo_ttype changed stat do
(
for obj in selection where classof obj == Object_Src do
(
if rdo_ttype.state == 1 then obj.temptype = 0
if rdo_ttype.state == 2 then obj.temptype = 1
if rdo_ttype.state == 3 then obj.temptype = 2
)
)
on btn_updatettype pressed do
(
for obj in selection where classof obj == Object_Src do
(
if rdo_ttype.state == 1 then obj.temptype = 0
if rdo_ttype.state == 2 then obj.temptype = 1
if rdo_ttype.state == 3 then obj.temptype = 2
)
)
on spn_tamount changed val do
(
for obj in selection where classof obj == Object_Src do
obj.Temperature = spn_tamount.value
)
on btn_updatetamounts pressed do
(
for obj in selection where classof obj == Object_Src do
obj.Temperature = spn_tamount.value
)
on btn_tmap picked texmap do
(
for obj in selection where classof obj == Object_Src do
obj.tempmap = btn_tmap.map
btn_tmap.caption = btn_tmap.map as string
)
on rdo_tmapemit changed stat do
(
for obj in selection where classof obj == Object_Src do
(
if rdo_tmapemit.state == 1 then obj.vctemp = 0
if rdo_tmapemit.state == 2 then obj.vctemp = 1
if rdo_tmapemit.state == 3 then obj.vctemp = 2
if rdo_tmapemit.state == 4 then obj.vctemp = 3
if rdo_tmapemit.state == 5 then obj.vctemp = 4
)
)
on btn_updatetmap pressed do
(
for obj in selection where classof obj == Object_Src do
(
if rdo_tmapemit.state == 1 then obj.vctemp = 0
if rdo_tmapemit.state == 2 then obj.vctemp = 1
if rdo_tmapemit.state == 3 then obj.vctemp = 2
if rdo_tmapemit.state == 4 then obj.vctemp = 3
if rdo_tmapemit.state == 5 then obj.vctemp = 4
obj.tempmap = btn_tmap.map
btn_tmap.caption = btn_tmap.map as string
)
)
)
rollout srcturbparam "Turbulence" width:160 height:120
(
spinner spn_turbamount "Amount:" pos:[24,8] width:120 height:16 range:[0,1,0] scale:0.01
spinner spn_turbscale "Scale:" pos:[24,32] width:120 height:16 range:[0,100000,0] scale:0.1
spinner spn_turbframes "Frames:" pos:[24,56] width:120 height:16 range:[0,100000,0] scale:0.01
button btn_updateturbamounts "Update Turbulence" pos:[16,80] width:128 height:32
on srcturbparam open do
(
spn_turbamount.value = .5
spn_turbscale.value = 10
spn_turbframes.value = 3
)
on spn_turbamount changed val do
(
for obj in selection where classof obj == Object_Src do
obj.turbulence = spn_turbamount.value
)
on spn_turbscale changed val do
(
for obj in selection where classof obj == Object_Src do
obj.turbulencescale = spn_turbscale.value
)
on spn_turbframes changed val do
(
for obj in selection where classof obj == Object_Src do
obj.turbulenceframes = spn_turbframes.value
)
on btn_updateturbamounts pressed do
(
for obj in selection where classof obj == Object_Src do
obj.turbulence = spn_turbamount.value
obj.tubulencescale = spn_turbscale.value
obj.turbulenceframes = spn_turbframes.value
)
)
rollout srcvelparam "Velocity" width:160 height:184
(
spinner spn_objvel "Object's:" pos:[25,8] width:120 height:16 range:[0,100000,0] scale:0.1
spinner spn_extravel "Extra:" pos:[25,32] width:120 height:16 range:[0,100000,0] scale:0.1
mapButton btn_vmap "None" pos:[49,120] width:96 height:24
label lbl_vmap "Map:" pos:[17,120] width:24 height:24
radiobuttons rdo_vmapemit "Map Emission:" pos:[17,56] width:128 height:62 labels:#("Disabled", "Red", "Green", "Blue", "Intensity") default:5 columns:2
button btn_updatevmap "UpdateVel Map Info" pos:[17,152] width:128 height:24
on srcvelparam open do
(
spn_objvel.value = 1
spn_extravel.value = .1
)
on spn_objvel changed val do
(
for obj in selection where classof obj == Object_Src do
obj.Object_Velocity = spn_objvel.value
)
on spn_extravel changed val do
(
for obj in selection where classof obj == Object_Src do
obj.Extra_Velocity = spn_extravel.value
)
on btn_vmap picked mtl do
(
for obj in selection where classof obj == Object_Src do
obj.extravelmap = btn_vmap.map
btn_vmap.caption = btn_vmap.map as string
)
on rdo_vmapemit changed stat do
(
for obj in selection where classof obj == Object_Src do
(
if rdo_vmapemit.state == 1 then obj.vccol = 0
if rdo_vmapemit.state == 2 then obj.vccol = 1
if rdo_vmapemit.state == 3 then obj.vccol = 2
if rdo_vmapemit.state == 4 then obj.vccol = 3
if rdo_vmapemit.state == 5 then obj.vccol = 4
)
)
on btn_updatevmap pressed do
(
for obj in selection where classof obj == Object_Src do
(
if rdo_vmapemit.state == 1 then obj.vccol = 0
if rdo_vmapemit.state == 2 then obj.vccol = 1
if rdo_vmapemit.state == 3 then obj.vccol = 2
if rdo_vmapemit.state == 4 then obj.vccol = 3
if rdo_vmapemit.state == 5 then obj.vccol = 4
obj.extravelmap = btn_vmap.map
btn_vmap.caption = btn_vmap.map as string
)
)
)
sourcemgrfloater = newrolloutfloater "Source Manager" 170 600
addrollout objsrcdup sourcemgrfloater
addrollout srcparam sourcemgrfloater
addrollout srcfuelparam sourcemgrfloater
addrollout srctempparam sourcemgrfloater
addrollout srcsmokeparam sourcemgrfloater
addrollout srcvelparam sourcemgrfloater
addrollout srcturbparam sourcemgrfloater
Yeah, thanks! I'll try that out!
Solitude Wrote:If you're using the particle src, you're not really emitting from the geometry... you're emitting from a circle around the particle... so if it doesn't matter, then cool!
It's kinda neat and quick workaround for some scenes. In my case: perfect.
Best regards
emil_vfx
Hey, Solitude. The script seems to work pretty cool ;-) I had to fix some variables, since they didn't work and errors occured. But, hey, great job, the manager is very clearly arranged and useful! Thanks! And what I really dig is that the sources are parented to the objects! I had that on my wishlist secretly... 8)
Greets
emil_vfx
Thanks for sharing this script !
I suppose I might create a showcase forum where user would post only max files, scripts, for
easier navigation ?
Kresimir
Damn. I could've sworn I replied to this... I must've hit the wrong button.
Emil: What variables were giving you errors?! (So I can fix them)
Kresimir: That's a great idea. Cgfluids already has this already as well...
Have you been able to confirm the exception errors with addsource? There's also somebody on cgfluids saying he's got the same issues.
Solitude Wrote:Emil: What variables were giving you errors?! (So I can fix them)
Hi!
It was the Smoke_Density and Fuel. It was just a simple syntax error, after correcting it, everything worked fine (as far as I've checked the stuff...)
Greets
Emil
thanks! I pretty much copy and pasted if after set up the first one, figured I'd mess up the text somewhere!
|