HeroEngine Forums
Welcome, Guest. Please login or Register for HeroCloud Account.

Author Topic: Clothes changer and coloring  (Read 2617 times)

Thazager

  • General Accounts
  • *
  • Posts: 1155
  • Never stop learning
    • View Profile
    • Heroes and Villains MMORPG
Clothes changer and coloring
« on: Feb 08, 13, 12:38:41 AM »

Moderate level scripting

This will demonstrate changing clothes on the base human female character.  It will also change the first color set on the item selected, based on 3 slider colors.  I have added a few examples of a database and how to access them. A database can save lots of hard coding.

__________________________________________________________________
From the basic window tutorial
Make basic window here. This is a base window and will be used in many of my Tutorials. It uses the GUI pics from textures that all engines have. This can be skipped if you have the basic window already from another tutorial.

Make basic button here. This will also be used in many of my tutorials.

_________________________________________________________________________
In the DOM,  create a 3 new (client side) fields.
1st name = tmp_Bankname
variable type = string
2nd name = tmp_Layername
variable type = string
3rd name = tmp_Piecename
variable type = string

__________________________________________________________________
In the DOM, create a new (client side) class.
name = TMP_Clothes
archtype = guicontrol
add a parent to the class, TMP_Window

add all 3 fields to class - tmp_Bankname, tmp_Layername, tmp_Piecename

click open script

In new (client side) script TMP_Clothes

Code: [Select]
// create clothes window
shared function Start()
  var win = getClothesClass()
  if win <> None
    DestroyNode( win )
  .
  win = CreateNodeFromPrototype("TMP_Clothes")
  win.build = true
  MiscUtils:centerWindow(win)
.

// build the drop down box, fill with item names
method onControlBuild()
  data as String = getItemList()    // list of items
  dataList as List of String
  SplitBy(data,"/",dataList)        // mop/wavy/braided bangs/ ...

  var box = me.getDropDownBox()
  if box <> None
    items as List of String
    loop i from 1 to 9
      add back dataList[i] to items       // make the list
    .

    foreach i in items
      box.E_dropDownBox_addDropDownBoxItem(i)   // add it to the drop down box
    .
  .
.

// list of items to change
function getItemList() as String
  data as String = "Mop/Wavy/Braided Bangs/"      // hair types
  data += "no shirt/Ranger Shirt/Wizard Shirt/"   // upper body types
  data += "no Pants/Ranger Pants/Wizard Robes"    // lower body types
  return data
.

// data table for easier reading
// lines up with list in getItemList()
// 1- setpart value
// 2- args.value
// 3- text: color
// 4- layer name
// 5- piece name
// 6- bank name
//
// these are pulled from the hotspot GUI, which gives the names
function getPartData(which as Integer) as String
  dataList as List of String
  // hair types
  add back "hair/Mop/hair Mop/hair base/Human Hair/hair\hair" to dataList
  add back "hair/Wavy/hair Wavy/hair base/Human Hair/hair\hair" to dataList
  add back "hair/Braided Bangs/hair Braided Bangs/hair base/Human Hair/hair\hair" to dataList

  // upper body types
  add back "Upper Body/Bare/Bare/female undergarments/Default/female_base_body\female_base_body" to dataList
  add back "Upper Body/Human Ranger Shirt/Ranger Shirt/shirt base/default/" \
   + "human_female_ranger_upper_body_shirt\human_female_ranger_upper_body_shirt" to dataList
  add back "Upper Body/Human Wizard Shirt/Wizard Shirt/female wizard shirt base/Default/" \
   + "human_female_wizard_upper_body_shirt\human_female_wizard_upper_body_shirt" to dataList

  // lower body types
  add back "Lower Body/Bare/Bare/female undergarments/Default/female_base_body\female_base_body" to dataList
  add back "Lower Body/Human Ranger Pants/Ranger Pants/ranger pants base/Default/" \
   + "human_ranger_lower_body_pants\human_ranger_lower_body_pants" to dataList
  add back "Lower Body/Human Wizard Robes/Wizard Robes/female wizard robes base/Default/" \
   + "human_female_wizard_lower_body_robes\human_female_wizard_lower_body_robes" to dataList

  data as String = dataList[which]
  return data
