Download CommonLua/Classes/AppearanceObject.lua from sirnii/myspace: direct link, hf CLI and curl.
- Browser
- Download file 9.34 kB
-
https://huggingface.co/spaces/sirnii/myspace/resolve/main/CommonLua/Classes/AppearanceObject.lua
- Command line
-
hf download hf://spaces/sirnii/myspace/CommonLua/Classes/AppearanceObject.lua
-
curl -L -o AppearanceObject.lua https://huggingface.co/spaces/sirnii/myspace/resolve/main/CommonLua/Classes/AppearanceObject.lua
9.34 kB
| DefineClass.AppearanceObjectPart = { | |
| __parents = { "CObject", "ComponentAnim", "ComponentAttach", "ComponentCustomData" }, | |
| flags = { gofSyncState = true, cofComponentColorizationMaterial = true }, | |
| } | |
| function ValidAnimationsCombo(character) | |
| local all_anims = character:GetStatesTextTable() | |
| local valid_anims = {} | |
| for _, anim in ipairs(all_anims) do | |
| if anim:sub(-1, -1) ~= "*" then | |
| table.insert(valid_anims, anim) | |
| end | |
| end | |
| return valid_anims | |
| end | |
| DefineClass.AppearanceObject = { | |
| __parents = { "Shapeshifter", "StripComponentAttachProperties", "ComponentAnim"}, | |
| flags = { gofSyncState = true, cofComponentColorizationMaterial = true }, | |
| properties = | |
| { | |
| { category = "Animation", id = "Appearance", name = "Appearance", editor = "preset_id", preset_class = "AppearancePreset", default = "" }, | |
| { category = "Animation", id = "anim", name = "Animation", editor = "dropdownlist", items = ValidAnimationsCombo, default = "idle" }, | |
| { category = "Animation Blending", id = "animWeight", name = "Animation Weight", editor = "number", slider = true, min = 0, max = 100, default = 100, help = "100 means only Animation is played, 0 means only Animation 2 is played, 50 means both animations are blended equally" }, | |
| { category = "Animation Blending", id = "animBlendTime", name = "Animation Blend Time", editor = "number", min = 0, default = 0 }, | |
| { category = "Animation Blending", id = "anim2", name = "Animation 2", editor = "dropdownlist", items = function(character) local list = character:GetStatesTextTable() table.insert(list, 1, "") return list end, default = "" }, | |
| { category = "Animation Blending", id = "anim2BlendTime", name = "Animation 2 Blend Time", editor = "number", min = 0, default = 0 }, | |
| }, | |
| fallback_body = config.DefaultAppearanceBody, | |
| parts = false, | |
| animFlags = 0, | |
| animCrossfade = 0, | |
| anim2Flags = 0, | |
| anim2Crossfade = 0, | |
| attached_parts = { "Head", "Pants", "Shirt", "Armor", "Hat", "Hat2", "Hair", "Chest", "Hip" }, | |
| animated_parts = { "Head", "Pants", "Shirt", "Armor" }, | |
| appearance_applied = false, | |
| anim_speed = 1000, | |
| } | |
| function AppearanceObject:PostLoad() | |
| self:ApplyAppearance() | |
| end | |
| function AppearanceObject:OnEditorSetProperty(prop_id) | |
| if prop_id == "Appearance" then | |
| self:ApplyAppearance() | |
| end | |
| end | |
| function AppearanceObject:Setanim(anim) | |
| self.anim = anim | |
| self:SetAnimHighLevel() | |
| end | |
| function AppearanceObject:Setanim2(anim) | |
| self.anim2 = anim | |
| self:SetAnimHighLevel() | |
| end | |
| function AppearanceObject:SetanimFlags(anim_flags) | |
| self.animFlags = anim_flags | |
| end | |
| function AppearanceObject:SetanimCrossfade(crossfade) | |
| self.animCrossfade = crossfade | |
| end | |
| function AppearanceObject:Setanim2Flags(anim_flags) | |
| self.anim2Flags = anim_flags | |
| end | |
| function AppearanceObject:Setanim2Crossfade(crossfade) | |
| self.anim2Crossfade = crossfade | |
| end | |
| function AppearanceObject:SetanimWeight(weight) | |
| self.animWeight = weight | |
| self:SetAnimHighLevel() | |
| end | |
| function AppearanceObject:SetAnimChannel(channel, anim, anim_flags, crossfade, weight, blend_time) | |
| if not self:HasState(anim) then | |
| if self:GetEntity() ~= "" then | |
| StoreErrorSource(self, "Missing object state " .. self:GetEntity() .. "." .. anim) | |
| end | |
| return | |
| end | |
| Shapeshifter.SetAnim(self, channel, anim, anim_flags, crossfade) | |
| Shapeshifter.SetAnimWeight(self, channel, 100) | |
| Shapeshifter.SetAnimWeight(self, channel, weight, blend_time) | |
| self:SetAnimSpeed(channel, self.anim_speed) | |
| local parts = self.parts | |
| if parts then | |
| for _, part_name in ipairs(self.animated_parts) do | |
| local part = parts[part_name] | |
| if part then | |
| part:SetAnim(channel, anim, anim_flags, crossfade) | |
| part:SetAnimWeight(channel, 100) | |
| part:SetAnimWeight(channel, weight, blend_time) | |
| part:SetAnimSpeed(channel, self.anim_speed) | |
| end | |
| end | |
| end | |
| return GetAnimDuration(self:GetEntity(), self:GetAnim(channel)) | |
| end | |
| function AppearanceObject:SetAnimLowLevel() | |
| self:ApplyAppearance() | |
| local time = self:SetAnimChannel(1, self.anim, self.animFlags, self.animCrossfade, self.animWeight, self.animBlendTime) | |
| if self.anim2 ~= "" then | |
| local time2, duration2 = self:SetAnimChannel(2, self.anim2, self.anim2Flags, self.anim2Crossfade, 100 - self.animWeight, self.anim2BlendTime) | |
| time = Max(time, time2) | |
| end | |
| return time | |
| end | |
| function AppearanceObject:SetAnimHighLevel() | |
| self:SetAnimLowLevel() | |
| end | |
| function AppearanceObject:SetEntity() | |
| end | |
| local function get_part_offset_angle(appearance, prop_name) | |
| local x = appearance[prop_name .. "AttachOffsetX"] or 0 | |
| local y = appearance[prop_name .. "AttachOffsetY"] or 0 | |
| local z = appearance[prop_name .. "AttachOffsetZ"] or 0 | |
| local angle = appearance[prop_name .. "AttachOffsetAngle"] or 0 | |
| if x ~= 0 or y ~= 0 or z ~= 0 or angle ~= 0 then | |
| return point(x, y, z), angle | |
| end | |
| end | |
| -- overload this in project | |
| config.DefaultAppearanceBody = "ErrorAnimatedMesh" | |
| function AppearanceObject:ColorizePart(part_name) | |
| local appearance = AppearancePresets[self.Appearance] | |
| local prop_color_name = string.format("%sColor", part_name) | |
| if not appearance:HasMember(prop_color_name) then return end | |
| local part = self.parts[part_name] | |
| local color_member = appearance[prop_color_name] | |
| if not color_member then | |
| print("once", string.format("[WARNING] No color specified for %s in %s", part_name, self.Appearance)) | |
| return | |
| end | |
| local palette = color_member["ColorizationPalette"] | |
| part:SetColorizationPalette(palette) | |
| for i = 1, const.MaxColorizationMaterials do | |
| if string.match(part_name, "Hair") then | |
| local custom = {} | |
| for i = 1, 4 do | |
| custom[i] = appearance["HairParam" .. i] | |
| end | |
| part:SetHairCustomParams(custom) | |
| end | |
| local color = color_member[string.format("EditableColor%d", i)] | |
| local roughness = color_member[string.format("EditableRoughness%d", i)] | |
| local metallic = color_member[string.format("EditableMetallic%d", i)] | |
| part:SetColorizationMaterial(i, color, roughness, metallic) | |
| end | |
| end | |
| function AppearanceObject:ApplyPartSpotAttachments(part_name) | |
| local appearance = AppearancePresets[self.Appearance] | |
| local part = self.parts[part_name] | |
| local spot_prop = part_name .. "Spot" | |
| local prop_spot = appearance:HasMember(spot_prop) and appearance[spot_prop] | |
| local spot_name = prop_spot or "Origin" | |
| self:Attach(part, self:GetSpotBeginIndex(spot_name)) | |
| if part_name == "Hat" or part_name == "Hat2" then | |
| local offset, angle = get_part_offset_angle(appearance, part_name) | |
| if offset and angle then | |
| part:SetAttachOffset(offset) | |
| part:SetAttachAngle(angle) | |
| end | |
| end | |
| end | |
| function AppearanceObject:ApplyAppearance(appearance, force) | |
| appearance = appearance or self.Appearance | |
| if not appearance then return end | |
| if not force and self.appearance_applied == appearance then return end | |
| self.appearance_applied = appearance | |
| if type(appearance) == "string" then | |
| self.Appearance = appearance | |
| appearance = AppearancePresets[appearance] | |
| else | |
| self.Appearance = appearance.id | |
| end | |
| if not appearance then | |
| local prop_meta = AppearanceObject:GetPropertyMetadata("Appearance") | |
| appearance = AppearancePresets[prop_meta.default] | |
| if not appearance then | |
| StoreErrorSource(self, "Default Appearance can't be invalid!") | |
| end | |
| appearance = AppearancePresets[self.Appearance] | |
| if not appearance then | |
| StoreErrorSource(self, string.format("Invalid appearance '%s'", self.Appearance)) | |
| return | |
| end | |
| end | |
| for _, part in pairs(self.parts) do | |
| DoneObject(part) | |
| end | |
| self:ChangeEntity(appearance.Body or self.fallback_body or config.DefaultAppearanceBody) | |
| if not IsValidEntity(self:GetEntity()) then | |
| StoreErrorSource(self, string.format("Invalid entity '%s'(%s) for Appearance '%s'", self:GetEntity(), appearance.Body, appearance.id)) | |
| printf("Invalid entity '%s'(%s) for Appearance '%s'", self:GetEntity(), appearance.Body, appearance.id) | |
| end | |
| if appearance:HasMember("BodyColor") and appearance.BodyColor then | |
| self:SetColorization(appearance.BodyColor, true) | |
| end | |
| self.parts = {} | |
| local real_time_animated = self:GetGameFlags(const.gofRealTimeAnim) ~= 0 | |
| for _, part_name in ipairs(self.attached_parts) do | |
| if IsValidEntity(appearance[part_name]) then | |
| local part = PlaceObject("AppearanceObjectPart") | |
| if real_time_animated then | |
| part:SetGameFlags(const.gofRealTimeAnim) | |
| end | |
| part:ChangeEntity(appearance[part_name]) | |
| if not IsValidEntity(part:GetEntity()) then | |
| StoreErrorSource(part, string.format("Invalid entity part '%s'(%s) for Appearance '%s'", part:GetEntity(), appearance[part_name], appearance.id)) | |
| printf("Invalid entity part '%s'(%s) for Appearance '%s'", part:GetEntity(), appearance[part_name], appearance.id) | |
| end | |
| self.parts[part_name] = part | |
| self:ColorizePart(part_name) | |
| self:ApplyPartSpotAttachments(part_name) | |
| end | |
| end | |
| self:Setanim(self.anim) | |
| end | |
| function AppearanceObject:PlayAnim(anim) | |
| self:Setanim(anim) | |
| local vec = self:GetStepVector() | |
| local time = self:GetAnimDuration() | |
| if vec:Len() > 0 then | |
| self:SetPos(self:GetPos() + vec, time) | |
| end | |
| Sleep(time) | |
| end | |
| function AppearanceObject:SetPhaseHighLevel(phase) | |
| self:SetAnimPhase(1, phase) | |
| local parts = self.parts | |
| if parts then | |
| for _, part_name in ipairs(self.attached_parts) do | |
| local part = parts[part_name] | |
| if part then | |
| part:SetAnimPhase(1, phase) | |
| end | |
| end | |
| end | |
| end | |
| function AppearanceObject:SetAnimPose(anim, phase) | |
| self:Setanim(anim) | |
| self.anim_speed = 0 | |
| self:SetPhaseHighLevel(phase) | |
| end | |