Scripts under Reader can be done using LUA language (v5.1)
LUA 5.1 reference manual is available at http://www.lua.org/manual/5.1/manual.html
If you need some requests, don't hesitate ;)
User Interface
Don't forget to define the script directory in the Option screen.
To use script, open a DAT file and use the following ribbon
(https://www.sc4devotion.com/forums/proxy.php?request=http%3A%2F%2Fimg651.imageshack.us%2Fimg651%2F1967%2Freader6.jpg&hash=42b70014f4ae4b4a8972d38dd6474cbe28d62320) (http://img651.imageshack.us/i/reader6.jpg/)
the combo list is filled with all lua scripts found in the defined script directory
the first icon is to create a new script
the second icon is not use at the moment
the third icon is to edit the script selected in the combo
the two last icons is to save and save as the script
when you edit the script, a new tab is created.
(https://www.sc4devotion.com/forums/proxy.php?request=http%3A%2F%2Fimg204.imageshack.us%2Fimg204%2F3797%2Freader7.th.jpg&hash=9d3367272f02aa73fbeec18e7db61c8081792d8e) (http://img204.imageshack.us/i/reader7.jpg/)
the first icon is to save the script
the second icon is to compile the script (but the script is not executed)
the third icon is to run the script
the fourth icon is to stop the script
the top pane displays the code, the bottom pane displays output messages
Coding
Entry point for Reader is the reader.main function.
Each script has to begin with the following line "function reader.main (this)" and is ended with "end" word.
There is no function to save the DAT. You have to save the DAT manually after checking that all your modifications are ok.
example 1
function reader.main (this)
pos = reader:entries_GetHeadPosition()
while pos~=0 do
entry,pos = reader:entries_GetNext(pos)
flag = reader:entry_GetFlag(entry)
if (flag == 7) then
exemplar = reader:ex_Decode(entry)
dw1,dw2,dw3 = reader:ex_GetParentCohort(exemplar)
dw1= 0x0000001
dw2= 0x0000002
dw3= 0x0000003
reader:ex_SetParentCohort(exemplar,dw1,dw2,dw3)
proppos = reader:exprop_GetHeadPosition(exemplar)
while proppos~=0 do
exprop, proppos = reader:exprop_GetNext(exemplar,proppos)
desc,descname = reader:exprop_GetDesc(exprop)
if (desc == 0x27812837) then
reader:exprop_SetDesc(exprop,0x12345678)
io.write("descname :",descname)
end
end
reader:ex_Encode(entry,exemplar)
end
end
end
This example parse all entries of a Dat file.
If an entry is an exemplar, it changes the Parent Cohort.
If a property desc of this exemplar is 0x27812837, it changes this property to 0x12345678.
Once done, it encodes the data to save modifications.
example 2
function reader.main (this)
pos = reader:entries_GetHeadPosition()
while pos~=0 do
entry,pos = reader:entries_GetNext(pos)
flag = reader:entry_GetFlag(entry)
if (flag == 2) then
s3d = reader:s3d_Decode(entry)
count = reader:s3d_Count(s3d, 4)
io.write("count :",count )
block = reader:s3d_GetBlock(s3d, 4, 0)
pos = reader:s3dtext_GetHeadPosition(block)
while pos ~=0 do
s3dtext, pos = reader:s3dtext_GetNext(block,pos)
id, wrapModeS, wrapModeT,magFilter, minFilter,name = reader:s3dtext_GetInfo(s3dtext)
if (id==0x00030403) then
io.write("id:",name)
id = 0x00000001
name="test_lua"
reader:s3dtext_SetInfo(s3dtext, id, wrapModeS, wrapModeT,magFilter, minFilter,name)
end
end
reader:s3d_SetBlock(s3d, 4, 0, block)
reader:s3d_Encode(entry,s3d)
end
end
reader:refresh()
end
This example parse all entries of a Dat file.
If an entry is a S3D, it reads material block (4) then parses all textures.
If id of one of them is 0x00030403, it changes to 0x00000001 and changes its name.
Once done, it encodes the data to save modifications.
-----------------------------------------------------------------------------
List of functions
-----------------------------------------------------------------------------
Entries/Entry group
refresh()
Refresh the main list in the reader
count = entries_Count()
Get the number of elements in the entries list
pos = entries_GetHeadPosition()
Get the position of the head element of the entries list
entry, pos = entries_GetNext(pos)
Get the list element identified by pos, then sets pos to the POSITION value of the next entry in the list
T,G,I = entry_GetTGI(entry)
Get the Type/Group/Instance of an entry
entry_SetTGI(entry,T,G,I)
Set the Type/Group/Instance of an entry
Flag = entry_GetFlag(entry)
Get the flag of an entry (see Annex 1 for list of value)
Exemplar group
exemplar = ex_Decode(entry)
Decode the entry to fill the exemplar struct
ex_Encode(entry,exemplar)
Encode exemplar values and fill the entry
ex_Release(exemplar)
Release an exemplar (if modification has to be canceled)
TC,GC,IC = ex_GetParentCohort(exemplar)
Get the Type/Group/Instance of the Parent Cohort property
ex_SetParentCohort(exemplar,TC,GC,IC)
Set the Type/Group/Instance of the Parent Cohort property
pos = exprop_GetHeadPosition(exemplar)
Get the position of the head element of the properties list
exprop, pos = exprop_GetNext(exemplar,pos)
Get the list element identified by pos, then sets pos to the POSITION value of the next entry in the list
exprop = exprop_Add(exemplar)
Add a new property
exprop_Del(exemplar,pos)
Delete a property
desc,name = exprop_GetDesc(exprop)
Get description of the property (desc is the hexadecimal value, name is the string value)
exprop_SetDesc(exprop,desc)
Set description of the property
type = exprop_GetType(exprop)
Get type of the property
Type can be
PROP_UINT8 0x100
PROP_UINT32 0x300
PROP_SINT32 0x700
PROP_SINT64 0x800
PROP_FLOAT32 0x900
PROP_BOOL 0xB00
PROP_STR 0xC00
exprop_SetType(exprop,type)
Set type of the property
rep = exprop_GetRep(exprop)
Get Rep of a property
exprop_SetRep(exprop,rep)
Set Rep of a property
valuestr = exprop_GetValueStr(exprop)
Get the complete value of a property in a string
result = exprop_HasValueStr(exprop, value)
Return 1 if the property has the value, 0 otherelse
Value depends on the type of the property. If type is 0xC00, value has to be a string.
exprop_SetValue(exprop, value, [idx])
Set the value of a property.
Idx has to be filled it you want to change a value in an array
S3D Group
s3d = s3d_Decode(entry)
Decode the entry to fill the s3d struct
s3d_Encode(entry,s3d)
Encode s3d values and fill the entry
s3d_Release(s3d)
Release a s3d (if modification has to be canceled)
count = s3d_Count(s3d, block_id)
Get the number of element depending on block ID
Block ID can be :
1 : vertices
2 : indexes
3 : primitives
4 : material
5 : animation
block = s3d_GetBlock(s3d, block_id, index)
Get the data block adressed by index
s3d_SetBlock(s3d, block_id, index, block)
Set the data block
s3d_ReleaseBlock(block_id, block)
Release the data block (if modification has to be canceled)
block 4
flags, alphafunc, depthfunc,srcBlendFactor,dstBlendFactor,alphaThreshold = s3dmat_GetInfo(block)
Get information about material block
flags values :
0x0001 - enable alpha test
0x0002 - enable depth test
0x0008 - enable backface culling
0x0010 - enable framebuffer blending
0x0020 - enable texturing
0x0040 - enable depth writes (unused - currently set by code)
0x0080 - enable color writes (unused - currently forced on)
alpha func, depthfunc :
0 - never
1 - less than
2 - equal
3 - less than or equal
4 - greater
5 - not equal
6 - greater than or equal
7 - always
srcBlendFactor,dstBlendFactor
0 - zero
1 - one
2 - source color (destination factor only)
3 - one minus source color (destination factor only)
4 - source alpha
5 - one minus source alpha
8 - destination color (source factor only)
9 - one minus destination color (source factor only)
s3dmat_SetInfo(block,flags, alphafunc, depthfunc,srcBlendFactor, dstBlendFactor,alphaThreshold)
Set information about material block
pos = s3dtext_GetHeadPosition(block)
Get the position of the head element of the texture list
s3dtext, pos = s3dtext_GetNext(block,pos)
Get the list element identified by pos, then sets pos to the POSITION value of the next entry in the list
s3dtext = s3dtext_Add(block)
Add a new texture
s3dtext_Del(block,pos)
Delete a texture
id, wrapModeS, wrapModeT,magFilter, minFilter,name = s3dtext_GetInfo(s3dtext)
Get information about texture
wrapModeS,wrapModeT : Texture addressing mode for S (U)/ T (V) texture axis
2 - clamp
3 - repeat
magFilter : Texture magnification filter hint
0 - nearest
1 - bilinear
minFilter : Texture minification filter hint
0 - nearest, no mipmapping
1 - bilinear, no mipmapping
2 - nearest mipmap nearest
3 - linear mipmap nearest (bilinear with mipmapping)
4 - nearest mipmap linear
5 - linear mipmap linear (trilinear)
name : Null-terminated name of texture
s3dtext_SetInfo(s3dtext, id, wrapModeS, wrapModeT,magFilter, minFilter,name)
Set information about texture
block 1
pos = s3dvert_GetHeadPosition(block)
Get the position of the head element of the vertices list
s3dvert, pos = s3dvert_GetNext(block,pos)
Get the list element identified by pos, then sets pos to the POSITION value of the next entry in the list
s3dvert = s3dvert_Add(block)
Add a new vertex
s3dvert_Del(block,pos)
Delete a vertex
vertex_format = s3dvert_GetFormat(block)
Get the format of the vertex
s3dvert_SetFormat(block, vertex_format)
Set the format of the vertex
x,y,z = s3dvert_GetInfoPos(s3dvert)
Get the world position
s3dvert_SetInfoPos(s3dvert, x,y,z)
Set the world position
b,g,r,a = s3dvert_GetInfoColor(s3dvert)
Get the diffuse color
s3dvert_SetInfoColor(s3dvert, b,g,r,a)
Set the diffuse color
u0,v0,u1,v1 = s3dvert_GetInfoCoord(s3dvert)
Get the first/second texture coordinate
s3dvert_SetInfoCoord(s3dvert, u0,v0,u1,v1)
Set the first/second texture coordinate
block 3
pos = s3dprim_GetHeadPosition(block)
Get the position of the head element of the primitives list
s3dprim, pos = s3dprim_GetNext(block,pos)
Get the list element identified by pos, then sets pos to the POSITION value of the next entry in the list
s3dprim = s3dprim_Add(block)
Add a new primitive
s3dprim_Del(block,pos)
Delete a primitive
type, first, count = s3dprim_GetInfo(s3dprim)
Get information about primitive
type
0- triangles
1- triangle strip
2 - triangle fan
6 - quads
7 - quad strips
first : first vertex used by primitive
count : Number of vertices used by primitive
s3dprim_SetInfo(s3dprim, type, first, count)
Set information about primitive
block 2
pos = s3didx_GetHeadPosition(block)
Get the position of the head element of the indexes list
s3didx, pos = s3didx_GetNext(block,pos)
Get the list element identified by pos, then sets pos to the POSITION value of the next entry in the list
s3didx = s3didx_Add(block)
Add a new index
s3didx_Del(block,pos)
Delete an index
t1,t2,t3 = s3didx_GetInfo(block,s3didx)
Get information about index
s3didx_SetInfo(block, s3didx, t1, t2, t3)
Set information about index
block 5
frameCount,frameRate,animMode,displacement = s3danim_GetInfo(block)
Get information about anim
animMode
0 - ping pong
1 - one -shot
2 - loop
s3danim_SetInfo(block, frameCount,frameRate,animMode,displacement)
Set information about anim
pos = s3dmesh_GetHeadPosition(block)
Get the position of the head element of the meshes list
s3dmesh, pos = s3dmesh_GetNext(block,pos)
Get the list element identified by pos, then sets pos to the POSITION value of the next entry in the list
s3dmesh = s3dmesh_Add(block)
Add a new mesh
s3dmesh_Del(block,pos)
Delete a mesh
pos = s3dfrm_GetHeadPosition(s3dmesh)
Get the position of the head element of the frames list
s3dfrm, pos = s3dfrm_GetNext(s3dmesh,pos)
Get the list element identified by pos, then sets pos to the POSITION value of the next entry in the list
s3dfrm = s3dfrm_Add(block)
Add a new frame
s3dfrm_Del(block,pos)
Delete a frame
vertBlock,indexBlock,primBlock,materialBlock = s3dfrm_GetInfo(s3dfrm)
Get information about frame
s3dfrm_SetInfo(s3dfrm, vertBlock,indexBlock,primBlock,materialBlock)
Set information about frame
Annex 1.
List of flags
S3D 2
FLG_ANIM 3
FLG_BMP 4
Cohort 5
FLG_EACS 6
Exemplar 7
FLG_MCO 8
FLG_F1B 9
FLG_HIT 10
FLG_JFIF 11
FLG_LEV 12
FLG_NA 13
FLG_PNG 14
FLG_RUL 15
FLG_SC4PATH 17
FLG_FSH 18
FLG_TRK 19
FLG_UI 20
FLG_UNKNOWN 21
FLG_MAD 22
FLG_WAVE 23
FLG_XA 24
FLG_DBPF 25
FLG_LUA 26
FLG_HLS 27
FLG_TLO 28
FLG_LTEXT 29
FLG_DIR 30
FLG_U1 31
FLG_KEYCFG 32
FLG_PRE_BMP 33
FLG_PRE_XA 34
FLG_EFF_DIR 35
FLG_U2 36
FLG_LD 37
FLG_SAVE_TAXES 38
FLG_SAVE_MYSIM 39
FLG_SAVE_ADV 40
FLG_SAVE_ORD 41
FLG_SAVE_PNG 42
FLG_SAVE_WILD 43
FLG_SAVE_REQ 44
FLG_DELOC 45
FLG_INI 46
FLG_SAVE_BUY_POWER 47
FLG_SAVE_SELL_POWER 48
FLG_SAVE_BUY_WATER 49
FLG_SAVE_SELL_WATER 50
FLG_SAVE_EXT_GARB 51
FLG_SAVE_IMP_GARB 52
FLG_SAVE_ADV_FIN 53
FLG_SAVE_ADV_UT 54
FLG_SAVE_ADV_ALL 55
FLG_SAVE_ADV_SIM 56
FLG_AB 57
FLG_AE 58
FLG_XML 59
This is an excellent feature, if I had discovered the new version a few days ago I would saved hours with this, but I've got a bunch of other large projects in the works and this will save tons of time.
Merci pour ce logiciel extraordinaire :)
Hi all,
I am trying to make one tree controller to rule them all. &cry2
There are 256 reps of the FloraPreferences, so I have started with 256 exemplars. Each exemplar has it's own unique "1" in an otherwise 255 reps of 0 (Exemplar 1: 1,0,...0, Exemplar 2: 0,1,...,0 , Exemplar 256: 0,0,...,1). Following my flora range and a "2", each exemplar is sequenced in the 6th and 7th digits (0x33AA2000, 0x33AA20100,...,0x3AA2FF0). Flora is best in clusters, so my plan was to simply clone each exemplar 15 times and increase the Instance by 1 (To fill up the entire 0x2### range). This would make every exemplar in the cluster have a "1" in the same place in FloraPreferences. Very nice, it took about 45 minutes to set the Preferences up for the final cloning.
Testing it out today, this will not do. The last flora in a cluster appear with far too much strength. To combat this I made the values in the Preferences decrease by .5 for each next flora in the cluster (1, .95, .9,...,.25), and I am pleased. However, I estimate setting up these Preferences to take about 12 hours...
...Probably faster to learn LUA scripting. I have an idea for a pretty simple script, but I have no idea how to implement it. It would gather the value of each Rep and then subract a divisor and place it back in. I would then clone the file, change the divisor and repeat.
Is anyone familiar with scripting for Reader? All of these commands are pretty abstract to me. Example 1 looks in Ilive's post looks pretty close to my idea, particularly the 1st half.
Quotedw1,dw2,dw3 = reader:ex_GetParentCohort(exemplar)
dw1= 0x0000001
dw2= 0x0000002
dw3= 0x0000003
reader:ex_SetParentCohort(exemplar,dw1,dw2,dw3)
If I could change the ParentCohort to FloraPreferences and use dw1-dw256 and then use math on them, I would be totally happy.
Thanks
Edit: so close and yet so far. Thought I had it figured out, but Reader can only hold 195 variables... Guess I only need 16, so time for some looping...
Guess I only need 2 variables.
function reader.main (this)
A0= 0
A1= 1
pos = reader:entries_GetHeadPosition()
repeat
repeat
entry,pos = reader:entries_GetNext(pos)
exemplar = reader:ex_Decode(entry)
proppos = reader:exprop_GetHeadPosition(exemplar)
exprop, proppos = reader:exprop_GetNext(exemplar,proppos)
exprop, proppos = reader:exprop_GetNext(exemplar,proppos)
exprop, proppos = reader:exprop_GetNext(exemplar,proppos)
exprop, proppos = reader:exprop_GetNext(exemplar,proppos)
reader:exprop_SetValue(exprop, A1, A0)
reader:ex_Encode(entry,exemplar)
A1= A1-(1/16)
until (A1 == 0)
A1= 1
A0= A0+1
until (A0 == 256) end
This will make changing "Exemplar Name" and "Flora: Cluster Type" much faster too. Took near 7 hours, but at least I learned something and could drink soda at the same time. :)
There are a few things I had to wrap my head around, so this I will share. All functions must have "reader:" before them (for "rep = exprop_GetRep(exprop)" to work, one needs to write "rep = reader:exprop_GetRep(exprop)"). Also, in this case, "rep" (not "Rep") is a variable, and can be anything that doesn't start with a number and isn't a Lua command. This variable can also be used in other "Set" functions.
In the function "exprop_SetValue(exprop, value, [idx])": "value" is what you want to set the property to be, and "[idx]" is the Rep of the property.
The script I wrote starts with defining two variables "A0" and "A1". You can see later on that I have used these variables as the "value" and "rep" of the SetValue function. It then goes to the head of the .dat file, and then goes into a loop. It selects the next entry (which would be us clicking on the top entry) and decodes it. I couldn't figure out "go to property" so in this case, I have the script basically scrolling down until it gets to the 4th property (notice we are in "proppos" not "entry" functions) which is the FloraPreferences. It sets the value of the property, at this point setting the "0" rep to "1". The exemplar is recoded. 1/16 is then subtracted from A1 and set to be A1. Since A1 does not equal zero, it goes back to the repeat, selecting the next exemplar, scrolling down 4 properties, but now setting the FloraPref to have .9375 as the 0 rep. This continues until A1=0, at which point it resets A1 to 1, and adds 1 to A0 (so now we are on the "1" rep), and repeats the -1/16 process. This continues until A0=256, and we have reached the end of the 4096 exemplars. :)
(https://www.sc4devotion.com/forums/proxy.php?request=http%3A%2F%2Fimg856.imageshack.us%2Fimg856%2F7718%2Ffloapref.jpg&hash=3c1109d5062cd5167b1faf323e9205ddff2f5725)
Ilive's examples have functions like get(this), if this=that, then prevail. These are basically checks to make sure the correct property is selected. After the 4th "exprop, proppos = reader:exprop_GetNext(exemplar,proppos)" I could have written:
desc,name = exprop_GetDesc(exprop)
if (desc == 0x083DC847) then
-Set the values-
This code would have checked to make sure the 4th property was "0x083DC847" (which is the value for FloraPref) before setting the values of the reps. For me, I knew all of my exemplars where just clones of each other, and didn't need any checking. While learning this script, I used this code followed by the "io.write("descname :",descname)" (which prints the property name) function to make sure I was in the right place.
Thinking about potentials now, I imagine with some knowledge the verticies of a model could be measured to find the exact volume of a model. I also wonder about a cohort maker.
good work with this!
Thanks there Frex_Ceafus
Quote from: toja on September 21, 2011, 10:41:08 AMBut maybe we should continue our conversation in the Script in Reader-topic?
Sounds fine.
I've been editing U,V values with Excell, but it's kind of lame. ::) I moved on to trying to get a script to do it, but I'm having troubles.
I made a simple model, and here are the Vertex Values:
(https://www.sc4devotion.com/forums/proxy.php?request=http%3A%2F%2Fimg716.imageshack.us%2Fimg716%2F5377%2Fvertexl.jpg&hash=d015e904cfafa04e0d87b5907f40aa9fc60029cc)
For this post, I've copy/pasted a zoom 4 S3D into its own file (so the script is pretty light/specific)
function reader.main(this)
pos= reader:entries_GetHeadPosition()
entry,pos= reader:entries_GetNext(pos)
s3d = reader:s3d_Decode(entry)
block = reader:s3d_GetBlock(s3d, 1, 0)
s3dpos= reader:s3dvert_GetHeadPosition(block)
while s3dpos ~=0 do
s3dvert, s3dpos= reader:s3dvert_GetNext(block,s3dpos)
u0,v0,u1,v1 = reader:s3dvert_GetInfoCoord(s3dvert)
print (u0)
end
// Testing to see if it's just me...
u0,v0,u1,v1 = reader:s3dvert_GetInfoCoord(s3dvert)
print (u0)
s3dvert, s3dpos= reader:s3dvert_GetNext(block,s3dpos)
u0,v0,u1,v1 = reader:s3dvert_GetInfoCoord(s3dvert)
print (u0)
reader:s3d_Encode(entry,s3d)
end
Basically, we're just going through the Vertices and printing the values. I've also thrown the lines at the bottom in to check if I'm using the while loop wrong. The output is this:
0.46666669845581
0.53333336114883
0.26666665077209
0.13333332538605
0.73333334922791
0.86666667461395
// testing
0.86666667461395
nil
.
The first issue is that these are the V values. In fact, u0 is the only variable that comes up with anything. Second, I can't get the last vertex to print. I first re-get it and print to see if it's the while loop. Then manually get the next position with a print-back of "nil".
Any Ideas?
I've examined the file ReaderLua.cpp from the source code and I think I know what's happening here: The C-function s3dvert_GetInfoCoord() collects four values but than it returns only three of them to the LUA interpreter. And it seems as if it's not the only function with this behaviour. As far as I can see the following functions do return the wrong number of values:
b,g,r,a = s3dvert_GetInfoColor(s3dvert)
u0,v0,u1,v1 = s3dvert_GetInfoCoord(s3dvert)
frameCount,frameRate,animMode,displacement = s3danim_GetInfo(block)
vertBlock,indexBlock,primBlock,materialBlock = s3dfrm_GetInfo(s3dfrm)
There's nothing we can do here, we can only wait for a bugfixed version... Have you tried to set your new UV-coordinates without calling s3dvert_GetInfoCoord before? I don't see a reason why it shouldn't work.
I'm not really sure why it's not possible to access the last vertex in a group, but I think it's another bug in the function s3dvert_GetNext (), to be more precise: line #985 in ReaderLUA.cpp
The following code seems to be a workaround, at least I was able to get the x,y,z-values for the last vertex :)
function reader.main(this)
...
local counter = 0 ---- we're counting the while loops with this variable
while s3dpos ~= 0 do
counter = counter + 1
s3dvert, s3dpos = reader:s3dvert_GetNext(block,s3dpos)
local x, y, z = reader:s3dvert_GetInfoPos(s3dvert)
print (x, y, z)
-- now we're using the variable counter to get the last vertex
if (s3dpos == 0) then
local last_s3dvert = reader:s3dvert_GetNext(block, counter + 1)
x, y, z = reader:s3dvert_GetInfoPos(last_s3dvert)
print (x, y, z)
end
end
end
hmm, I've gone as far as copy/pasting this into my script, but Reader becomes unresponsive after I run it. Could it be I need something special for "local"?
Ah, there was an error in the code, my mistake, I'm sorry. I've declared the variables s3dvert and s3dpos as local inside the while-loop which makes it run forever. I've updated the code above, it should be correct now.
Works like a charm. :thumbsup:
Gets the 7th vert value too, but still missing the real u0.
Well, I'm a begginer on modding, so sorry for my ignorance. What's this script for? What's its function?
@Lowkee33: I'm glad to hear that it works now, although I can't help with the u0 value. It would be really easy to fix the bug, but I don't have the possibility to recompile the source code.
@Lior: It's only a code snippet, that allows you to read the coordinates of an S3D model and print them to the console window. It becomes useful when you want to change the coordinates of all S3D models in a file with only one click via LUA
@Lior: Passed what Toga said, it's hard for me to explain without writing a manuscript.
Suffice to say, that first image I posted (Link (http://img716.imageshack.us/img716/5377/vertexl.jpg)), is the part of the model that defines the way the S3D and FSH files interact. The S3D is a series of points creating triangles (the LOD), and the FSH is an image that is laid over the LOD. The X,Y,Z, values are the position of the point (meters) in a 3D grid, and the U,V values are the position of the point on the FSH image (%).
Normally there are 20 FSH for a model, but I've been trying to make mine only have one. This means that the U,V values need to be scaled down for the lesser zooms (they may have been a %80 of a 16x16 image, but only %20 for a 64x64 pixel FSH).
So, like I said, this can be done in Excell, but much less chance of error with a script. First step is to get and print the right values. After that there is some math to do, and then the final set value. Looks like I'm not going to get passed that first step though.
Anyone know how to get the previous property position?
I'm trying to automate deleting properties, the relevant section is:
while proppos~=0 do
exprop, proppos = reader:exprop_GetNext(exemplar,proppos)
desc,descname = reader:exprop_GetDesc(exprop)
if (desc == 0x27812820) then
io.write("found at pos :",proppos)
reader:exprop_Del(exemplar,proppos)
end
end
This deletes the property that comes AFTER the given property. And I can't simply subtract 1, since the proppos is 121890252 and the item before it is 121890188 (and the one before that was 121891484, yes higher). This only seems to apply to delete... if I change anything it's applied to the correct item.
Has anyone been working with the script feature and can offer any insight?
I think everyone who uses the script feature should post their scripts here, so everyone can learn better.
Right now I'm using a script that helps automate things I have to do on the huge number of lots in my projects.
What it does is identifies the exemplars in a file, checks to make sure it isn't the LotConfigurations exemplar (which has a parent cohort of 0,0,0), then sets the parent cohort, sets the lot name (so its not PZ_grass2358973057), and adds an ItemOrder property. I'm still trying to figure out how to get it to delete properties correctly.
function reader.main (this)
pos = reader:entries_GetHeadPosition()
while pos~=0 do
entry,pos = reader:entries_GetNext(pos)
flag = reader:entry_GetFlag(entry)
if (flag == 7) then
crex= 0
exemplar = reader:ex_Decode(entry)
dw1,dw2,dw3 = reader:ex_GetParentCohort(exemplar)
if (dw1==0) then
crex= 1
end
if (crex ~= 1) then
dw1= 0x05342861
dw2= 0xB6A644F7
dw3= 0xA584310F
reader:ex_SetParentCohort(exemplar,dw1,dw2,dw3)
proppos = reader:exprop_GetHeadPosition(exemplar)
while proppos~=0 do
exprop, proppos = reader:exprop_GetNext(exemplar,proppos)
desc,descname = reader:exprop_GetDesc(exprop)
if (desc == 0x00000020) then
io.write("found namedesc")
reader:exprop_SetValue(exprop,"MHTRM_Lot")
end
end
exprop = reader:exprop_Add(exemplar)
reader:exprop_SetType(exprop,0x300)
reader:exprop_SetDesc(exprop,0x8A2602B9)
reader:exprop_SetValue(exprop,0x00000000)
reader:exprop_SetRep(exprop,1)
end
reader:ex_Encode(entry,exemplar)
end
end
end
I have once tried to get the script feature working for me (and I could well have used it FREQUENTLY), but I could not get it to run properly, at all. Either the reader constantly crashed or the script did not show any effect, although I am pretty sure the script was correct. This was rather demotivating and I have stuck to 0.93 since. &mmm
Edit: As for your problem with deleting properties, maybe you could do a workaround and simply save the previous position into a variable in order to reference it for the deletion.
QuoteAs for your problem with deleting properties, maybe you could do a workaround and simply save the previous position into a variable in order to reference it for the deletion.
or in lua:
while proppos~=0 do
previous_proppos = proppos
exprop, proppos = reader:exprop_GetNext(exemplar,proppos)
desc,descname = reader:exprop_GetDesc(exprop)
if (desc == 0x27812820) then
io.write("found at pos :", previous_proppos)
reader:exprop_Del(exemplar, previous_proppos)
end
end
Quote from: memo on January 28, 2013, 02:47:45 PM
Either the reader constantly crashed or the script did not show any effect, although I am pretty sure the script was correct.
Did your script generate any output the console? The reader crashes, when you print more than just a few lines to the console.
The deal with the console output is that there's an off-by-one error that will cause a buffer overflow if you write more than 255 characters within about a tenth of a second.
Also, exprop_SetRep and exprop_SetValue are mostly broken; you can only set string values and elements of existing arrays.
How do i enable multiple flags? i mean, in LUA 5.1 there is no bitwise operator so im kinda screwed here..
I need all of them
0x0001 - enable alpha test
0x0002 - enable depth test
0x0008 - enable backface culling
0x0010 - enable framebuffer blending
0x0020 - enable texture
Edit: I fixed it by installing luaforwindows and use the bit.dll package in my script (btw nice snippet for everyone who wants to make their props transparent 'fast':
------------------------------------------------------------------------------------
-- S3D TRANSPARENCY.LUA - By Nique de Graaff --
-- You MUST install luaforwindows in the default installation folder for --
-- this to work! Then run this in the ILives Reader on your sc4model --
------------------------------------------------------------------------------------
-- This script will: --
-- Enable framebuffer blending --
-- Set Alpha Func to "Always" --
-- Set Src Blend to "Source alpha" --
-- Set Dest Blend to "one minus source alpha" --
------------------------------------------------------------------------------------
dir = "C:/Program Files (x86)/Lua/5.1/clibs/"
package.cpath = dir.."?.dll"
require("bit")
function reader.main (this)
pos = reader:entries_GetHeadPosition()
while pos ~= 0 do
entry,pos = reader:entries_GetNext(pos)
flag = reader:entry_GetFlag(entry)
if (flag == 2) then
s3d = reader:s3d_Decode(entry)
count = reader:s3d_Count(s3d, 4)-1
for i=0,count do
block = reader:s3d_GetBlock(s3d, 4, i)
s3dpos = reader:s3dtext_GetHeadPosition(block)
while s3dpos ~= 0 do
s3dtext, s3dpos = reader:s3dtext_GetNext(block,s3dpos)
flags, alphafunc, depthfunc,srcBlendFactor,dstBlendFactor,alphaThreshold = reader:s3dmat_GetInfo(block)
flags = bit.bor(flags, 0x0010)
alphafunc = 7
srcBlendFactor = 4
dstBlendFactor = 5
reader:s3dmat_SetInfo(block, flags, alphafunc, depthfunc,srcBlendFactor, dstBlendFactor,alphaThreshold)
end
reader:s3d_SetBlock(s3d, 4, i, block)
end
reader:s3d_Encode(entry,s3d)
end
end
io.write("\nDone!")
reader:refresh()
end
I am trying to write a script that changes S3D values in the Mats tab (wrapModeS, wrapModeT, magFilter & minFilter) and can't seem to quite understand LUA in iLives. I have used a little tad bit of LUA before but it seems not enough. This is what I have so far;
function reader.main (this)
id, wrapModeS, wrapModeT,magFilter, minFilter,name = reader:s3dtext_GetInfo(s3dtext)
if (wrapModeS== 3) then
io.write("2", wrapModeS)
id = 2
name="script"
reader:s3dtext_SetInfo(s3dtext, id, wrapModeS, wrapModeT,magFilter, minFilter,name)
end
end
reader:s3d_SetBlock(s3d, 4, 0, block)
reader:s3d_Encode(entry,s3d)
end
end
I tried to reuse some code form the original post as well.
Maybe someone has already done a similar script?
Thanks
-Billy
Durfsurn, lol i just posted something similar, take a look at my code (above) ( or click http://codetidy.com/4934/ )
Look at lines 39~45:
flags, alphafunc, depthfunc,srcBlendFactor,dstBlendFactor,alphaThreshold = reader:s3dmat_GetInfo(block)
-- (change settings here) --
reader:s3dmat_SetInfo(block, flags, alphafunc, depthfunc,srcBlendFactor, dstBlendFactor,alphaThreshold)
Change it to something like this
id, wrapModeS, wrapModeT,magFilter, minFilter,name = reader:s3dtext_GetInfo(s3dtext)
-- (change settings here) --
reader:s3dtext_SetInfo(s3dtext, id, wrapModeS, wrapModeT,magFilter, minFilter,name)
Cheers Nique, that really helped :).
I suppose I should share it all here with you.
This script changes the following settings for all S3D's in the dat (so also Preview Models);
- wrapModeS = Clamb
- wrapMode T = Clamb
- magFilter = Bilinear
- minFilter = Bilinear, no mipmapping
This is useful for changing lots of S3D's at once to PP specs so they don't look fuzzy :)
function reader.main (this)
pos = reader:entries_GetHeadPosition()
while pos ~= 0 do
entry,pos = reader:entries_GetNext(pos)
flag = reader:entry_GetFlag(entry)
if (flag == 2) then
s3d = reader:s3d_Decode(entry)
count = reader:s3d_Count(s3d, 4)-1
for i=0,count do
block = reader:s3d_GetBlock(s3d, 4, i)
s3dpos = reader:s3dtext_GetHeadPosition(block)
while s3dpos ~= 0 do
s3dtext, s3dpos = reader:s3dtext_GetNext(block,s3dpos)
id, wrapModeS, wrapModeT,magFilter, minFilter,name = reader:s3dtext_GetInfo(s3dtext)
wrapModeS = 2
wrapModeT = 2
magFilter = 1
minFilter = 1
reader:s3dtext_SetInfo(s3dtext, id, wrapModeS, wrapModeT,magFilter, minFilter,name)
end
reader:s3d_SetBlock(s3d, 4, i, block)
end
reader:s3d_Encode(entry,s3d)
end
end
io.write("\nFinished.")
reader:refresh()
end
-Billy