.

// check for user choice
method _onDropDownBoxValueChange(args references Class GUIValueFieldChangeEvent)
  item as String = getItemList()    // list of items
  itemList as List of String
  SplitBy(item,"/",itemList)        // mop/wavy/braided bangs/ ...

  loop i from 1 to 9
    if itemList[i] = args.value
      me.setNewClothes(i)
      break
    .
  .
.

// add clothes from data List to parts needing them
method setNewClothes(which as Integer)

  dataList as List of String
  data as String = getPartData(which) // get current data set
  SplitBy(data,"/",dataList)          // setpart/args.value/text color/layer name/piece name/bank name

  var pc = GetPlayerCharacterNode()
  SetPart(pc, dataList[1], dataList[2])

  var part = me.getPart()
  part.text = dataList[3]

  var win = getClothesClass()
  win.tmp_Layername = dataList[4]
  win.tmp_Piecename = dataList[5]
  win.tmp_Bankname = "character\dynamic_2\texturebanks\" + dataList[6]

  me.setSliderPos()
.

// set sliders to current positions
method setSliderPos()
  var color = me.GetPieceColor()
  thumb as NodeRef of Class GUISlider

  thumb = FindGUIControlByName(me, "RedSlider.thumb")
  thumb.pos = color.x * 20 - 10
  thumb = FindGUIControlByName(me, "GreenSlider.thumb")
  thumb.pos = color.y * 20 - 10
  thumb = FindGUIControlByName(me, "BlueSlider.thumb")
  thumb.pos = color.z * 20 - 10
.

// check for color changes
method _onSliderValueChange(args references Class GUIValueChangeEvent)
  slide as NodeRef of Class GUISlider = args.source
  colorVal as Float = ((stof(args.value) + 10) / 20)   // calc 0.0 - 1.0 values
  var pc = GetPlayerCharacterNode()

  // get current colors
  var color = me.GetPieceColor()
  Red as Float = color.x
  Green as Float = color.y
  Blue as Float = color.z

  when slide.parent.name
    is "RedSlider"
      Red = colorVal
    .
    is "GreenSlider"
      Green = colorVal
    .
    is "BlueSlider"
      Blue = colorVal
    .
  .

  // put in new color
  var square = me.getSquare()
  square.defaultStatePresentation.color = MiscUtils:MakeRGBA( Red, Green, Blue, 1.0 )
  SetTexturePieceColorDirectly(pc, me.tmp_Bankname, me.tmp_Layername, me.tmp_Piecename, 1, ( Red, Green, Blue ))
.

// get color for piece based on which piece
method GetPieceColor() as Vector3
  var pc = GetPlayerCharacterNode()

  // the 1 can be changed to 2, or for those with more than 2 colors - 3 or 4
  return GetCurrentColorForPiece(pc, me.tmp_Bankname, me.tmp_Layername, me.tmp_Piecename, 1)
.

//=================================================================================================
// get clothes class
public function getClothesClass() as NodeRef of Class TMP_Clothes
  return FindGUIControlByName(None, "game.TMP_Clothes")
.

// pointers
method getSquare() as NodeRef of Class GUIControl
  return FindGUIControlByName(me, "realColor")
.

method getPart() as NodeRef of Class GUILabel
  return FindGUIControlByName(me, "choice")
.

method getDropDownBox() as NodeRef of Class E_dropDownBox
  return FindGUIControlByName(me, "myChoice")
.

___________________________________________________________
In new (XML) script TMP_Clothes

