|
<!DOCTYPE html> |
|
<html lang="en"> |
|
<head> |
|
<meta charset="UTF-8"> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
<title>Python Strings and Methods for Autodesk Maya</title> |
|
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet"> |
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.0.0/css/all.min.css"> |
|
<style> |
|
body { |
|
background-color: #1a1a1a; |
|
color: #e0e0e0; |
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; |
|
} |
|
.method-container { |
|
background-color: #2d2d2d; |
|
border-radius: 8px; |
|
margin-bottom: 20px; |
|
transition: all 0.3s ease; |
|
} |
|
.method-container:hover { |
|
box-shadow: 0 0 15px rgba(66, 153, 225, 0.3); |
|
} |
|
.play-button { |
|
background-color: #4299e1; |
|
transition: all 0.2s ease; |
|
} |
|
.play-button:hover { |
|
background-color: #3182ce; |
|
transform: scale(1.05); |
|
} |
|
.play-button:active { |
|
transform: scale(0.98); |
|
} |
|
.result-box { |
|
background-color: #363636; |
|
border-left: 4px solid #4299e1; |
|
font-family: 'Consolas', 'Courier New', monospace; |
|
} |
|
.section-title { |
|
border-bottom: 2px solid #4299e1; |
|
padding-bottom: 8px; |
|
} |
|
input[type="text"], textarea { |
|
background-color: #363636; |
|
border: 1px solid #4a4a4a; |
|
color: #e0e0e0; |
|
} |
|
input[type="text"]:focus, textarea:focus { |
|
border-color: #4299e1; |
|
outline: none; |
|
box-shadow: 0 0 0 3px rgba(66, 153, 225, 0.3); |
|
} |
|
code { |
|
background-color: #363636; |
|
padding: 2px 4px; |
|
border-radius: 4px; |
|
font-family: 'Consolas', 'Courier New', monospace; |
|
} |
|
</style> |
|
</head> |
|
<body class="px-4 py-6 max-w-6xl mx-auto"> |
|
<header class="mb-8"> |
|
<h1 class="text-4xl font-bold text-blue-400 mb-2">Python Strings and Methods for Autodesk Maya</h1> |
|
<p class="text-lg text-gray-300">Interactive examples to practice string manipulation techniques useful in Maya scripting</p> |
|
</header> |
|
|
|
<main> |
|
|
|
<section class="mb-10"> |
|
<p class="mb-4"> |
|
In Maya Python scripting, strings are essential for working with node names, file paths, commands, and more. |
|
This interactive guide lets you experiment with Python's string methods and see immediate results. |
|
</p> |
|
<p class="text-sm text-gray-400 italic mb-6"> |
|
For each example, enter your own text in the input field and click the play button to see the result. |
|
</p> |
|
</section> |
|
|
|
|
|
<section class="mb-10"> |
|
<h2 class="text-2xl font-bold text-blue-300 section-title mb-4">Basic String Operations</h2> |
|
|
|
|
|
<div class="method-container p-4 mb-6"> |
|
<h3 class="text-xl font-semibold mb-2">String Concatenation</h3> |
|
<p class="mb-3">Combines two or more strings together using the <code>+</code> operator. In Maya, this is often used to build command strings or create full paths.</p> |
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4"> |
|
<div> |
|
<label class="block mb-2">First String:</label> |
|
<input type="text" id="concat-input1" class="w-full p-2 rounded" value="sphere_" placeholder="Enter first string"> |
|
</div> |
|
<div> |
|
<label class="block mb-2">Second String:</label> |
|
<input type="text" id="concat-input2" class="w-full p-2 rounded" value="01" placeholder="Enter second string"> |
|
</div> |
|
</div> |
|
|
|
<button onclick="concatStrings()" class="play-button px-4 py-2 rounded text-white flex items-center"> |
|
<i class="fas fa-play mr-2"></i> Run Example |
|
</button> |
|
|
|
<div class="mt-4"> |
|
<p class="font-medium mb-1">Result:</p> |
|
<div id="concat-result" class="result-box p-3 rounded"></div> |
|
</div> |
|
|
|
<div class="mt-4 text-sm text-gray-400"> |
|
<p>Maya usage example:</p> |
|
<pre class="bg-gray-800 p-2 rounded"><code>node_prefix = "pSphere" |
|
node_number = "1" |
|
full_node_name = node_prefix + node_number # Creates "pSphere1" |
|
cmds.select(full_node_name)</code></pre> |
|
</div> |
|
</div> |
|
|
|
|
|
<div class="method-container p-4 mb-6"> |
|
<h3 class="text-xl font-semibold mb-2">String Indexing</h3> |
|
<p class="mb-3">Access individual characters in a string using their index position (starting from 0). Useful for inspecting specific characters in node names.</p> |
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4"> |
|
<div> |
|
<label class="block mb-2">String:</label> |
|
<input type="text" id="index-input" class="w-full p-2 rounded" value="pCube5_grp" placeholder="Enter a string"> |
|
</div> |
|
<div> |
|
<label class="block mb-2">Index Position:</label> |
|
<input type="number" id="index-position" class="w-full p-2 rounded" value="1" min="0" placeholder="Enter index number"> |
|
</div> |
|
</div> |
|
|
|
<button onclick="indexString()" class="play-button px-4 py-2 rounded text-white flex items-center"> |
|
<i class="fas fa-play mr-2"></i> Run Example |
|
</button> |
|
|
|
<div class="mt-4"> |
|
<p class="font-medium mb-1">Result:</p> |
|
<div id="index-result" class="result-box p-3 rounded"></div> |
|
</div> |
|
|
|
<div class="mt-4 text-sm text-gray-400"> |
|
<p>Maya usage example:</p> |
|
<pre class="bg-gray-800 p-2 rounded"><code>node_name = "pSphere1" |
|
node_type = node_name[0] # Gets 'p' which can indicate a polygon object |
|
if node_type == "p": |
|
print("This is likely a polygon object")</code></pre> |
|
</div> |
|
</div> |
|
|
|
|
|
<div class="method-container p-4 mb-6"> |
|
<h3 class="text-xl font-semibold mb-2">String Slicing</h3> |
|
<p class="mb-3">Extract a substring using the slice notation <code>[start:end]</code>. Useful for extracting parts of object names or file paths in Maya.</p> |
|
|
|
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-4"> |
|
<div> |
|
<label class="block mb-2">String:</label> |
|
<input type="text" id="slice-input" class="w-full p-2 rounded" value="pCylinder25_geo" placeholder="Enter a string"> |
|
</div> |
|
<div> |
|
<label class="block mb-2">Start Index:</label> |
|
<input type="number" id="slice-start" class="w-full p-2 rounded" value="0" min="0" placeholder="Start index"> |
|
</div> |
|
<div> |
|
<label class="block mb-2">End Index:</label> |
|
<input type="number" id="slice-end" class="w-full p-2 rounded" value="9" min="0" placeholder="End index"> |
|
</div> |
|
</div> |
|
|
|
<button onclick="sliceString()" class="play-button px-4 py-2 rounded text-white flex items-center"> |
|
<i class="fas fa-play mr-2"></i> Run Example |
|
</button> |
|
|
|
<div class="mt-4"> |
|
<p class="font-medium mb-1">Result:</p> |
|
<div id="slice-result" class="result-box p-3 rounded"></div> |
|
</div> |
|
|
|
<div class="mt-4 text-sm text-gray-400"> |
|
<p>Maya usage example:</p> |
|
<pre class="bg-gray-800 p-2 rounded"><code>file_path = "C:/Projects/Maya/scenes/character_rig_v001.mb" |
|
file_name = file_path[-11:] # Gets "v001.mb" |
|
version_number = file_name[1:4] # Gets "001"</code></pre> |
|
</div> |
|
</div> |
|
</section> |
|
|
|
|
|
<section class="mb-10"> |
|
<h2 class="text-2xl font-bold text-blue-300 section-title mb-4">Case Methods</h2> |
|
|
|
|
|
<div class="method-container p-4 mb-6"> |
|
<h3 class="text-xl font-semibold mb-2">.upper()</h3> |
|
<p class="mb-3">Converts all characters in a string to uppercase. Useful for case-insensitive comparisons in Maya scripts.</p> |
|
|
|
<div class="mb-4"> |
|
<label class="block mb-2">String:</label> |
|
<input type="text" id="upper-input" class="w-full p-2 rounded" value="leftArm_ctrl" placeholder="Enter a string"> |
|
</div> |
|
|
|
<button onclick="upperCaseString()" class="play-button px-4 py-2 rounded text-white flex items-center"> |
|
<i class="fas fa-play mr-2"></i> Run Example |
|
</button> |
|
|
|
<div class="mt-4"> |
|
<p class="font-medium mb-1">Result:</p> |
|
<div id="upper-result" class="result-box p-3 rounded"></div> |
|
</div> |
|
|
|
<div class="mt-4 text-sm text-gray-400"> |
|
<p>Maya usage example:</p> |
|
<pre class="bg-gray-800 p-2 rounded"><code>user_input = "yes" |
|
if user_input.upper() == "YES": |
|
# Process regardless of input case (yes, Yes, YES) |
|
cmds.polyCube(name="new_cube")</code></pre> |
|
</div> |
|
</div> |
|
|
|
|
|
<div class="method-container p-4 mb-6"> |
|
<h3 class="text-xl font-semibold mb-2">.lower()</h3> |
|
<p class="mb-3">Converts all characters in a string to lowercase. Useful for standardizing naming or case-insensitive comparisons.</p> |
|
|
|
<div class="mb-4"> |
|
<label class="block mb-2">String:</label> |
|
<input type="text" id="lower-input" class="w-full p-2 rounded" value="RightLeg_GRP" placeholder="Enter a string"> |
|
</div> |
|
|
|
<button onclick="lowerCaseString()" class="play-button px-4 py-2 rounded text-white flex items-center"> |
|
<i class="fas fa-play mr-2"></i> Run Example |
|
</button> |
|
|
|
<div class="mt-4"> |
|
<p class="font-medium mb-1">Result:</p> |
|
<div id="lower-result" class="result-box p-3 rounded"></div> |
|
</div> |
|
|
|
<div class="mt-4 text-sm text-gray-400"> |
|
<p>Maya usage example:</p> |
|
<pre class="bg-gray-800 p-2 rounded"><code>obj_name = "CHARACTER_RIG" |
|
standardized_name = obj_name.lower() # "character_rig" |
|
cmds.rename(obj_name, standardized_name)</code></pre> |
|
</div> |
|
</div> |
|
|
|
|
|
<div class="method-container p-4 mb-6"> |
|
<h3 class="text-xl font-semibold mb-2">.title()</h3> |
|
<p class="mb-3">Converts the first character of each word to uppercase and the rest to lowercase. Useful for formatting display names in UIs.</p> |
|
|
|
<div class="mb-4"> |
|
<label class="block mb-2">String:</label> |
|
<input type="text" id="title-input" class="w-full p-2 rounded" value="character facial controls" placeholder="Enter a string"> |
|
</div> |
|
|
|
<button onclick="titleCaseString()" class="play-button px-4 py-2 rounded text-white flex items-center"> |
|
<i class="fas fa-play mr-2"></i> Run Example |
|
</button> |
|
|
|
<div class="mt-4"> |
|
<p class="font-medium mb-1">Result:</p> |
|
<div id="title-result" class="result-box p-3 rounded"></div> |
|
</div> |
|
|
|
<div class="mt-4 text-sm text-gray-400"> |
|
<p>Maya usage example:</p> |
|
<pre class="bg-gray-800 p-2 rounded"><code>control_description = "head rotation controls" |
|
display_name = control_description.title() # "Head Rotation Controls" |
|
cmds.button(label=display_name)</code></pre> |
|
</div> |
|
</div> |
|
|
|
|
|
<div class="method-container p-4 mb-6"> |
|
<h3 class="text-xl font-semibold mb-2">.capitalize()</h3> |
|
<p class="mb-3">Capitalizes the first character of the string and converts the rest to lowercase. Useful for formatting single labels or short descriptions.</p> |
|
|
|
<div class="mb-4"> |
|
<label class="block mb-2">String:</label> |
|
<input type="text" id="capitalize-input" class="w-full p-2 rounded" value="mainController" placeholder="Enter a string"> |
|
</div> |
|
|
|
<button onclick="capitalizeString()" class="play-button px-4 py-2 rounded text-white flex items-center"> |
|
<i class="fas fa-play mr-2"></i> Run Example |
|
</button> |
|
|
|
<div class="mt-4"> |
|
<p class="font-medium mb-1">Result:</p> |
|
<div id="capitalize-result" class="result-box p-3 rounded"></div> |
|
</div> |
|
|
|
<div class="mt-4 text-sm text-gray-400"> |
|
<p>Maya usage example:</p> |
|
<pre class="bg-gray-800 p-2 rounded"><code>error_message = "invalid selection" |
|
formatted_message = error_message.capitalize() # "Invalid selection" |
|
cmds.warning(formatted_message)</code></pre> |
|
</div> |
|
</div> |
|
</section> |
|
|
|
|
|
<section class="mb-10"> |
|
<h2 class="text-2xl font-bold text-blue-300 section-title mb-4">Search Methods</h2> |
|
|
|
|
|
<div class="method-container p-4 mb-6"> |
|
<h3 class="text-xl font-semibold mb-2">.find()</h3> |
|
<p class="mb-3">Returns the index of the first occurrence of a substring, or -1 if not found. Useful for locating specific patterns in node names or paths.</p> |
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4"> |
|
<div> |
|
<label class="block mb-2">String:</label> |
|
<input type="text" id="find-input" class="w-full p-2 rounded" value="character_arm_joint_01" placeholder="Enter a string"> |
|
</div> |
|
<div> |
|
<label class="block mb-2">Substring to Find:</label> |
|
<input type="text" id="find-substring" class="w-full p-2 rounded" value="arm" placeholder="Enter substring to find"> |
|
</div> |
|
</div> |
|
|
|
<button onclick="findInString()" class="play-button px-4 py-2 rounded text-white flex items-center"> |
|
<i class="fas fa-play mr-2"></i> Run Example |
|
</button> |
|
|
|
<div class="mt-4"> |
|
<p class="font-medium mb-1">Result:</p> |
|
<div id="find-result" class="result-box p-3 rounded"></div> |
|
</div> |
|
|
|
<div class="mt-4 text-sm text-gray-400"> |
|
<p>Maya usage example:</p> |
|
<pre class="bg-gray-800 p-2 rounded"><code>node_name = "character_arm_joint_01" |
|
if node_name.find("arm") != -1: |
|
print("This is an arm joint") |
|
# Add arm-specific rigging code</code></pre> |
|
</div> |
|
</div> |
|
|
|
|
|
<div class="method-container p-4 mb-6"> |
|
<h3 class="text-xl font-semibold mb-2">.startswith()</h3> |
|
<p class="mb-3">Checks if a string starts with a specified prefix, returning True or False. Useful for filtering nodes by prefix naming conventions.</p> |
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4"> |
|
<div> |
|
<label class="block mb-2">String:</label> |
|
<input type="text" id="startswith-input" class="w-full p-2 rounded" value="jnt_spine_01" placeholder="Enter a string"> |
|
</div> |
|
<div> |
|
<label class="block mb-2">Prefix to Check:</label> |
|
<input type="text" id="startswith-prefix" class="w-full p-2 rounded" value="jnt_" placeholder="Enter prefix to check"> |
|
</div> |
|
</div> |
|
|
|
<button onclick="checkStartsWith()" class="play-button px-4 py-2 rounded text-white flex items-center"> |
|
<i class="fas fa-play mr-2"></i> Run Example |
|
</button> |
|
|
|
<div class="mt-4"> |
|
<p class="font-medium mb-1">Result:</p> |
|
<div id="startswith-result" class="result-box p-3 rounded"></div> |
|
</div> |
|
|
|
<div class="mt-4 text-sm text-gray-400"> |
|
<p>Maya usage example:</p> |
|
<pre class="bg-gray-800 p-2 rounded"><code>all_nodes = cmds.ls() |
|
joint_nodes = [] |
|
|
|
for node in all_nodes: |
|
if node.startswith("jnt_"): |
|
joint_nodes.append(node) |
|
|
|
print(f"Found {len(joint_nodes)} joints")</code></pre> |
|
</div> |
|
</div> |
|
|
|
|
|
<div class="method-container p-4 mb-6"> |
|
<h3 class="text-xl font-semibold mb-2">.endswith()</h3> |
|
<p class="mb-3">Checks if a string ends with a specified suffix, returning True or False. Useful for filtering nodes by suffix naming conventions.</p> |
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4"> |
|
<div> |
|
<label class="block mb-2">String:</label> |
|
<input type="text" id="endswith-input" class="w-full p-2 rounded" value="character_head_ctrl" placeholder="Enter a string"> |
|
</div> |
|
<div> |
|
<label class="block mb-2">Suffix to Check:</label> |
|
<input type="text" id="endswith-suffix" class="w-full p-2 rounded" value="_ctrl" placeholder="Enter suffix to check"> |
|
</div> |
|
</div> |
|
|
|
<button onclick="checkEndsWith()" class="play-button px-4 py-2 rounded text-white flex items-center"> |
|
<i class="fas fa-play mr-2"></i> Run Example |
|
</button> |
|
|
|
<div class="mt-4"> |
|
<p class="font-medium mb-1">Result:</p> |
|
<div id="endswith-result" class="result-box p-3 rounded"></div> |
|
</div> |
|
|
|
<div class="mt-4 text-sm text-gray-400"> |
|
<p>Maya usage example:</p> |
|
<pre class="bg-gray-800 p-2 rounded"><code>all_objects = cmds.ls() |
|
control_objects = [] |
|
|
|
for obj in all_objects: |
|
if obj.endswith("_ctrl"): |
|
control_objects.append(obj) |
|
|
|
cmds.select(control_objects) # Select all control objects</code></pre> |
|
</div> |
|
</div> |
|
</section> |
|
|
|
|
|
<section class="mb-10"> |
|
<h2 class="text-2xl font-bold text-blue-300 section-title mb-4">Modification Methods</h2> |
|
|
|
|
|
<div class="method-container p-4 mb-6"> |
|
<h3 class="text-xl font-semibold mb-2">.replace()</h3> |
|
<p class="mb-3">Replaces occurrences of a substring with another substring. Perfect for renaming parts of object names or updating file paths.</p> |
|
|
|
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-4"> |
|
<div> |
|
<label class="block mb-2">String:</label> |
|
<input type="text" id="replace-input" class="w-full p-2 rounded" value="arm_left_ctrl" placeholder="Enter a string"> |
|
</div> |
|
<div> |
|
<label class="block mb-2">Text to Replace:</label> |
|
<input type="text" id="replace-old" class="w-full p-2 rounded" value="left" placeholder="Text to replace"> |
|
</div> |
|
<div> |
|
<label class="block mb-2">Replacement Text:</label> |
|
<input type="text" id="replace-new" class="w-full p-2 rounded" value="right" placeholder="Replacement text"> |
|
</div> |
|
</div> |
|
|
|
<button onclick="replaceInString()" class="play-button px-4 py-2 rounded text-white flex items-center"> |
|
<i class="fas fa-play mr-2"></i> Run Example |
|
</button> |
|
|
|
<div class="mt-4"> |
|
<p class="font-medium mb-1">Result:</p> |
|
<div id="replace-result" class="result-box p-3 rounded"></div> |
|
</div> |
|
|
|
<div class="mt-4 text-sm text-gray-400"> |
|
<p>Maya usage example:</p> |
|
<pre class="bg-gray-800 p-2 rounded"><code>left_nodes = cmds.ls("*left*") |
|
for node in left_nodes: |
|
right_node_name = node.replace("left", "right") |
|
duplicate_node = cmds.duplicate(node, name=right_node_name) |
|
# Now mirror the duplicate to the right side</code></pre> |
|
</div> |
|
</div> |
|
|
|
|
|
<div class="method-container p-4 mb-6"> |
|
<h3 class="text-xl font-semibold mb-2">.strip()</h3> |
|
<p class="mb-3">Removes leading and trailing whitespace or specified characters. Useful for cleaning up user input or imported data.</p> |
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4"> |
|
<div> |
|
<label class="block mb-2">String (with whitespace or chars to remove):</label> |
|
<input type="text" id="strip-input" class="w-full p-2 rounded" value=" pSphere1 " placeholder="Enter a string with whitespace"> |
|
</div> |
|
<div> |
|
<label class="block mb-2">Characters to Strip (optional):</label> |
|
<input type="text" id="strip-chars" class="w-full p-2 rounded" placeholder="Enter specific chars to strip (leave empty for whitespace)"> |
|
</div> |
|
</div> |
|
|
|
<button onclick="stripString()" class="play-button px-4 py-2 rounded text-white flex items-center"> |
|
<i class="fas fa-play mr-2"></i> Run Example |
|
</button> |
|
|
|
<div class="mt-4"> |
|
<p class="font-medium mb-1">Result:</p> |
|
<div id="strip-result" class="result-box p-3 rounded"></div> |
|
</div> |
|
|
|
<div class="mt-4 text-sm text-gray-400"> |
|
<p>Maya usage example:</p> |
|
<pre class="bg-gray-800 p-2 rounded"><code>user_input = " pCube1 " # User might add extra spaces |
|
clean_input = user_input.strip() |
|
if cmds.objExists(clean_input): |
|
cmds.select(clean_input) |
|
else: |
|
cmds.warning("Object not found")</code></pre> |
|
</div> |
|
</div> |
|
|
|
|
|
<div class="method-container p-4 mb-6"> |
|
<h3 class="text-xl font-semibold mb-2">.split()</h3> |
|
<p class="mb-3">Splits a string into a list using a delimiter. Perfect for parsing paths, node hierarchies, or breaking down complex names.</p> |
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4"> |
|
<div> |
|
<label class="block mb-2">String:</label> |
|
<input type="text" id="split-input" class="w-full p-2 rounded" value="head_geo|head_eyebrows_geo|head_eyes_geo" placeholder="Enter a string"> |
|
</div> |
|
<div> |
|
<label class="block mb-2">Delimiter:</label> |
|
<input type="text" id="split-delimiter" class="w-full p-2 rounded" value="|" placeholder="Enter delimiter character"> |
|
</div> |
|
</div> |
|
|
|
<button onclick="splitString()" class="play-button px-4 py-2 rounded text-white flex items-center"> |
|
<i class="fas fa-play mr-2"></i> Run Example |
|
</button> |
|
|
|
<div class="mt-4"> |
|
<p class="font-medium mb-1">Result:</p> |
|
<div id="split-result" class="result-box p-3 rounded"></div> |
|
</div> |
|
|
|
<div class="mt-4 text-sm text-gray-400"> |
|
<p>Maya usage example:</p> |
|
<pre class="bg-gray-800 p-2 rounded"><code>full_path = "characters|hero|skeleton|spine|neck|head" |
|
path_components = full_path.split("|") |
|
parent_node = path_components[-2] # "neck" |
|
cmds.select(parent_node)</code></pre> |
|
</div> |
|
</div> |
|
|
|
|
|
<div class="method-container p-4 mb-6"> |
|
<h3 class="text-xl font-semibold mb-2">str.join()</h3> |
|
<p class="mb-3">Joins elements of an iterable with a specified string. Useful for building paths, constructing node names, or formatting output.</p> |
|
|
|
<div class="mb-4"> |
|
<label class="block mb-2">List of Strings (comma-separated):</label> |
|
<input type="text" id="join-input" class="w-full p-2 rounded" value="character,rig,arm,left,01" placeholder="Enter comma-separated strings"> |
|
|
|
<label class="block mt-4 mb-2">Join Character:</label> |
|
<input type="text" id="join-char" class="w-full p-2 rounded" value="_" placeholder="Character to join with"> |
|
</div> |
|
|
|
<button onclick="joinStrings()" class="play-button px-4 py-2 rounded text-white flex items-center"> |
|
<i class="fas fa-play mr-2"></i> Run Example |
|
</button> |
|
|
|
<div class="mt-4"> |
|
<p class="font-medium mb-1">Result:</p> |
|
<div id="join-result" class="result-box p-3 rounded"></div> |
|
</div> |
|
|
|
<div class="mt-4 text-sm text-gray-400"> |
|
<p>Maya usage example:</p> |
|
<pre class="bg-gray-800 p-2 rounded"><code>name_parts = ["character", "arm", "left", "ctrl"] |
|
node_name = "_".join(name_parts) # "character_arm_left_ctrl" |
|
cmds.circle(name=node_name)</code></pre> |
|
</div> |
|
</div> |
|
</section> |
|
|
|
|
|
<section class="mb-10"> |
|
<h2 class="text-2xl font-bold text-blue-300 section-title mb-4">Maya-Specific Examples</h2> |
|
|
|
|
|
<div class="method-container p-4 mb-6"> |
|
<h3 class="text-xl font-semibold mb-2">Node Naming Convention Tool</h3> |
|
<p class="mb-3">Creates a Maya-style node name based on input parts. Demonstrates string concatenation and naming conventions.</p> |
|
|
|
<div class="grid grid-cols-1 md:grid-cols-4 gap-4 mb-4"> |
|
<div> |
|
<label class="block mb-2">Prefix:</label> |
|
<select id="node-prefix" class="w-full p-2 rounded bg-gray-700 text-white"> |
|
<option value="c_">c_ (center)</option> |
|
<option value="l_">l_ (left)</option> |
|
<option value="r_">r_ (right)</option> |
|
</select> |
|
</div> |
|
<div> |
|
<label class="block mb-2">Body Part:</label> |
|
<input type="text" id="node-bodypart" class="w-full p-2 rounded" value="arm" placeholder="Body part"> |
|
</div> |
|
<div> |
|
<label class="block mb-2">Index:</label> |
|
<input type="number" id="node-index" class="w-full p-2 rounded" value="1" min="1" placeholder="Index number"> |
|
</div> |
|
<div> |
|
<label class="block mb-2">Type:</label> |
|
<select id="node-type" class="w-full p-2 rounded bg-gray-700 text-white"> |
|
<option value="_jnt">_jnt (joint)</option> |
|
<option value="_geo">_geo (geometry)</option> |
|
<option value="_ctrl">_ctrl (controller)</option> |
|
<option value="_grp">_grp (group)</option> |
|
</select> |
|
</div> |
|
</div> |
|
|
|
<button onclick="generateNodeName()" class="play-button px-4 py-2 rounded text-white flex items-center"> |
|
<i class="fas fa-play mr-2"></i> Generate Node Name |
|
</button> |
|
|
|
<div class="mt-4"> |
|
<p class="font-medium mb-1">Result:</p> |
|
<div id="maya-naming-result" class="result-box p-3 rounded"></div> |
|
</div> |
|
|
|
<div class="mt-4 text-sm text-gray-400"> |
|
<p>Maya usage example:</p> |
|
<pre class="bg-gray-800 p-2 rounded"><code>def create_named_joint(side, part, index): |
|
side_prefix = { |
|
"left": "l_", |
|
"right": "r_", |
|
"center": "c_" |
|
}.get(side, "c_") |
|
|
|
node_name = f"{side_prefix}{part}{str(index).zfill(2)}_jnt" |
|
return cmds.joint(name=node_name) |
|
|
|
# Create joints with proper naming |
|
spine_joint = create_named_joint("center", "spine", 1) |
|
left_arm_joint = create_named_joint("left", "arm", 1)</code></pre> |
|
</div> |
|
</div> |
|
|
|
|
|
<div class="method-container p-4 mb-6"> |
|
<h3 class="text-xl font-semibold mb-2">Maya File Path Manipulation</h3> |
|
<p class="mb-3">Extract and modify parts of a Maya file path. Demonstrates how to work with file paths in Maya scripts.</p> |
|
|
|
<div class="mb-4"> |
|
<label class="block mb-2">Maya File Path:</label> |
|
<input type="text" id="filepath-input" class="w-full p-2 rounded" value="C:/Projects/Character/scenes/character_model_v001.mb" placeholder="Enter a file path"> |
|
</div> |
|
|
|
<button onclick="analyzeFilePath()" class="play-button px-4 py-2 rounded text-white flex items-center"> |
|
<i class="fas fa-play mr-2"></i> Analyze Path |
|
</button> |
|
|
|
<div class="mt-4"> |
|
<p class="font-medium mb-1">Result:</p> |
|
<div id="filepath-result" class="result-box p-3 rounded whitespace-pre-line"></div> |
|
</div> |
|
|
|
<div class="mt-4 text-sm text-gray-400"> |
|
<p>Maya usage example:</p> |
|
<pre class="bg-gray-800 p-2 rounded"><code>def increment_version(file_path): |
|
# Split the path to get the directory and filename |
|
components = file_path.replace("\\", "/").split("/") |
|
directory = "/".join(components[:-1]) |
|
file_name = components[-1] |
|
|
|
# Find version number |
|
if "_v" in file_name: |
|
base_name, version_ext = file_name.split("_v") |
|
version_num, ext = version_ext.split(".") |
|
|
|
# Increment version |
|
new_version = str(int(version_num) + 1).zfill(len(version_num)) |
|
new_file_name = f"{base_name}_v{new_version}.{ext}" |
|
|
|
# Join to get new path |
|
new_path = f"{directory}/{new_file_name}" |
|
return new_path |
|
|
|
return file_path |
|
|
|
current_path = cmds.file(q=True, sn=True) |
|
new_path = increment_version(current_path) |
|
cmds.file(rename=new_path) |
|
cmds.file(save=True)</code></pre> |
|
</div> |
|
</div> |
|
</section> |
|
</main> |
|
|
|
<footer class="mt-12 text-center text-gray-500 text-sm"> |
|
<p>Interactive Python String Methods for Autodesk Maya</p> |
|
<p class="mt-2">Use these examples in Maya's Script Editor for practical applications</p> |
|
</footer> |
|
|
|
<script> |
|
|
|
function concatStrings() { |
|
const str1 = document.getElementById('concat-input1').value; |
|
const str2 = document.getElementById('concat-input2').value; |
|
const result = str1 + str2; |
|
|
|
const resultBox = document.getElementById('concat-result'); |
|
resultBox.innerHTML = `Combined string: "${result}"<br>Python: str1 + str2`; |
|
} |
|
|
|
function indexString() { |
|
const str = document.getElementById('index-input').value; |
|
const index = parseInt(document.getElementById('index-position').value); |
|
|
|
const resultBox = document.getElementById('index-result'); |
|
|
|
if (index < 0 || index >= str.length) { |
|
resultBox.innerHTML = `Error: Index ${index} is out of range (0 to ${str.length - 1})`; |
|
return; |
|
} |
|
|
|
const result = str[index]; |
|
resultBox.innerHTML = `Character at index ${index}: "${result}"<br>Python: str[${index}]`; |
|
} |
|
|
|
function sliceString() { |
|
const str = document.getElementById('slice-input').value; |
|
const start = parseInt(document.getElementById('slice-start').value); |
|
const end = parseInt(document.getElementById('slice-end').value); |
|
|
|
const resultBox = document.getElementById('slice-result'); |
|
|
|
if (start < 0 || start > str.length) { |
|
resultBox.innerHTML = `Error: Start index ${start} is out of range (0 to ${str.length})`; |
|
return; |
|
} |
|
|
|
if (end < start || end > str.length) { |
|
resultBox.innerHTML = `Error: End index ${end} is invalid (should be between ${start} and ${str.length})`; |
|
return; |
|
} |
|
|
|
const result = str.slice(start, end); |
|
resultBox.innerHTML = `Slice from index ${start} to ${end}: "${result}"<br>Python: str[${start}:${end}]`; |
|
} |
|
|
|
|
|
function upperCaseString() { |
|
const str = document.getElementById('upper-input').value; |
|
const result = str.toUpperCase(); |
|
|
|
const resultBox = document.getElementById('upper-result'); |
|
resultBox.innerHTML = `Uppercase: "${result}"<br>Python: str.upper()`; |
|
} |
|
|
|
function lowerCaseString() { |
|
const str = document.getElementById('lower-input').value; |
|
const result = str.toLowerCase(); |
|
|
|
const resultBox = document.getElementById('lower-result'); |
|
resultBox.innerHTML = `Lowercase: "${result}"<br>Python: str.lower()`; |
|
} |
|
|
|
function titleCaseString() { |
|
const str = document.getElementById('title-input').value; |
|
|
|
const result = str.toLowerCase().replace(/(?:^|\s)\S/g, function(a) { |
|
return a.toUpperCase(); |
|
}); |
|
|
|
const resultBox = document.getElementById('title-result'); |
|
resultBox.innerHTML = `Title case: "${result}"<br>Python: str.title()`; |
|
} |
|
|
|
function capitalizeString() { |
|
const str = document.getElementById('capitalize-input').value; |
|
|
|
const result = str.charAt(0).toUpperCase() + str.slice(1).toLowerCase(); |
|
|
|
const resultBox = document.getElementById('capitalize-result'); |
|
resultBox.innerHTML = `Capitalized: "${result}"<br>Python: str.capitalize()`; |
|
} |
|
|
|
|
|
function findInString() { |
|
const str = document.getElementById('find-input').value; |
|
const substr = document.getElementById('find-substring').value; |
|
const result = str.indexOf(substr); |
|
|
|
const resultBox = document.getElementById('find-result'); |
|
if (result === -1) { |
|
resultBox.innerHTML = `Substring "${substr}" not found.<br>Python: str.find("${substr}") returned -1`; |
|
} else { |
|
resultBox.innerHTML = `Substring "${substr}" found at index ${result}.<br>Python: str.find("${substr}")`; |
|
} |
|
} |
|
|
|
function checkStartsWith() { |
|
const str = document.getElementById('startswith-input').value; |
|
const prefix = document.getElementById('startswith-prefix').value; |
|
const result = str.startsWith(prefix); |
|
|
|
const resultBox = document.getElementById('startswith-result'); |
|
resultBox.innerHTML = `Does "${str}" start with "${prefix}"? ${result}<br>Python: str.startswith("${prefix}")`; |
|
} |
|
|
|
function checkEndsWith() { |
|
const str = document.getElementById('endswith-input').value; |
|
const suffix = document.getElementById('endswith-suffix').value; |
|
const result = str.endsWith(suffix); |
|
|
|
const resultBox = document.getElementById('endswith-result'); |
|
resultBox.innerHTML = `Does "${str}" end with "${suffix}"? ${result}<br>Python: str.endswith("${suffix}")`; |
|
} |
|
|
|
|
|
function replaceInString() { |
|
const str = document.getElementById('replace-input').value; |
|
const oldText = document.getElementById('replace-old').value; |
|
const newText = document.getElementById('replace-new').value; |
|
const result = str.replace(oldText, newText); |
|
|
|
const resultBox = document.getElementById('replace-result'); |
|
resultBox.innerHTML = `Result: "${result}"<br>Python: str.replace("${oldText}", "${newText}")`; |
|
} |
|
|
|
function stripString() { |
|
const str = document.getElementById('strip-input').value; |
|
const chars = document.getElementById('strip-chars').value; |
|
|
|
let result; |
|
if (chars) { |
|
|
|
let startIndex = 0; |
|
let endIndex = str.length - 1; |
|
|
|
|
|
while (startIndex <= endIndex && chars.includes(str[startIndex])) { |
|
startIndex++; |
|
} |
|
|
|
|
|
while (endIndex >= startIndex && chars.includes(str[endIndex])) { |
|
endIndex--; |
|
} |
|
|
|
result = str.slice(startIndex, endIndex + 1); |
|
} else { |
|
result = str.trim(); |
|
} |
|
|
|
const resultBox = document.getElementById('strip-result'); |
|
if (chars) { |
|
resultBox.innerHTML = `Result: "${result}"<br>Python: str.strip("${chars}")`; |
|
} else { |
|
resultBox.innerHTML = `Result: "${result}"<br>Python: str.strip()`; |
|
} |
|
} |
|
|
|
function splitString() { |
|
const str = document.getElementById('split-input').value; |
|
const delimiter = document.getElementById('split-delimiter').value; |
|
const result = str.split(delimiter); |
|
|
|
const resultBox = document.getElementById('split-result'); |
|
resultBox.innerHTML = `Split into list: [${result.map(item => `"${item}"`).join(', ')}]<br>Python: str.split("${delimiter}")`; |
|
} |
|
|
|
function joinStrings() { |
|
const strList = document.getElementById('join-input').value.split(','); |
|
const joinChar = document.getElementById('join-char').value; |
|
const result = strList.join(joinChar); |
|
|
|
const resultBox = document.getElementById('join-result'); |
|
resultBox.innerHTML = `Joined string: "${result}"<br>Python: "${joinChar}".join([${strList.map(item => `"${item}"`).join(', ')}])`; |
|
} |
|
|
|
|
|
function generateNodeName() { |
|
const prefix = document.getElementById('node-prefix').value; |
|
const bodyPart = document.getElementById('node-bodypart').value; |
|
const index = document.getElementById('node-index').value; |
|
const type = document.getElementById('node-type').value; |
|
|
|
|
|
const formattedIndex = index < 10 ? `0${index}` : index; |
|
|
|
const nodeName = `${prefix}${bodyPart}${formattedIndex}${type}`; |
|
|
|
const resultBox = document.getElementById('maya-naming-result'); |
|
resultBox.innerHTML = `Maya node name: "${nodeName}"<br>Python: f"{prefix}{bodyPart}{str(index).zfill(2)}{type}"`; |
|
} |
|
|
|
function analyzeFilePath() { |
|
const filePath = document.getElementById('filepath-input').value; |
|
|
|
|
|
const normalizedPath = filePath.replace(/\\/g, '/'); |
|
|
|
|
|
const lastSlashIndex = normalizedPath.lastIndexOf('/'); |
|
const directory = normalizedPath.substring(0, lastSlashIndex); |
|
const filename = normalizedPath.substring(lastSlashIndex + 1); |
|
|
|
|
|
const lastDotIndex = filename.lastIndexOf('.'); |
|
const basename = filename.substring(0, lastDotIndex); |
|
const extension = filename.substring(lastDotIndex + 1); |
|
|
|
|
|
let version = "None"; |
|
let versionNumber = "None"; |
|
let basePart = basename; |
|
|
|
const versionMatch = basename.match(/(.*)_v(\d+)$/); |
|
if (versionMatch) { |
|
basePart = versionMatch[1]; |
|
version = `v${versionMatch[2]}`; |
|
versionNumber = versionMatch[2]; |
|
} |
|
|
|
|
|
let nextVersion = "None"; |
|
if (versionNumber !== "None") { |
|
const numDigits = versionNumber.length; |
|
const nextNum = parseInt(versionNumber) + 1; |
|
nextVersion = `v${nextNum.toString().padStart(numDigits, '0')}`; |
|
} |
|
|
|
|
|
let nextVersionPath = "None"; |
|
if (nextVersion !== "None") { |
|
nextVersionPath = `${directory}/${basePart}_${nextVersion}.${extension}`; |
|
} |
|
|
|
const resultBox = document.getElementById('filepath-result'); |
|
resultBox.innerHTML = `Directory: ${directory} |
|
Filename: ${filename} |
|
Base Name: ${basename} |
|
Extension: ${extension} |
|
Clean Base: ${basePart} |
|
Version: ${version} |
|
Next Version: ${nextVersion} |
|
Next Path: ${nextVersionPath} |
|
|
|
# Python in Maya: |
|
directory = "${directory}" |
|
filename = "${filename}" |
|
basename = "${basename}" |
|
extension = "${extension}" |
|
clean_base = "${basePart}" |
|
version = "${version}" |
|
next_version = "${nextVersion}" |
|
next_path = "${nextVersionPath}"`; |
|
} |
|
|
|
|
|
document.addEventListener('DOMContentLoaded', function() { |
|
concatStrings(); |
|
indexString(); |
|
sliceString(); |
|
upperCaseString(); |
|
lowerCaseString(); |
|
titleCaseString(); |
|
capitalizeString(); |
|
findInString(); |
|
checkStartsWith(); |
|
checkEndsWith(); |
|
replaceInString(); |
|
stripString(); |
|
splitString(); |
|
joinStrings(); |
|
generateNodeName(); |
|
analyzeFilePath(); |
|
}); |
|
</script> |
|
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=subbuadd/pystrings" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> |
|
</html> |
|
|