--*********************************************************** --** THE INDIE STONE ** --** Author: turbotutone ** --*********************************************************** require "ISUI/ISPanel" local setup_table = { [0] = { filename = "left-hand" }, [1] = { filename = "right-hand"}, [2] = { filename = "lower-left-arm"}, [3] = { filename = "lower-right-arm"}, [4] = { filename = "upper-left-arm"}, [5] = { filename = "upper-right-arm"}, [6] = { filename = "chest", z = 30 }, [7] = { filename = "abdomen", z = 50 }, [8] = { filename = "head"}, [9] = { filename = "neck"}, [10] = { filename = "groin", z = 100 }, [11] = { filename = "left-thigh"}, [12] = { filename = "right-thigh"}, [13] = { filename = "left-calf"}, [14] = { filename = "right-calf"}, [15] = { filename = "left-foot"}, [16] = { filename = "right-foot"}, } ISBodyPartPanel = ISPanelJoypad:derive("ISBodyPartPanel"); function ISBodyPartPanel:initialise() ISPanelJoypad.initialise(self); local sex = self.bFemale and "female" or "male"; local bodyDamage = self.player:getBodyDamage(); self.cacheColor = Color.new( 1.0, 1.0, 1.0, 1.0 ); self.bps = {}; self.selectedBp = false; for i=0,16 do local type = BodyPartType.FromIndex(i); local tex = getTexture("media/ui/BodyParts/bps_"..sex.."_"..setup_table[i].filename); if not tex then --print("missing: "..tostring(setup_table[i].filename)); else --print("filename: "..tostring(setup_table[i].filename)); --print("tex offsetX "..tostring(tex:getOffsetX())); --print("tex offsetY "..tostring(tex:getOffsetY())); --print("tex width "..tostring(tex:getWidth())); --print("tex height "..tostring(tex:getHeight())); --print("tex orig width "..tostring(tex:getWidthOrig())); --print("tex orig height "..tostring(tex:getHeightOrig())); --print("bodypart "..tostring(type)); end local bp = { texture = getTexture("media/ui/BodyParts/bps_"..sex.."_"..setup_table[i].filename); bodyPartType = type; bodyPart = bodyDamage:getBodyPart(type); value = self.minValue + (self.maxValue/2), selected = false, color = Color.new(1,1,1,1), alpha = 1.0, offsetX = tex:getOffsetX(), offsetY = tex:getOffsetY(), width = tex:getWidth(), height = tex:getHeight(), centerX = tex:getOffsetX() + (tex:getWidth()/2), centerY = tex:getOffsetY() + (tex:getHeight()/2), nodeTexture = nil, z = setup_table[i].z or 0, enabled = true, nodeOffsetX = 0, nodeOffsetY = 0, }; if self.bFemale then if i==4 then bp.nodeOffsetX = 4; bp.nodeOffsetY = 0; end if i==5 then bp.nodeOffsetX = -4; bp.nodeOffsetY = 0; end if i==11 then bp.nodeOffsetX = -2; bp.nodeOffsetY = 10; end if i==12 then bp.nodeOffsetX = 2; bp.nodeOffsetY = 10; end if i==15 then bp.nodeOffsetX = -2; bp.nodeOffsetY = 0; end if i==16 then bp.nodeOffsetX = 2; bp.nodeOffsetY = 0; end else if i==4 then bp.nodeOffsetX = 10; bp.nodeOffsetY = 0; end if i==5 then bp.nodeOffsetX = -10; bp.nodeOffsetY = 0; end if i==11 then bp.nodeOffsetX = -2; bp.nodeOffsetY = 10; end if i==12 then bp.nodeOffsetX = 2; bp.nodeOffsetY = 10; end if i==15 then bp.nodeOffsetX = -2; bp.nodeOffsetY = 0; end if i==16 then bp.nodeOffsetX = 2; bp.nodeOffsetY = 0; end end table.insert(self.bps, bp); end end function ISBodyPartPanel:createChildren() ISPanelJoypad.createChildren(self) --instanceItem("item"); end function ISBodyPartPanel:prerender() ISPanelJoypad.prerender(self); end function ISBodyPartPanel:render() ISPanelJoypad.render(self); self:drawTexture(self.baseTexture, 0, 0, self.backgroundAlpha); local bp; for i=1, #self.bps do bp = self.bps[i]; if (not self.selectedBp) then self:drawTexture(bp.texture, 0, 0, self.defaultAlpha, bp.color:getRedFloat(), bp.color:getGreenFloat(), bp.color:getBlueFloat()); else if bp == self.selectedBp then self:drawTexture(bp.texture, 0, 0, self.selectedAlpha, bp.color:getRedFloat(), bp.color:getGreenFloat(), bp.color:getBlueFloat()); else self:drawTexture(bp.texture, 0, 0, self.deselectedAlpha, bp.color:getRedFloat(), bp.color:getGreenFloat(), bp.color:getBlueFloat()); end end end self:drawTexture(self.outlineTex, 0, 0, 1.0); --self:drawRectBorder( x, y, w, h, a, r, g, b) for i=1, #self.bps do bp = self.bps[i]; if self.drawDebugLines and self.bps[i].texture then local tex = self.bps[i].texture; self:drawRectBorder( tex:getOffsetX(), tex:getOffsetY(), tex:getWidth(), tex:getHeight(), 1, 0, 0, 1); end if bp == self.selectedBp and self.selectlines.enabled then self:drawLineLeft(bp.centerX+bp.nodeOffsetX, bp.centerY+bp.nodeOffsetY); if self.drawSelectedHitbox then self:drawRectBorder( bp.offsetX-1, bp.offsetY-1, bp.width+2, bp.height+2, 1, 0, 0, 0); self:drawRectBorder( bp.offsetX-2, bp.offsetY-2, bp.width+4, bp.height+4, 1, 1, 1, 1); self:drawRectBorder( bp.offsetX-3, bp.offsetY-3, bp.width+6, bp.height+6, 1, 0, 0, 0); end end if self.nodes.enabled and ((not self.nodes.onlySelected) or bp == self.selectedBp ) then local bp_n, bp_no = bp.nodeTex or self.nodes.nodeTex, bp.nodeOutlineTex or self.nodes.nodeOutlineTex; if bp_n and bp_no then self:drawTexture(bp_n, bp.centerX-(bp_n:getWidthOrig()/2)+bp.nodeOffsetX, bp.centerY-(bp_n:getHeightOrig()/2)+bp.nodeOffsetY, self.nodeAlpha, bp.color:getRedFloat(), bp.color:getGreenFloat(), bp.color:getBlueFloat()); self:drawTexture(bp_no, bp.centerX-(bp_no:getWidth()/2)+bp.nodeOffsetX, bp.centerY-(bp_no:getHeight()/2)+bp.nodeOffsetY, self.nodeAlpha, bp.color:getRedFloat(), bp.color:getGreenFloat(), bp.color:getBlueFloat()); end end end end function ISBodyPartPanel:drawLineLeft(x, y) local midpoint = x+((self.width-x)/2); local tx = self.selectlines.anchorX; local ty = self.selectlines.anchorY; local y1 = y>ty and y or ty; local y2 = y>ty and ty or y; self:drawRect(x, y-1, midpoint-x, 3, 1.0, 0.0, 0.0, 0.0); self:drawRect(midpoint-1, y2, 3, y1-y2, 1.0, 0.0, 0.0, 0.0); self:drawRect(midpoint, ty-1, tx-midpoint, 3, 1.0, 0.0, 0.0, 0.0); self:drawRect(x, y, midpoint-x, 1, 1.0, 1.0, 1.0, 1.0); self:drawRect(midpoint, y2, 1, y1-y2, 1.0, 1.0, 1.0, 1.0); self:drawRect(midpoint, ty, tx-midpoint, 1, 1.0, 1.0, 1.0, 1.0); end function ISBodyPartPanel:getPartForCoordinate(mx, my) local bp, z = false, -1; local out; local x,y = mx, my; for i=1, #self.bps do bp = self.bps[i]; if bp.enabled then if x >= bp.offsetX and x<= bp.offsetX+bp.width and y >= bp.offsetY and y <= bp.offsetY+bp.height and (bp.z or 0) > z then out = bp; z = bp.z or 0; end end end return out; end function ISBodyPartPanel:setSelected(mx, my, bLock) --print("mouse move "..tostring(dx).." - "..tostring(dy)) if self.canSelect then local bp = self:getPartForCoordinate(mx, my); if bp~=self.selectedBp or (bLock and not self.lockedSelection) then self.selectedBp = bp; self.lockedSelection = bLock; if self.onPartSelected then self.onPartSelected( self.functionTarget, bp ); end else if bp==self.selectedBp and bLock then self.lockedSelection =false; end end end end function ISBodyPartPanel:deselect() self.selectedBp = false; self.lockedSelection =false; end function ISBodyPartPanel:onMouseMove(dx, dy) --print("mouse move "..tostring(dx).." - "..tostring(dy)) if not self.lockedSelection then self:setSelected(self:getMouseX(), self:getMouseY()); end end function ISBodyPartPanel:onMouseMoveOutside(dx, dy) if self.selectedBp and (not self.lockedSelection) then self.selectedBp = false; if self.onPartSelected then self.onPartSelected( self.functionTarget, nil ); end end end function ISBodyPartPanel:onMouseDown(x, y) self:setSelected(x, y, true); end function ISBodyPartPanel:onMouseUp(x, y) end function ISBodyPartPanel:onRightMouseUp(x, y) if self.lockedSelection then self.selectedBp = false; self.lockedSelection = false; if self.onPartSelected then self.onPartSelected( self.functionTarget, nil ); end end end function ISBodyPartPanel:setToolTip( _b, _text ) end function ISBodyPartPanel:activateToolTip() end function ISBodyPartPanel:deactivateToolTip() end function ISBodyPartPanel:onJoypadDown(button) if button == Joypad.BButton then --getPlayerInfoPanel(self.playerNum):toggleView(xpSystemText.clothingIns); --setJoypadFocus(self.playerNum, nil); end if button == Joypad.LBumper then --getPlayerInfoPanel(self.playerNum):onJoypadDown(button); end if button == Joypad.RBumper then --getPlayerInfoPanel(self.playerNum):onJoypadDown(button); end end --if enabled, when selecting a node a line will be drawn from the node center to anchor point function ISBodyPartPanel:setEnableSelectLines( _b, _defaultAnchorX, _defaultAnchorY ) self.selectlines.enabled = _b; self:setSelectLinesAnchor( _defaultAnchorX or self:getWidth(), _defaultAnchorY or (self:getHeight()/2)); end function ISBodyPartPanel:setSelectLinesAnchor( _anchorX, _anchorY ) self.selectlines.anchorX = PZMath.clampFloat(_anchorX, 0, self:getWidth()); self.selectlines.anchorY = PZMath.clampFloat(_anchorY, 0, self:getHeight()); end -- enable and set default node texture for all bodyparts -- default available nodes textures: -- "media/ui/BodyParts/bps_node", "media/ui/BodyParts/bps_node_outline" -- "media/ui/BodyParts/bps_node_a", "media/ui/BodyParts/bps_node_a_outline" -- "media/ui/BodyParts/bps_node_big", "media/ui/BodyParts/bps_node_big_outline" -- "media/ui/BodyParts/bps_node_diamond", "media/ui/BodyParts/bps_node_diamond_outline" function ISBodyPartPanel:enableNodes( _nodeTex, _nodeOutlineTex ) self.nodes.enabled = true; self.nodes.nodeTex = getTexture(_nodeTex); self.nodes.nodeOutlineTex = getTexture(_nodeOutlineTex); end --override node texture for a specific bodypart function ISBodyPartPanel:overrideNodeTexture( _bodyPartType, _nodeTex, _nodeOutlineTex ) local target, bp; for i=1, #self.bps do bp = self.bps[i]; if bp.bodyPartType == _bodyPartType then bp.nodeTex = getTexture(_nodeTex); bp.nodeOutlineTex = getTexture(_nodeOutlineTex); break; end end end function ISBodyPartPanel:setAlphas( _defaultAlpha, _nodeAlpha, _selectedAlpha, _deselectedAlpha, _backgroundAlpha ) self.defaultAlpha = _defaultAlpha; self.nodeAlpha = _nodeAlpha; self.selectedAlpha = _selectedAlpha; self.deselectedAlpha = _deselectedAlpha; self.backgroundAlpha = _backgroundAlpha or self.backgroundAlpha; end function ISBodyPartPanel:getBodyPartColor( _bodyPartType ) local bp; for i=1, #self.bps do bp = self.bps[i]; if bp.bodyPartType == _bodyPartType then return bp.color; end end end function ISBodyPartPanel:setValue( _bodyPartType, _value, _force ) local target, bp; local val = PZMath.clampFloat(_value, self.minValue, self.maxValue); for i=1, #self.bps do bp = self.bps[i]; if bp.bodyPartType == _bodyPartType then if _force or bp.value~=val then bp.value = val; self:setColorForValue( bp.value, bp.color ); --[[ local colS = self.colorScheme[1].color; local colE = colS; local s, e = 0, 1; for j=1,#self.colorScheme do if self.colorScheme[j].val >= bp.value then e = self.colorScheme[j].val; colE = self.colorScheme[j].color; break; end colS = self.colorScheme[j].color; s = self.colorScheme[j].val; end colS:interp(colE, (bp.value-s) / ((e-s >0) and (e-s) or 1) ,bp.color); --]] end break; end end end function ISBodyPartPanel:setColorForValue( _val, _color ) local val = PZMath.clampFloat(_val, self.minValue, self.maxValue); local colS = self.colorScheme[1].color; local colE = colS; local s, e = 0, 1; for j=1,#self.colorScheme do if self.colorScheme[j].val >= val then e = self.colorScheme[j].val; colE = self.colorScheme[j].color; break; end colS = self.colorScheme[j].color; s = self.colorScheme[j].val; end colS:interp(colE, (val-s) / ((e-s >0) and (e-s) or 1) , _color); return _color; end function ISBodyPartPanel:getRgbForValue( _val ) self:setColorForValue( _val, self.cacheColor ); return self.cacheColor:getRedFloat(), self.cacheColor:getGreenFloat(), self.cacheColor:getBlueFloat(); end function ISBodyPartPanel:setColorScheme( _colorScheme ) self.colorScheme = _colorScheme; for i=1, #self.bps do local bp = self.bps[i]; self:setValue(bp.bodyPartType, bp.value, true); end end function ISBodyPartPanel:new (player, x, y, target, onPartSelected) local o = ISPanelJoypad:new(x, y, 123, 302); setmetatable(o, self) self.__index = self o.x = x; o.y = y; o.background = false; o.backgroundColor = {r=0, g=0, b=0, a=1.0}; o.borderColor = {r=0.4, g=0.4, b=0.4, a=1}; o.width = 123; o.height = 302; o.anchorLeft = true; o.anchorRight = false; o.anchorTop = true; o.anchorBottom = false; o.player = player; o.playerNum = player:getPlayerNum(); o.bFemale = o.player:isFemale(); o.baseTexture = o.bFemale and getTexture("media/ui/BodyParts/female_base_white") or getTexture("media/ui/BodyParts/male_base_white"); o.outlineTex = o.bFemale and getTexture("media/ui/BodyParts/bps_female_outlines") or getTexture("media/ui/BodyParts/bps_male_outlines"); --options o.minValue = 0; o.maxValue = 1; o.colorScheme = { { val = 0, color = Color.new(0,0,0,1) }, { val = 1, color = Color.new(1,1,1,1) }, } o.canSelect = true; o.selectlines = { enabled = false }; o.drawSelectedHitbox = false; o.nodes = { enabled = false, onlySelected = true }; --o.onClickPart = onClickPart; --o.onMouseOverPart = onMouseOverPart; o.onPartSelected = onPartSelected; o.drawDebugLines = false; o.defaultAlpha = 0.80; o.nodeAlpha = 1.0; o.deselectedAlpha = 0.25; o.selectedAlpha = 1.0; o.backgroundAlpha = 0.25 o.functionTarget = target; o.doToolTip = false; o.toolTipText = ""; return o end