Code: [Select]
<createControlType inheritFrom='TMP_Window' class='TMP_Clothes' type='TMP_Clothes' description='clothes changer' treePath='CleanEngine' name="TMP_Clothes" tmp_Bankname="" tmp_Piecename="" tmp_Layername="">
  <position x="300" y="300"/>
  <size x="200" y="200"/>
  <defaultStatePresentation>
    <color r="0" g="0" b="0" a="0"/>
  </defaultStatePresentation>
  <set name="TMP_Clothes.BGpanel">
    <size x="192" y="192"/>
  </set>
  <_label name="title" text="Clothes" displayfont="JUMBO" dropShadowAlpha="1" justification="CENTER">
    <position x="50" y="5"/>
    <defaultStatePresentation>
      <color r="1" g="0" b="0"/>
    </defaultStatePresentation>
    <autoCenter horizontal="true"/>
  </_label>
  <E_dropDownBox name="myChoice">
    <position x="10" y="70"/>
    <set name='TMP_Clothes.myChoice.E_dropDownList' attribute='layer' value="game"/>
    <set name='TMP_Clothes.myChoice.E_dropDownList.clientarea' attribute='layer' value="game"/>
  </E_dropDownBox>
  <_panel name="realColor">
    <position x="160" y="10"/>
    <size x="20" y="20"/>
  </_panel>
  <_label name="choice" text="name" dropShadowAlpha="1" justification="CENTER">
    <position x="50" y="40"/>
    <size x="180" y="20"/>
    <defaultStatePresentation>
      <color r="1" g="0" b="0"/>
    </defaultStatePresentation>
    <autoCenter horizontal="true"/>
  </_label>
  <_slider name="RedSlider">
    <position x="10" y="110"/>
    <hoverStatePresentation>
      <color r="0" g="0" b="0" a="0"/>
    </hoverStatePresentation>
    <set name="TMP_Clothes.RedSlider.sliderTracks">
      <defaultStatePresentation>
        <color g="0" b="0"/>
      </defaultStatePresentation>
    </set>
    <set name="TMP_Clothes.RedSlider.thumb">
      <position x="83"/>
      <defaultStatePresentation>
        <color g="0" b="0"/>
      </defaultStatePresentation>
      <hoverStatePresentation>
        <color g="0" b="0"/>
      </hoverStatePresentation>
    </set>
  </_slider>
  <_slider name="GreenSlider">
    <position x="10" y="140"/>
    <hoverStatePresentation>
      <color r="0" g="0" b="0" a="0"/>
    </hoverStatePresentation>
    <set name="TMP_Clothes.GreenSlider.sliderTracks">
      <defaultStatePresentation>
        <color r="0" b="0"/>
      </defaultStatePresentation>
    </set>
    <set name="TMP_Clothes.GreenSlider.thumb">
      <position x="83"/>
      <defaultStatePresentation>
        <color r="0" b="0"/>
      </defaultStatePresentation>
      <hoverStatePresentation>
        <color r="0" b="0"/>
      </hoverStatePresentation>
    </set>
  </_slider>
  <_slider name="BlueSlider">
    <position x="10" y="170"/>
    <hoverStatePresentation>
      <color r="0" g="0" b="0" a="0"/>
    </hoverStatePresentation>
    <set name="TMP_Clothes.BlueSlider.sliderTracks">
      <defaultStatePresentation>
        <color r="0" g="0"/>
      </defaultStatePresentation>
    </set>
    <set name="TMP_Clothes.BlueSlider.thumb">
      <position x="83"/>
      <defaultStatePresentation>
        <color r="0" g="0"/>
      </defaultStatePresentation>
      <hoverStatePresentation>
        <color r="0" g="0"/>
      </hoverStatePresentation>
    </set>
  </_slider>
</createControlType>

___________________________________________________________
In (client side) script E_PlayerAccountClassMethods under the chatwindow

Code: [Select]
        TMP_ClothesClassMethods:Start()
« Last Edit: Jun 01, 15, 11:32:33 PM by Thazager »
Logged

Viper155

  • World Owners
  • ****
  • Posts: 73
    • View Profile
Re: Clothes changer and coloring
« Reply #1 on: Feb 08, 13, 01:41:41 AM »

I havnt tried this yet but I wanted to thank you anyway, these tutorials are of great help to me.

Appreciate it!
Logged

Thazager

  • General Accounts
  • *
  • Posts: 1155
  • Never stop learning
    • View Profile
    • Heroes and Villains MMORPG
Re: Clothes changer and coloring
« Reply #2 on: Aug 27, 14, 09:34:17 PM »

Updated tutorial with new structure and added a few databases and how to access them.
Logged

keeperofstars

  • General Accounts
  • *
  • Posts: 998
    • View Profile
    • StarKeeper Online
Re: Clothes changer and coloring
« Reply #3 on: Aug 27, 14, 10:48:00 PM »

I appreciate the tutorial as it's always great to learn, but I just wondering why not use the parts system? It's much cleaner, allows for subparts, and you can build keywords to make UI interfacing much easier. Also can build out rules for parts, so you can prevent parts from showing when they shouldn't etc.

Also can use get and set functions for your body parts, and the parts system knows how to better group the model parts as to allow for bulk processing of the model in as few draw calls. Also allows you separate the mesh files from internal scripts so you don't have to go back and rewrite script when an artist makes a change to a model piece or a new one is added.
Logged
[img]http://screencast.com/t/x7btcSSyp3h0[\img]

Thazager

  • General Accounts
  • *
  • Posts: 1155
  • Never stop learning
    • View Profile
    • Heroes and Villains MMORPG
Re: Clothes changer and coloring
« Reply #4 on: Aug 27, 14, 11:09:14 PM »

I will wait for the tutorial on that to use it  ;)
Logged

keeperofstars

  • General Accounts
  • *
  • Posts: 998
    • View Profile
    • StarKeeper Online
Re: Clothes changer and coloring
« Reply #5 on: Aug 28, 14, 09:36:51 PM »

they have one called the wiki. :) explains it pretty straight forward. :)
with code examples and all.
Logged
[img]http://screencast.com/t/x7btcSSyp3h0[\img]

Thazager

  • General Accounts
  • *
  • Posts: 1155
  • Never stop learning
    • View Profile
    • Heroes and Villains MMORPG
Re: Clothes changer and coloring
« Reply #6 on: Aug 28, 14, 09:56:06 PM »

.
« Last Edit: Nov 10, 14, 08:41:49 PM by Thazager »
Logged

keeperofstars

  • General Accounts
  • *
  • Posts: 998
    • View Profile
    • StarKeeper Online
Re: Clothes changer and coloring
« Reply #7 on: Aug 29, 14, 09:34:02 PM »

might want to setup the keywords though, so your not having to manually build the part pieces out in strings.
You have way to much string parsing going on.

If you setup the keywords can grab the list of parts, then reference the keywords for your GUI elements. That way your not building long lists of manual strings that will become unmanageable. As you build out a parts system that has over hundreds of parts to it.

Also should be relying on the built in character functions to grab the parts and pieces.

http://hewiki.heroengine.com/wiki/Technical:Character_Functions

So for example:  GetAllPartsForSlot(charNode as noderef, slotName as string, parts as List of String)

that will return the list of all parts for a slot such as Head. as a list.
That way your code isn't hardcoded to 1 character in the game, but will work for any character or NPC.

 GetDivisions(charNode as noderef, divisionNames as List of String)

for getting the main divisions or slots.
etc.

They build a whole list of ways to get and set each part, that auto returns the appropriate list without having to build it yourself manually in code. Any time you code a manual string you break your code's ability to be flexible or reuseable. And since there is a great set of functions already built to do what you need, should probably use them. Will save you a ton of time, be much less bug prone, and will be flexible as you go to using this for setting and getting apperances of npcs, which is something you will need to build, as you will need the ability to build / create npc's via the spec system, or some system that can auto figure out parts. Cause you as a coder shouldn't care what your artists are doing, as long as they are building the parts to match a schema.
AKA all things have head slot.

Keywords are great for GUI elements, cause you can get all the parts then use the keywords to do things like grouping by, etc. Beyond what the part is.

So you can say, head slot keyword=Metal_helm.
Then in the gui you could sort by head types, such as metal_helm

If you do some planning with your keywords you can build great systems easily.
Logged
[img]http://screencast.com/t/x7btcSSyp3h0[\img]